summaryrefslogtreecommitdiff
path: root/lib/flow.h
diff options
context:
space:
mode:
authorEric Garver <e@erig.me>2017-03-01 17:47:59 -0500
committerBen Pfaff <blp@ovn.org>2017-03-16 15:18:40 -0700
commitf0fb825a3785320430686834741c718ff4f8ebf4 (patch)
treee58d08de18a42bd74edbed5a9c0d8951d03e7d81 /lib/flow.h
parent4c71600d2256641b927e04b75e95751355e799f8 (diff)
downloadopenvswitch-f0fb825a3785320430686834741c718ff4f8ebf4.tar.gz
Add support for 802.1ad (QinQ tunneling)
Flow key handling changes: - Add VLAN header array in struct flow, to record multiple 802.1q VLAN headers. - Add dpif multi-VLAN capability probing. If datapath supports multi-VLAN, increase the maximum depth of nested OVS_KEY_ATTR_ENCAP. Refactor VLAN handling in dpif-xlate: - Introduce 'xvlan' to track VLAN stack during flow processing. - Input and output VLAN translation according to the xbundle type. Push VLAN action support: - Allow ethertype 0x88a8 in VLAN headers and push_vlan action. - Support push_vlan on dot1q packets. Use other_config:vlan-limit in table Open_vSwitch to limit maximum VLANs that can be matched. This allows us to preserve backwards compatibility. Add test cases for VLAN depth limit, Multi-VLAN actions and QinQ VLAN handling Co-authored-by: Thomas F Herbert <thomasfherbert@gmail.com> Signed-off-by: Thomas F Herbert <thomasfherbert@gmail.com> Co-authored-by: Xiao Liang <shaw.leon@gmail.com> Signed-off-by: Xiao Liang <shaw.leon@gmail.com> Signed-off-by: Eric Garver <e@erig.me> Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'lib/flow.h')
-rw-r--r--lib/flow.h36
1 files changed, 26 insertions, 10 deletions
diff --git a/lib/flow.h b/lib/flow.h
index 14a30041e..86b52584b 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -53,6 +53,9 @@ struct match;
extern const uint8_t flow_segment_u64s[];
+/* Configured maximum VLAN headers. */
+extern int flow_vlan_limit;
+
#define FLOW_U64_OFFSET(FIELD) \
(offsetof(struct flow, FIELD) / sizeof(uint64_t))
#define FLOW_U64_OFFREM(FIELD) \
@@ -87,9 +90,17 @@ 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_fix_vlan_tpid(struct flow *);
void flow_set_vlan_vid(struct flow *, ovs_be16 vid);
void flow_set_vlan_pcp(struct flow *, uint8_t pcp);
+void flow_limit_vlans(int vlan_limit);
+int flow_count_vlan_headers(const struct flow *);
+void flow_skip_common_vlan_headers(const struct flow *a, int *p_an,
+ const struct flow *b, int *p_bn);
+void flow_pop_vlan(struct flow*, struct flow_wildcards*);
+void flow_push_vlan_uninit(struct flow*, struct flow_wildcards*);
+
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,
@@ -694,7 +705,7 @@ static inline uint32_t miniflow_get_u32(const struct miniflow *,
unsigned int u32_ofs);
static inline ovs_be32 miniflow_get_be32(const struct miniflow *,
unsigned int be32_ofs);
-static inline uint16_t miniflow_get_vid(const struct miniflow *);
+static inline uint16_t miniflow_get_vid(const struct miniflow *, size_t);
static inline uint16_t miniflow_get_tcp_flags(const struct miniflow *);
static inline ovs_be64 miniflow_get_metadata(const struct miniflow *);
@@ -732,7 +743,7 @@ static inline uint32_t minimask_get_u32(const struct minimask *,
unsigned int u32_ofs);
static inline ovs_be32 minimask_get_be32(const struct minimask *,
unsigned int be32_ofs);
-static inline uint16_t minimask_get_vid_mask(const struct minimask *);
+static inline uint16_t minimask_get_vid_mask(const struct minimask *, size_t);
static inline ovs_be64 minimask_get_metadata_mask(const struct minimask *);
bool minimask_equal(const struct minimask *a, const struct minimask *b);
@@ -779,10 +790,15 @@ static inline ovs_be32 miniflow_get_be32(const struct miniflow *flow,
/* Returns the VID within the vlan_tci member of the "struct flow" represented
* by 'flow'. */
static inline uint16_t
-miniflow_get_vid(const struct miniflow *flow)
+miniflow_get_vid(const struct miniflow *flow, size_t n)
{
- ovs_be16 tci = MINIFLOW_GET_BE16(flow, vlan_tci);
- return vlan_tci_to_vid(tci);
+ if (n < FLOW_MAX_VLAN_HEADERS) {
+ union flow_vlan_hdr hdr = {
+ .qtag = MINIFLOW_GET_BE32(flow, vlans[n])
+ };
+ return vlan_tci_to_vid(hdr.tci);
+ }
+ return 0;
}
/* Returns the uint32_t that would be at byte offset '4 * u32_ofs' if 'mask'
@@ -802,9 +818,9 @@ minimask_get_be32(const struct minimask *mask, unsigned int be32_ofs)
/* Returns the VID mask within the vlan_tci member of the "struct
* flow_wildcards" represented by 'mask'. */
static inline uint16_t
-minimask_get_vid_mask(const struct minimask *mask)
+minimask_get_vid_mask(const struct minimask *mask, size_t n)
{
- return miniflow_get_vid(&mask->masks);
+ return miniflow_get_vid(&mask->masks, n);
}
/* Returns the value of the "tcp_flags" field in 'flow'. */
@@ -889,7 +905,7 @@ static inline void
pkt_metadata_from_flow(struct pkt_metadata *md, const struct flow *flow)
{
/* Update this function whenever struct flow changes. */
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 37);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 38);
md->recirc_id = flow->recirc_id;
md->dp_hash = flow->dp_hash;
@@ -938,9 +954,9 @@ static inline bool is_vlan(const struct flow *flow,
struct flow_wildcards *wc)
{
if (wc) {
- WC_MASK_FIELD_MASK(wc, vlan_tci, htons(VLAN_CFI));
+ WC_MASK_FIELD_MASK(wc, vlans[0].tci, htons(VLAN_CFI));
}
- return (flow->vlan_tci & htons(VLAN_CFI)) != 0;
+ return (flow->vlans[0].tci & htons(VLAN_CFI)) != 0;
}
static inline bool is_ip_any(const struct flow *flow)