Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Support 802.11ad EthType for localnet ports
In some environments, hardware serving the fabric network doesn't
support double 802.1q (0x8100) VLAN tags, but does support 802.11ad
(0x8a88) EthType for two layer VLAN traffic. Specifically, Cisco
hardware UCS VIC was identified affected by this limitation.

With vlan-passthru=true set for a logical switch, VLAN tagged traffic
may be generated by VIFs. This patch allows to support the feature in
affected hardware environments.

Signed-off-by: Ihar Hrachyshka <ihrachys@redhat.com>
Signed-off-by: Numan Siddique <numans@ovn.org>
  • Loading branch information
booxter authored and numansiddique committed Apr 19, 2021
1 parent e45e94b commit 50f4ea0
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 8 deletions.
1 change: 1 addition & 0 deletions NEWS
Expand Up @@ -10,6 +10,7 @@ Post-v21.03.0
- Introduced parallel processing in ovn-northd with the NB_Global config option
'use_parallel_build' to enable it. It is disabled by default.
- Support vlan-passthru mode for tag=0 localnet ports.
- Support custom 802.11ad EthType for localnet ports.

OVN v21.03.0 - 12 Mar 2021
-------------------------
Expand Down
40 changes: 32 additions & 8 deletions controller/physical.c
Expand Up @@ -609,6 +609,34 @@ put_replace_chassis_mac_flows(const struct simap *ct_zones,
}
}

#define VLAN_80211AD_ETHTYPE 0x88a8
#define VLAN_80211Q_ETHTYPE 0x8100

static void
ofpact_put_push_vlan(struct ofpbuf *ofpacts, const struct smap *options, int tag)
{
const char *ethtype_opt = options ? smap_get(options, "ethtype") : NULL;

int ethtype = VLAN_80211Q_ETHTYPE;
if (ethtype_opt) {
if (!strcasecmp(ethtype_opt, "802.11ad")) {
ethtype = VLAN_80211AD_ETHTYPE;
} else if (strcasecmp(ethtype_opt, "802.11q")) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
VLOG_WARN_RL(&rl, "Unknown port ethtype: %s", ethtype_opt);
}
}

struct ofpact_push_vlan *push_vlan;
push_vlan = ofpact_put_PUSH_VLAN(ofpacts);
push_vlan->ethertype = htons(ethtype);

struct ofpact_vlan_vid *vlan_vid;
vlan_vid = ofpact_put_SET_VLAN_VID(ofpacts);
vlan_vid->vlan_vid = tag;
vlan_vid->push_vlan_if_needed = false;
}

