mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 01:51:26 +00:00
Add new port VLAN mode "dot1q-tunnel"
- Example: ovs-vsctl set Port p1 vlan_mode=dot1q-tunnel tag=100 Pushes another VLAN 100 header on packets (tagged and untagged) on ingress, and pops it on egress. - Customer VLAN check: ovs-vsctl set Port p1 vlan_mode=dot1q-tunnel tag=100 cvlans=10,20 Only customer VLAN of 10 and 20 are allowed. 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:
parent
cc3ef00887
commit
fed8962aff
3
NEWS
3
NEWS
@ -11,7 +11,8 @@ Post-v2.7.0
|
||||
'ovs-appctl vlog' commands for 'dpdk' module. Lower bound
|
||||
still can be configured via extra arguments for DPDK EAL.
|
||||
- The "learn" action now supports a "limit" option (see ovs-ofctl(8)).
|
||||
- New support for multiple VLANs (802.1ad or "QinQ").
|
||||
- New support for multiple VLANs (802.1ad or "QinQ"), including a new
|
||||
"dot1q-tunnel" port VLAN mode.
|
||||
|
||||
v2.7.0 - 21 Feb 2017
|
||||
---------------------
|
||||
|
@ -127,9 +127,13 @@ struct xbundle {
|
||||
struct lacp *lacp; /* LACP handle or null. */
|
||||
|
||||
enum port_vlan_mode vlan_mode; /* VLAN mode. */
|
||||
uint16_t qinq_ethtype; /* Ethertype of dot1q-tunnel interface
|
||||
* either 0x8100 or 0x88a8. */
|
||||
int vlan; /* -1=trunk port, else a 12-bit VLAN ID. */
|
||||
unsigned long *trunks; /* Bitmap of trunked VLANs, if 'vlan' == -1.
|
||||
* NULL if all VLANs are trunked. */
|
||||
unsigned long *cvlans; /* Bitmap of allowed customer vlans,
|
||||
* NULL if all VLANs are allowed */
|
||||
bool use_priority_tags; /* Use 802.1p tag for frames in VLAN 0? */
|
||||
bool floodable; /* No port has OFPUTIL_PC_NO_FLOOD set? */
|
||||
bool protected; /* Protected port mode */
|
||||
@ -499,6 +503,7 @@ static bool input_vid_is_valid(const struct xlate_ctx *,
|
||||
uint16_t vid, struct xbundle *);
|
||||
static void xvlan_copy(struct xvlan *dst, const struct xvlan *src);
|
||||
static void xvlan_pop(struct xvlan *src);
|
||||
static void xvlan_push_uninit(struct xvlan *src);
|
||||
static void xvlan_extract(const struct flow *, struct xvlan *);
|
||||
static void xvlan_put(struct flow *, const struct xvlan *);
|
||||
static void xvlan_input_translate(const struct xbundle *,
|
||||
@ -550,8 +555,8 @@ static void xlate_xbridge_set(struct xbridge *, struct dpif *,
|
||||
const struct dpif_backer_support *);
|
||||
static void xlate_xbundle_set(struct xbundle *xbundle,
|
||||
enum port_vlan_mode vlan_mode,
|
||||
int vlan,
|
||||
unsigned long *trunks,
|
||||
uint16_t qinq_ethtype, int vlan,
|
||||
unsigned long *trunks, unsigned long *cvlans,
|
||||
bool use_priority_tags,
|
||||
const struct bond *bond, const struct lacp *lacp,
|
||||
bool floodable, bool protected);
|
||||
@ -857,8 +862,8 @@ xlate_xbridge_set(struct xbridge *xbridge,
|
||||
|
||||
static void
|
||||
xlate_xbundle_set(struct xbundle *xbundle,
|
||||
enum port_vlan_mode vlan_mode,
|
||||
int vlan, unsigned long *trunks,
|
||||
enum port_vlan_mode vlan_mode, uint16_t qinq_ethtype,
|
||||
int vlan, unsigned long *trunks, unsigned long *cvlans,
|
||||
bool use_priority_tags,
|
||||
const struct bond *bond, const struct lacp *lacp,
|
||||
bool floodable, bool protected)
|
||||
@ -866,8 +871,10 @@ xlate_xbundle_set(struct xbundle *xbundle,
|
||||
ovs_assert(xbundle->xbridge);
|
||||
|
||||
xbundle->vlan_mode = vlan_mode;
|
||||
xbundle->qinq_ethtype = qinq_ethtype;
|
||||
xbundle->vlan = vlan;
|
||||
xbundle->trunks = trunks;
|
||||
xbundle->cvlans = cvlans;
|
||||
xbundle->use_priority_tags = use_priority_tags;
|
||||
xbundle->floodable = floodable;
|
||||
xbundle->protected = protected;
|
||||
@ -962,8 +969,8 @@ xlate_xbundle_copy(struct xbridge *xbridge, struct xbundle *xbundle)
|
||||
new_xbundle->name = xstrdup(xbundle->name);
|
||||
xlate_xbundle_init(new_xcfg, new_xbundle);
|
||||
|
||||
xlate_xbundle_set(new_xbundle, xbundle->vlan_mode,
|
||||
xbundle->vlan, xbundle->trunks,
|
||||
xlate_xbundle_set(new_xbundle, xbundle->vlan_mode, xbundle->qinq_ethtype,
|
||||
xbundle->vlan, xbundle->trunks, xbundle->cvlans,
|
||||
xbundle->use_priority_tags, xbundle->bond, xbundle->lacp,
|
||||
xbundle->floodable, xbundle->protected);
|
||||
LIST_FOR_EACH (xport, bundle_node, &xbundle->xports) {
|
||||
@ -1157,8 +1164,8 @@ xlate_remove_ofproto(struct ofproto_dpif *ofproto)
|
||||
void
|
||||
xlate_bundle_set(struct ofproto_dpif *ofproto, struct ofbundle *ofbundle,
|
||||
const char *name, enum port_vlan_mode vlan_mode,
|
||||
int vlan,
|
||||
unsigned long *trunks,
|
||||
uint16_t qinq_ethtype, int vlan,
|
||||
unsigned long *trunks, unsigned long *cvlans,
|
||||
bool use_priority_tags,
|
||||
const struct bond *bond, const struct lacp *lacp,
|
||||
bool floodable, bool protected)
|
||||
@ -1179,7 +1186,7 @@ xlate_bundle_set(struct ofproto_dpif *ofproto, struct ofbundle *ofbundle,
|
||||
free(xbundle->name);
|
||||
xbundle->name = xstrdup(name);
|
||||
|
||||
xlate_xbundle_set(xbundle, vlan_mode, vlan, trunks,
|
||||
xlate_xbundle_set(xbundle, vlan_mode, qinq_ethtype, vlan, trunks, cvlans,
|
||||
use_priority_tags, bond, lacp, floodable, protected);
|
||||
}
|
||||
|
||||
@ -1700,6 +1707,12 @@ xbundle_trunks_vlan(const struct xbundle *bundle, uint16_t vlan)
|
||||
&& (!bundle->trunks || bitmap_is_set(bundle->trunks, vlan)));
|
||||
}
|
||||
|
||||
static bool
|
||||
xbundle_allows_cvlan(const struct xbundle *bundle, uint16_t vlan)
|
||||
{
|
||||
return (!bundle->cvlans || bitmap_is_set(bundle->cvlans, vlan));
|
||||
}
|
||||
|
||||
static bool
|
||||
xbundle_includes_vlan(const struct xbundle *xbundle, const struct xvlan *xvlan)
|
||||
{
|
||||
@ -1712,6 +1725,10 @@ xbundle_includes_vlan(const struct xbundle *xbundle, const struct xvlan *xvlan)
|
||||
case PORT_VLAN_NATIVE_TAGGED:
|
||||
return xbundle_trunks_vlan(xbundle, xvlan->v[0].vid);
|
||||
|
||||
case PORT_VLAN_DOT1Q_TUNNEL:
|
||||
return xvlan->v[0].vid == xbundle->vlan &&
|
||||
xbundle_allows_cvlan(xbundle, xvlan->v[1].vid);
|
||||
|
||||
default:
|
||||
OVS_NOT_REACHED();
|
||||
}
|
||||
@ -1948,6 +1965,15 @@ input_vid_is_valid(const struct xlate_ctx *ctx,
|
||||
}
|
||||
return true;
|
||||
|
||||
case PORT_VLAN_DOT1Q_TUNNEL:
|
||||
if (!xbundle_allows_cvlan(in_xbundle, vid)) {
|
||||
xlate_report_error(ctx, "dropping VLAN %"PRIu16" packet received "
|
||||
"on dot1q-tunnel port %s that excludes this "
|
||||
"VLAN", vid, in_xbundle->name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
OVS_NOT_REACHED();
|
||||
}
|
||||
@ -1968,6 +1994,13 @@ xvlan_pop(struct xvlan *src)
|
||||
sizeof(src->v[FLOW_MAX_VLAN_HEADERS - 1]));
|
||||
}
|
||||
|
||||
static void
|
||||
xvlan_push_uninit(struct xvlan *src)
|
||||
{
|
||||
memmove(&src->v[1], &src->v[0], sizeof(src->v) - sizeof(src->v[0]));
|
||||
memset(&src->v[0], 0, sizeof(src->v[0]));
|
||||
}
|
||||
|
||||
/* Extract VLAN information (headers) from flow */
|
||||
static void
|
||||
xvlan_extract(const struct flow *flow, struct xvlan *xvlan)
|
||||
@ -2035,6 +2068,14 @@ xvlan_input_translate(const struct xbundle *in_xbundle,
|
||||
}
|
||||
break;
|
||||
|
||||
case PORT_VLAN_DOT1Q_TUNNEL:
|
||||
xvlan_copy(xvlan, in_xvlan);
|
||||
xvlan_push_uninit(xvlan);
|
||||
xvlan->v[0].tpid = in_xbundle->qinq_ethtype;
|
||||
xvlan->v[0].vid = in_xbundle->vlan;
|
||||
xvlan->v[0].pcp = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
OVS_NOT_REACHED();
|
||||
}
|
||||
@ -2064,11 +2105,26 @@ xvlan_output_translate(const struct xbundle *out_xbundle,
|
||||
}
|
||||
break;
|
||||
|
||||
case PORT_VLAN_DOT1Q_TUNNEL:
|
||||
xvlan_copy(out_xvlan, xvlan);
|
||||
xvlan_pop(out_xvlan);
|
||||
break;
|
||||
|
||||
default:
|
||||
OVS_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
/* If output xbundle is dot1q-tunnel, set mask bits of cvlan */
|
||||
static void
|
||||
check_and_set_cvlan_mask(struct flow_wildcards *wc,
|
||||
const struct xbundle *xbundle)
|
||||
{
|
||||
if (xbundle->vlan_mode == PORT_VLAN_DOT1Q_TUNNEL && xbundle->cvlans) {
|
||||
wc->masks.vlans[1].tci = htons(0xffff);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle,
|
||||
const struct xvlan *xvlan)
|
||||
@ -2080,6 +2136,8 @@ output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle,
|
||||
bool use_recirc = false;
|
||||
struct xvlan out_xvlan;
|
||||
|
||||
check_and_set_cvlan_mask(ctx->wc, out_xbundle);
|
||||
|
||||
xvlan_output_translate(out_xbundle, xvlan, &out_xvlan);
|
||||
if (out_xbundle->use_priority_tags) {
|
||||
out_xvlan.v[0].pcp = ntohs(ctx->xin->flow.vlans[0].tci) &
|
||||
|
@ -168,8 +168,8 @@ void xlate_remove_ofproto(struct ofproto_dpif *);
|
||||
|
||||
void xlate_bundle_set(struct ofproto_dpif *, struct ofbundle *,
|
||||
const char *name, enum port_vlan_mode,
|
||||
int vlan,
|
||||
unsigned long *trunks,
|
||||
uint16_t qinq_ethtype, int vlan,
|
||||
unsigned long *trunks, unsigned long *cvlans,
|
||||
bool use_priority_tags,
|
||||
const struct bond *, const struct lacp *,
|
||||
bool floodable, bool protected);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
|
||||
* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Nicira, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -94,9 +94,11 @@ struct ofbundle {
|
||||
/* Configuration. */
|
||||
struct ovs_list ports; /* Contains "struct ofport"s. */
|
||||
enum port_vlan_mode vlan_mode; /* VLAN mode */
|
||||
uint16_t qinq_ethtype;
|
||||
int vlan; /* -1=trunk port, else a 12-bit VLAN ID. */
|
||||
unsigned long *trunks; /* Bitmap of trunked VLANs, if 'vlan' == -1.
|
||||
* NULL if all VLANs are trunked. */
|
||||
unsigned long *cvlans;
|
||||
struct lacp *lacp; /* LACP if LACP is enabled, otherwise NULL. */
|
||||
struct bond *bond; /* Nonnull iff more than one port. */
|
||||
bool use_priority_tags; /* Use 802.1p tag for frames in VLAN 0? */
|
||||
@ -449,8 +451,8 @@ type_run(const char *type)
|
||||
|
||||
HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) {
|
||||
xlate_bundle_set(ofproto, bundle, bundle->name,
|
||||
bundle->vlan_mode,
|
||||
bundle->vlan, bundle->trunks,
|
||||
bundle->vlan_mode, bundle->qinq_ethtype,
|
||||
bundle->vlan, bundle->trunks, bundle->cvlans,
|
||||
bundle->use_priority_tags,
|
||||
bundle->bond, bundle->lacp,
|
||||
bundle->floodable, bundle->protected);
|
||||
@ -2857,6 +2859,7 @@ bundle_destroy(struct ofbundle *bundle)
|
||||
hmap_remove(&ofproto->bundles, &bundle->hmap_node);
|
||||
free(bundle->name);
|
||||
free(bundle->trunks);
|
||||
free(bundle->cvlans);
|
||||
lacp_unref(bundle->lacp);
|
||||
bond_unref(bundle->bond);
|
||||
free(bundle);
|
||||
@ -2871,6 +2874,7 @@ bundle_set(struct ofproto *ofproto_, void *aux,
|
||||
struct ofport_dpif *port;
|
||||
struct ofbundle *bundle;
|
||||
unsigned long *trunks = NULL;
|
||||
unsigned long *cvlans = NULL;
|
||||
int vlan;
|
||||
size_t i;
|
||||
bool ok;
|
||||
@ -2895,8 +2899,10 @@ bundle_set(struct ofproto *ofproto_, void *aux,
|
||||
|
||||
ovs_list_init(&bundle->ports);
|
||||
bundle->vlan_mode = PORT_VLAN_TRUNK;
|
||||
bundle->qinq_ethtype = ETH_TYPE_VLAN_8021AD;
|
||||
bundle->vlan = -1;
|
||||
bundle->trunks = NULL;
|
||||
bundle->cvlans = NULL;
|
||||
bundle->use_priority_tags = s->use_priority_tags;
|
||||
bundle->lacp = NULL;
|
||||
bundle->bond = NULL;
|
||||
@ -2961,6 +2967,11 @@ bundle_set(struct ofproto *ofproto_, void *aux,
|
||||
need_flush = true;
|
||||
}
|
||||
|
||||
if (s->qinq_ethtype != bundle->qinq_ethtype) {
|
||||
bundle->qinq_ethtype = s->qinq_ethtype;
|
||||
need_flush = true;
|
||||
}
|
||||
|
||||
/* Set VLAN tag. */
|
||||
vlan = (s->vlan_mode == PORT_VLAN_TRUNK ? -1
|
||||
: s->vlan >= 0 && s->vlan <= 4095 ? s->vlan
|
||||
@ -2998,6 +3009,10 @@ bundle_set(struct ofproto *ofproto_, void *aux,
|
||||
}
|
||||
break;
|
||||
|
||||
case PORT_VLAN_DOT1Q_TUNNEL:
|
||||
cvlans = CONST_CAST(unsigned long *, s->cvlans);
|
||||
break;
|
||||
|
||||
default:
|
||||
OVS_NOT_REACHED();
|
||||
}
|
||||
@ -3015,6 +3030,20 @@ bundle_set(struct ofproto *ofproto_, void *aux,
|
||||
free(trunks);
|
||||
}
|
||||
|
||||
if (!vlan_bitmap_equal(cvlans, bundle->cvlans)) {
|
||||
free(bundle->cvlans);
|
||||
if (cvlans == s->cvlans) {
|
||||
bundle->cvlans = vlan_bitmap_clone(cvlans);
|
||||
} else {
|
||||
bundle->cvlans = cvlans;
|
||||
cvlans = NULL;
|
||||
}
|
||||
need_flush = true;
|
||||
}
|
||||
if (cvlans != s->cvlans) {
|
||||
free(cvlans);
|
||||
}
|
||||
|
||||
/* Bonding. */
|
||||
if (!ovs_list_is_short(&bundle->ports)) {
|
||||
bundle->ofproto->has_bonded_bundles = true;
|
||||
|
@ -388,7 +388,11 @@ enum port_vlan_mode {
|
||||
/* Untagged incoming packets are part of 'vlan', as are incoming packets
|
||||
* tagged with 'vlan'. Outgoing packets tagged with 'vlan' are untagged.
|
||||
* Other VLANs in 'trunks' are trunked. */
|
||||
PORT_VLAN_NATIVE_UNTAGGED
|
||||
PORT_VLAN_NATIVE_UNTAGGED,
|
||||
|
||||
/* 802.1q tunnel port. Incoming packets are added an outer vlan tag
|
||||
* 'vlan'. If 'cvlans' is set, only allows VLANs in 'cvlans'. */
|
||||
PORT_VLAN_DOT1Q_TUNNEL
|
||||
};
|
||||
|
||||
/* Configuration of bundles. */
|
||||
@ -399,8 +403,10 @@ struct ofproto_bundle_settings {
|
||||
size_t n_slaves;
|
||||
|
||||
enum port_vlan_mode vlan_mode; /* Selects mode for vlan and trunks */
|
||||
uint16_t qinq_ethtype;
|
||||
int vlan; /* VLAN VID, except for PORT_VLAN_TRUNK. */
|
||||
unsigned long *trunks; /* vlan_bitmap, except for PORT_VLAN_ACCESS. */
|
||||
unsigned long *cvlans;
|
||||
bool use_priority_tags; /* Use 802.1p tag for frames in VLAN 0? */
|
||||
|
||||
struct bond_settings *bond; /* Must be nonnull iff if n_slaves > 1. */
|
||||
|
@ -3182,6 +3182,11 @@ OVS_VSWITCHD_START(
|
||||
add-port br0 p7 vlan_mode=native-untagged tag=12 -- \
|
||||
add-port br0 p8 vlan_mode=native-untagged tag=12 trunks=10,12 \
|
||||
other-config:priority-tags=true -- \
|
||||
add-port br0 p9 vlan_mode=dot1q-tunnel tag=10 other-config:qinq-ethtype=802.1q -- \
|
||||
add-port br0 p10 vlan_mode=dot1q-tunnel tag=10 cvlans=10,12 other-config:qinq-ethtype=802.1q -- \
|
||||
add-port br0 p11 vlan_mode=dot1q-tunnel tag=12 other-config:qinq-ethtype=802.1q -- \
|
||||
add-port br0 p12 vlan_mode=dot1q-tunnel tag=12 other-config:qinq-ethtype=802.1q \
|
||||
other-config:priority-tags=true -- \
|
||||
set Interface p1 type=dummy -- \
|
||||
set Interface p2 type=dummy -- \
|
||||
set Interface p3 type=dummy -- \
|
||||
@ -3189,7 +3194,11 @@ OVS_VSWITCHD_START(
|
||||
set Interface p5 type=dummy -- \
|
||||
set Interface p6 type=dummy -- \
|
||||
set Interface p7 type=dummy -- \
|
||||
set Interface p8 type=dummy --])
|
||||
set Interface p8 type=dummy -- \
|
||||
set Interface p9 type=dummy -- \
|
||||
set Interface p10 type=dummy -- \
|
||||
set Interface p11 type=dummy -- \
|
||||
set Interface p12 type=dummy --])
|
||||
|
||||
dnl Each of these specifies an in_port by number, a VLAN VID (or "none"),
|
||||
dnl a VLAN PCP (used if the VID isn't "none") and the expected set of datapath
|
||||
@ -3198,84 +3207,93 @@ for tuple in \
|
||||
"100 none 0 drop" \
|
||||
"100 0 0 drop" \
|
||||
"100 0 1 drop" \
|
||||
"100 10 0 1,5,6,7,8,pop_vlan,2" \
|
||||
"100 10 1 1,5,6,7,8,pop_vlan,2" \
|
||||
"100 10 0 1,5,6,7,8,pop_vlan,2,9" \
|
||||
"100 10 1 1,5,6,7,8,pop_vlan,2,9" \
|
||||
"100 11 0 5,7" \
|
||||
"100 11 1 5,7" \
|
||||
"100 12 0 1,5,6,pop_vlan,3,4,7,8" \
|
||||
"100 12 1 1,5,6,pop_vlan,4,7,push_vlan(vid=0,pcp=1),3,8" \
|
||||
"100 12 0 1,5,6,pop_vlan,3,4,7,8,11,12" \
|
||||
"100 12 1 1,5,6,pop_vlan,4,7,11,push_vlan(vid=0,pcp=1),3,8,12" \
|
||||
"1 none 0 drop" \
|
||||
"1 0 0 drop" \
|
||||
"1 0 1 drop" \
|
||||
"1 10 0 5,6,7,8,100,pop_vlan,2" \
|
||||
"1 10 1 5,6,7,8,100,pop_vlan,2" \
|
||||
"1 10 0 5,6,7,8,100,pop_vlan,2,9" \
|
||||
"1 10 1 5,6,7,8,100,pop_vlan,2,9" \
|
||||
"1 11 0 drop" \
|
||||
"1 11 1 drop" \
|
||||
"1 12 0 5,6,100,pop_vlan,3,4,7,8" \
|
||||
"1 12 1 5,6,100,pop_vlan,4,7,push_vlan(vid=0,pcp=1),3,8" \
|
||||
"2 none 0 push_vlan(vid=10,pcp=0),1,5,6,7,8,100" \
|
||||
"2 0 0 pop_vlan,push_vlan(vid=10,pcp=0),1,5,6,7,8,100" \
|
||||
"2 0 1 pop_vlan,push_vlan(vid=10,pcp=1),1,5,6,7,8,100" \
|
||||
"1 12 0 5,6,100,pop_vlan,3,4,7,8,11,12" \
|
||||
"1 12 1 5,6,100,pop_vlan,4,7,11,push_vlan(vid=0,pcp=1),3,8,12" \
|
||||
"2 none 0 9,push_vlan(vid=10,pcp=0),1,5,6,7,8,100" \
|
||||
"2 0 0 pop_vlan,9,push_vlan(vid=10,pcp=0),1,5,6,7,8,100" \
|
||||
"2 0 1 pop_vlan,9,push_vlan(vid=10,pcp=1),1,5,6,7,8,100" \
|
||||
"2 10 0 drop" \
|
||||
"2 10 1 drop" \
|
||||
"2 11 0 drop" \
|
||||
"2 11 1 drop" \
|
||||
"2 12 0 drop" \
|
||||
"2 12 1 drop" \
|
||||
"3 none 0 4,7,8,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"3 0 0 pop_vlan,4,7,8,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"3 0 1 8,pop_vlan,4,7,push_vlan(vid=12,pcp=1),1,5,6,100" \
|
||||
"3 none 0 4,7,8,11,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"3 0 0 pop_vlan,4,7,8,11,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"3 0 1 8,12,pop_vlan,4,7,11,push_vlan(vid=12,pcp=1),1,5,6,100" \
|
||||
"3 10 0 drop" \
|
||||
"3 10 1 drop" \
|
||||
"3 11 0 drop" \
|
||||
"3 11 1 drop" \
|
||||
"3 12 0 drop" \
|
||||
"3 12 1 drop" \
|
||||
"4 none 0 3,7,8,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"4 0 0 pop_vlan,3,7,8,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"4 0 1 3,8,pop_vlan,7,push_vlan(vid=12,pcp=1),1,5,6,100" \
|
||||
"4 none 0 3,7,8,11,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"4 0 0 pop_vlan,3,7,8,11,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"4 0 1 3,8,12,pop_vlan,7,11,push_vlan(vid=12,pcp=1),1,5,6,100" \
|
||||
"4 10 0 drop" \
|
||||
"4 10 1 drop" \
|
||||
"4 11 0 drop" \
|
||||
"4 11 1 drop" \
|
||||
"4 12 0 drop" \
|
||||
"4 12 1 drop" \
|
||||
"5 none 0 2,push_vlan(vid=10,pcp=0),1,6,7,8,100" \
|
||||
"5 0 0 pop_vlan,2,push_vlan(vid=10,pcp=0),1,6,7,8,100" \
|
||||
"5 0 1 pop_vlan,2,push_vlan(vid=10,pcp=1),1,6,7,8,100" \
|
||||
"5 10 0 1,6,7,8,100,pop_vlan,2" \
|
||||
"5 10 1 1,6,7,8,100,pop_vlan,2" \
|
||||
"5 none 0 2,9,push_vlan(vid=10,pcp=0),1,6,7,8,100" \
|
||||
"5 0 0 pop_vlan,2,9,push_vlan(vid=10,pcp=0),1,6,7,8,100" \
|
||||
"5 0 1 pop_vlan,2,9,push_vlan(vid=10,pcp=1),1,6,7,8,100" \
|
||||
"5 10 0 1,6,7,8,100,pop_vlan,2,9" \
|
||||
"5 10 1 1,6,7,8,100,pop_vlan,2,9" \
|
||||
"5 11 0 7,100" \
|
||||
"5 11 1 7,100" \
|
||||
"5 12 0 1,6,100,pop_vlan,3,4,7,8" \
|
||||
"5 12 1 1,6,100,pop_vlan,4,7,push_vlan(vid=0,pcp=1),3,8" \
|
||||
"6 none 0 2,push_vlan(vid=10,pcp=0),1,5,7,8,100" \
|
||||
"6 0 0 pop_vlan,2,push_vlan(vid=10,pcp=0),1,5,7,8,100" \
|
||||
"6 0 1 pop_vlan,2,push_vlan(vid=10,pcp=1),1,5,7,8,100" \
|
||||
"6 10 0 1,5,7,8,100,pop_vlan,2" \
|
||||
"6 10 1 1,5,7,8,100,pop_vlan,2" \
|
||||
"5 12 0 1,6,100,pop_vlan,3,4,7,8,11,12" \
|
||||
"5 12 1 1,6,100,pop_vlan,4,7,11,push_vlan(vid=0,pcp=1),3,8,12" \
|
||||
"6 none 0 2,9,push_vlan(vid=10,pcp=0),1,5,7,8,100" \
|
||||
"6 0 0 pop_vlan,2,9,push_vlan(vid=10,pcp=0),1,5,7,8,100" \
|
||||
"6 0 1 pop_vlan,2,9,push_vlan(vid=10,pcp=1),1,5,7,8,100" \
|
||||
"6 10 0 1,5,7,8,100,pop_vlan,2,9" \
|
||||
"6 10 1 1,5,7,8,100,pop_vlan,2,9" \
|
||||
"6 11 0 drop" \
|
||||
"6 11 1 drop" \
|
||||
"6 12 0 1,5,100,pop_vlan,3,4,7,8" \
|
||||
"6 12 1 1,5,100,pop_vlan,4,7,push_vlan(vid=0,pcp=1),3,8" \
|
||||
"7 none 0 3,4,8,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"7 0 0 pop_vlan,3,4,8,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"7 0 1 3,8,pop_vlan,4,push_vlan(vid=12,pcp=1),1,5,6,100" \
|
||||
"7 10 0 1,5,6,8,100,pop_vlan,2" \
|
||||
"7 10 1 1,5,6,8,100,pop_vlan,2" \
|
||||
"6 12 0 1,5,100,pop_vlan,3,4,7,8,11,12" \
|
||||
"6 12 1 1,5,100,pop_vlan,4,7,11,push_vlan(vid=0,pcp=1),3,8,12" \
|
||||
"7 none 0 3,4,8,11,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"7 0 0 pop_vlan,3,4,8,11,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"7 0 1 3,8,12,pop_vlan,4,11,push_vlan(vid=12,pcp=1),1,5,6,100" \
|
||||
"7 10 0 1,5,6,8,100,pop_vlan,2,9" \
|
||||
"7 10 1 1,5,6,8,100,pop_vlan,2,9" \
|
||||
"7 11 0 5,100" \
|
||||
"7 11 1 5,100" \
|
||||
"7 12 0 1,5,6,100,pop_vlan,3,4,8" \
|
||||
"7 12 1 1,5,6,100,pop_vlan,4,push_vlan(vid=0,pcp=1),3,8" \
|
||||
"8 none 0 3,4,7,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"8 0 0 pop_vlan,3,4,7,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"8 0 1 3,pop_vlan,4,7,push_vlan(vid=12,pcp=1),1,5,6,100" \
|
||||
"8 10 0 1,5,6,7,100,pop_vlan,2" \
|
||||
"8 10 1 1,5,6,7,100,pop_vlan,2" \
|
||||
"7 12 0 1,5,6,100,pop_vlan,3,4,8,11,12" \
|
||||
"7 12 1 1,5,6,100,pop_vlan,4,11,push_vlan(vid=0,pcp=1),3,8,12" \
|
||||
"8 none 0 3,4,7,11,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"8 0 0 pop_vlan,3,4,7,11,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"8 0 1 3,12,pop_vlan,4,7,11,push_vlan(vid=12,pcp=1),1,5,6,100" \
|
||||
"8 10 0 1,5,6,7,100,pop_vlan,2,9" \
|
||||
"8 10 1 1,5,6,7,100,pop_vlan,2,9" \
|
||||
"8 11 0 drop" \
|
||||
"8 11 1 drop" \
|
||||
"8 12 0 1,5,6,100,pop_vlan,3,4,7" \
|
||||
"8 12 1 1,5,6,100,pop_vlan,4,7,push_vlan(vid=0,pcp=1),3"
|
||||
"8 12 0 1,5,6,100,pop_vlan,3,4,7,11,12" \
|
||||
"8 12 1 1,5,6,100,pop_vlan,4,7,11,push_vlan(vid=0,pcp=1),3,12" \
|
||||
"9 none 0 2,push_vlan(vid=10,pcp=0),1,5,6,7,8,100" \
|
||||
"9 10 0 10,push_vlan(vid=10,pcp=0),1,5,6,7,8,100" \
|
||||
"9 11 0 push_vlan(vid=10,pcp=0),1,5,6,7,8,100" \
|
||||
"10 none 0 drop" \
|
||||
"10 0 0 drop" \
|
||||
"10 11 0 drop" \
|
||||
"10 12 0 9,push_vlan(vid=10,pcp=0),1,5,6,7,8,100" \
|
||||
"11 10 0 7,8,12,push_vlan(vid=12,pcp=0),1,5,6,100" \
|
||||
"11 10 1 7,8,12,push_vlan(vid=12,pcp=0),1,5,6,100"
|
||||
do
|
||||
set $tuple
|
||||
in_port=$1
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
|
||||
/* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Nicira, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -978,6 +978,11 @@ port_configure(struct port *port)
|
||||
s.trunks = vlan_bitmap_from_array(cfg->trunks, cfg->n_trunks);
|
||||
}
|
||||
|
||||
s.cvlans = NULL;
|
||||
if (cfg->n_cvlans) {
|
||||
s.cvlans = vlan_bitmap_from_array(cfg->cvlans, cfg->n_cvlans);
|
||||
}
|
||||
|
||||
/* Get VLAN mode. */
|
||||
if (cfg->vlan_mode) {
|
||||
if (!strcmp(cfg->vlan_mode, "access")) {
|
||||
@ -988,6 +993,8 @@ port_configure(struct port *port)
|
||||
s.vlan_mode = PORT_VLAN_NATIVE_TAGGED;
|
||||
} else if (!strcmp(cfg->vlan_mode, "native-untagged")) {
|
||||
s.vlan_mode = PORT_VLAN_NATIVE_UNTAGGED;
|
||||
} else if (!strcmp(cfg->vlan_mode, "dot1q-tunnel")) {
|
||||
s.vlan_mode = PORT_VLAN_DOT1Q_TUNNEL;
|
||||
} else {
|
||||
/* This "can't happen" because ovsdb-server should prevent it. */
|
||||
VLOG_WARN("port %s: unknown VLAN mode %s, falling "
|
||||
@ -997,7 +1004,7 @@ port_configure(struct port *port)
|
||||
} else {
|
||||
if (s.vlan >= 0) {
|
||||
s.vlan_mode = PORT_VLAN_ACCESS;
|
||||
if (cfg->n_trunks) {
|
||||
if (cfg->n_trunks || cfg->n_cvlans) {
|
||||
VLOG_WARN("port %s: ignoring trunks in favor of implicit vlan",
|
||||
port->name);
|
||||
}
|
||||
@ -1005,6 +1012,12 @@ port_configure(struct port *port)
|
||||
s.vlan_mode = PORT_VLAN_TRUNK;
|
||||
}
|
||||
}
|
||||
|
||||
const char *qe = smap_get_def(&cfg->other_config, "qinq-ethtype", "");
|
||||
s.qinq_ethtype = (!strcmp(qe, "802.1q")
|
||||
? ETH_TYPE_VLAN_8021Q
|
||||
: ETH_TYPE_VLAN_8021AD);
|
||||
|
||||
s.use_priority_tags = smap_get_bool(&cfg->other_config, "priority-tags",
|
||||
false);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{"name": "Open_vSwitch",
|
||||
"version": "7.14.0",
|
||||
"cksum": "3374030633 22987",
|
||||
"version": "7.15.0",
|
||||
"cksum": "544856471 23228",
|
||||
"tables": {
|
||||
"Open_vSwitch": {
|
||||
"columns": {
|
||||
@ -145,6 +145,11 @@
|
||||
"minInteger": 0,
|
||||
"maxInteger": 4095},
|
||||
"min": 0, "max": 4096}},
|
||||
"cvlans": {
|
||||
"type": {"key": {"type": "integer",
|
||||
"minInteger": 0,
|
||||
"maxInteger": 4095},
|
||||
"min": 0, "max": 4096}},
|
||||
"tag": {
|
||||
"type": {"key": {"type": "integer",
|
||||
"minInteger": 0,
|
||||
@ -152,7 +157,8 @@
|
||||
"min": 0, "max": 1}},
|
||||
"vlan_mode": {
|
||||
"type": {"key": {"type": "string",
|
||||
"enum": ["set", ["trunk", "access", "native-tagged", "native-untagged"]]},
|
||||
"enum": ["set", ["trunk", "access", "native-tagged",
|
||||
"native-untagged", "dot1q-tunnel"]]},
|
||||
"min": 0, "max": 1}},
|
||||
"qos": {
|
||||
"type": {"key": {"type": "uuid",
|
||||
|
@ -1281,7 +1281,39 @@
|
||||
</column>
|
||||
|
||||
<group title="VLAN Configuration">
|
||||
<p>Bridge ports support the following types of VLAN configuration:</p>
|
||||
<p>
|
||||
In short, a VLAN (short for ``virtual LAN'') is a way to partition a
|
||||
single switch into multiple switches. VLANs can be confusing, so for
|
||||
an introduction, please refer to the question ``What's a VLAN?'' in the
|
||||
Open vSwitch FAQ.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A VLAN is sometimes encoded into a packet using a 802.1Q or 802.1ad
|
||||
VLAN header, but every packet is part of some VLAN whether or not it is
|
||||
encoded in the packet. (A packet that appears to have no VLAN is part
|
||||
of VLAN 0, by default.) As a result, it's useful to think of a VLAN as
|
||||
a metadata property of a packet, separate from how the VLAN is encoded.
|
||||
For a given port, this column determines how the encoding of a packet
|
||||
that ingresses or egresses the port maps to the packet's VLAN. When a
|
||||
packet enters the switch, its VLAN is determined based on its setting
|
||||
in this column and its VLAN headers, if any, and then, conceptually,
|
||||
the VLAN headers are then stripped off. Conversely, when a packet
|
||||
exits the switch, its VLAN and the settings in this column determine
|
||||
what VLAN headers, if any, are pushed onto the packet before it
|
||||
egresses the port.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The VLAN configuration in this column affects Open vSwitch only when it
|
||||
is doing ``normal switching.'' It does not affect flows set up by an
|
||||
OpenFlow controller, outside of the OpenFlow ``normal action.''
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Bridge ports support the following types of VLAN configuration:
|
||||
</p>
|
||||
|
||||
<dl>
|
||||
<dt>trunk</dt>
|
||||
<dd>
|
||||
@ -1329,6 +1361,29 @@
|
||||
exception that a packet that egresses on a native-untagged port in
|
||||
the native VLAN will not have an 802.1Q header.
|
||||
</dd>
|
||||
|
||||
<dt>dot1q-tunnel</dt>
|
||||
<dd>
|
||||
<p>
|
||||
A dot1q-tunnel port is somewhat like an access port. Like an
|
||||
access port, it carries packets on the single VLAN specified in the
|
||||
<ref column="tag"/> column and this VLAN, called the service VLAN,
|
||||
does not appear in an 802.1Q header for packets that ingress or
|
||||
egress on the port. The main difference lies in the behavior when
|
||||
packets that include a 802.1Q header ingress on the port. Whereas
|
||||
an access port drops such packets, a dot1q-tunnel port treats these
|
||||
as double-tagged with the outer service VLAN <ref column="tag"/>
|
||||
and the inner customer VLAN taken from the 802.1Q header.
|
||||
Correspondingly, to egress on the port, a packet outer VLAN (or
|
||||
only VLAN) must be <ref column="tag"/>, which is removed before
|
||||
egress, which exposes the inner (customer) VLAN if one is present.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If <ref column="cvlans"/> is set, only allows packets in the
|
||||
specified customer VLANs.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<p>
|
||||
A packet will only egress through bridge ports that carry the VLAN of
|
||||
@ -1373,6 +1428,37 @@
|
||||
</p>
|
||||
</column>
|
||||
|
||||
<column name="cvlans">
|
||||
<p>
|
||||
For a dot1q-tunnel port, the customer VLANs that this port includes.
|
||||
If this is empty, the port includes all customer VLANs.
|
||||
</p>
|
||||
<p>
|
||||
For other kinds of ports, this setting is ignored.
|
||||
</p>
|
||||
</column>
|
||||
|
||||
<column name="other_config" key="qinq-ethtype"
|
||||
type='{"type": "string", "enum": ["set", ["802.1ad", "802.1q"]]}'>
|
||||
<p>
|
||||
For a dot1q-tunnel port, this is the TPID for the service tag, that
|
||||
is, for the 802.1Q header that contains the service VLAN ID. Because
|
||||
packets that actually ingress and egress a dot1q-tunnel port do not
|
||||
include an 802.1Q header for the service VLAN, this does not affect
|
||||
packets on the dot1q-tunnel port itself. Rather, it determines the
|
||||
service VLAN for a packet that ingresses on a dot1q-tunnel port and
|
||||
egresses on a trunk port.
|
||||
</p>
|
||||
<p>
|
||||
The value <code>802.1ad</code> specifies TPID 0x88a8, which is also
|
||||
the default if the setting is omitted. The value <code>802.1q</code>
|
||||
specifies TPID 0x8100.
|
||||
</p>
|
||||
<p>
|
||||
For other kinds of ports, this setting is ignored.
|
||||
</p>
|
||||
</column>
|
||||
|
||||
<column name="other_config" key="priority-tags"
|
||||
type='{"type": "boolean"}'>
|
||||
<p>
|
||||
|
Loading…
x
Reference in New Issue
Block a user