2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 14:25:26 +00:00

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>
This commit is contained in:
Eric Garver
2017-03-01 17:47:59 -05:00
committed by Ben Pfaff
parent 4c71600d22
commit f0fb825a37
33 changed files with 1109 additions and 577 deletions

View File

@@ -1408,6 +1408,7 @@ dpctl_normalize_actions(int argc, const char *argv[],
struct ds s;
int left;
int i, error;
int encaps = 0;
ds_init(&s);
@@ -1464,12 +1465,14 @@ dpctl_normalize_actions(int argc, const char *argv[],
const struct ovs_action_push_vlan *push;
switch(nl_attr_type(a)) {
case OVS_ACTION_ATTR_POP_VLAN:
flow.vlan_tci = htons(0);
flow_pop_vlan(&flow, NULL);
continue;
case OVS_ACTION_ATTR_PUSH_VLAN:
flow_push_vlan_uninit(&flow, NULL);
push = nl_attr_get_unspec(a, sizeof *push);
flow.vlan_tci = push->vlan_tci;
flow.vlans[0].tpid = push->vlan_tpid;
flow.vlans[0].tci = push->vlan_tci;
continue;
}
@@ -1495,12 +1498,22 @@ dpctl_normalize_actions(int argc, const char *argv[],
sort_output_actions(af->actions.data, af->actions.size);
if (af->flow.vlan_tci != htons(0)) {
dpctl_print(dpctl_p, "vlan(vid=%"PRIu16",pcp=%d): ",
vlan_tci_to_vid(af->flow.vlan_tci),
vlan_tci_to_pcp(af->flow.vlan_tci));
} else {
dpctl_print(dpctl_p, "no vlan: ");
for (encaps = 0; encaps < FLOW_MAX_VLAN_HEADERS; encaps ++) {
union flow_vlan_hdr *vlan = &af->flow.vlans[encaps];
if (vlan->tci != htons(0)) {
dpctl_print(dpctl_p, "vlan(");
if (vlan->tpid != htons(ETH_TYPE_VLAN)) {
dpctl_print(dpctl_p, "tpid=0x%04"PRIx16",", vlan->tpid);
}
dpctl_print(dpctl_p, "vid=%"PRIu16",pcp=%d): ",
vlan_tci_to_vid(vlan->tci),
vlan_tci_to_pcp(vlan->tci));
} else {
if (encaps == 0) {
dpctl_print(dpctl_p, "no vlan: ");
}
break;
}
}
if (eth_type_mpls(af->flow.dl_type)) {