diff options
author | Eric Garver <e@erig.me> | 2017-03-01 17:47:59 -0500 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2017-03-16 15:18:40 -0700 |
commit | f0fb825a3785320430686834741c718ff4f8ebf4 (patch) | |
tree | e58d08de18a42bd74edbed5a9c0d8951d03e7d81 /lib/flow.h | |
parent | 4c71600d2256641b927e04b75e95751355e799f8 (diff) | |
download | openvswitch-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.h | 36 |
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) |