static void
put_replace_router_port_mac_flows(struct ovsdb_idl_index
*sbrec_port_binding_by_name,
Expand Down Expand Up @@ -696,10 +724,7 @@ put_replace_router_port_mac_flows(struct ovsdb_idl_index
replace_mac->mac = chassis_mac;

if (tag) {
struct ofpact_vlan_vid *vlan_vid;
vlan_vid = ofpact_put_SET_VLAN_VID(ofpacts_p);
vlan_vid->vlan_vid = tag;
vlan_vid->push_vlan_if_needed = true;
ofpact_put_push_vlan(ofpacts_p, &localnet_port->options, tag);
}

ofpact_put_OUTPUT(ofpacts_p)->port = ofport;
Expand Down Expand Up @@ -1203,10 +1228,9 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
if (tag) {
/* For containers sitting behind a local vif, tag the packets
* before delivering them. */
struct ofpact_vlan_vid *vlan_vid;
vlan_vid = ofpact_put_SET_VLAN_VID(ofpacts_p);
vlan_vid->vlan_vid = tag;
vlan_vid->push_vlan_if_needed = true;
ofpact_put_push_vlan(
ofpacts_p, localnet_port ? &localnet_port->options : NULL,
tag);
}
ofpact_put_OUTPUT(ofpacts_p)->port = ofport;
if (tag) {
Expand Down
6 changes: 6 additions & 0 deletions ovn-nb.xml
Expand Up @@ -847,6 +847,12 @@
uses its local configuration to determine exactly how to connect to
this locally accessible network, if at all.
</column>

<column name="options" key="ethtype">
Optional. VLAN EtherType field value for encapsulating VLAN
headers. Supported values: 802.11q (default), 802.11ad.
</column>

</group>

<group title="Options for l2gateway ports">
Expand Down
85 changes: 85 additions & 0 deletions tests/ovn.at
Expand Up @@ -3227,6 +3227,91 @@ done
AT_CLEANUP
])

OVN_FOR_EACH_NORTHD([
AT_SETUP([ovn -- VLAN transparency, passthru=true, multiple hosts, custom ethtype])
ovn_start

ethtype=802.11ad

check ovn-nbctl ls-add ls
check ovn-nbctl --wait=sb add Logical-Switch ls other_config vlan-passthru=true

ln_port_name=ln-100
ovn-nbctl lsp-add ls $ln_port_name "" 100
ovn-nbctl lsp-set-addresses $ln_port_name unknown
ovn-nbctl lsp-set-type $ln_port_name localnet
ovn-nbctl lsp-set-options $ln_port_name network_name=phys-100 ethtype=$ethtype
net_add n-100

# two hypervisors, each connected to the same network
for i in 1 2; do
sim_add hv-$i
as hv-$i
ovs-vsctl add-br br-phys
ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys-100:br-phys
ovn_attach n-100 br-phys 192.168.0.$i
done

for i in 1 2; do
check ovn-nbctl lsp-add ls lsp$i
check ovn-nbctl lsp-set-addresses lsp$i f0:00:00:00:00:0$i
done

for i in 1 2; do
as hv-$i
check ovs-vsctl add-port br-int vif$i -- set Interface vif$i external-ids:iface-id=lsp$i \
options:tx_pcap=vif$i-tx.pcap \
options:rxq_pcap=vif$i-rx.pcap \
ofport-request=$i
wait_for_ports_up lsp$i
done

# create taps on fabric to check vlan encapsulation there
for i in 1 2; do
as hv-$i
ovs-vsctl add-port br-phys tap$i -- set Interface tap$i \
options:tx_pcap=tap$i-tx.pcap \
options:rxq_pcap=tap$i-rx.pcap
done

for i in 1 2; do
: > $i.expected
done
: > tap.expected

test_packet() {
local inport=$1 dst=$2 src=$3 eth=$4 lout=$5 ethtype=$6

# First try tracing the packet.
uflow="inport==\"lsp$inport\" && eth.dst==$dst && eth.src==$src && eth.type==0x$eth && vlan.present==1"
echo "output(\"$lout\");" > expout
AT_CAPTURE_FILE([trace])
AT_CHECK([ovn-trace --all ls "$uflow" | tee trace | sed '1,/Minimal trace/d'], [0], [expout])

# Then actually send a packet, for an end-to-end test.
payload=fefefefe
local packet=$(echo $dst$src | sed 's/://g')${eth}${payload}
vif=vif$inport
as hv-$1
ovs-appctl netdev-dummy/receive $vif $packet
echo $packet >> ${inport}.expected

phys_packet=$(echo $dst$src | sed 's/://g')${ethtype}0064${eth}${payload}
echo $phys_packet >> tap.expected
}

test_packet 1 f0:00:00:00:00:03 f0:00:00:00:00:01 8100 ln-100 88a8
test_packet 2 f0:00:00:00:00:03 f0:00:00:00:00:02 8100 ln-100 88a8
for i in 1 2; do
OVN_CHECK_PACKETS_REMOVE_BROADCAST([vif$i-rx.pcap], [$i.expected])
done
for i in 1 2; do
OVN_CHECK_PACKETS_REMOVE_BROADCAST([tap$i-tx.pcap], [tap.expected])
done

AT_CLEANUP
])

OVN_FOR_EACH_NORTHD([
AT_SETUP([ovn -- VLAN transparency, passthru=true, multiple hosts, flat/untagged])
ovn_start
Expand Down

0 comments on commit 50f4ea0

Please sign in to comment.