From: "hongbo.wang" <[email protected]>
1. the patch 0001* is for setting single port into 802.1AD(QinQ) mode,
before this patch, the function dsa_slave_vlan_rx_add_vid didn't pass
the parameter "proto" to next port level, so switch's port can't get
parameter "proto"
after applying this patch, we can use the following commands to set port
to enable or disable QinQ mode:
ip link add link swp1 name swp1.100 type vlan protocol 802.1ad id 100
ip link del link swp1 name swp1.100
2. the patch 0002* is for setting QinQ related registers in ocelot
switch driver, after applying this patch, the switch(VSC99599)'s port can
enable or disable QinQ mode.
hongbo.wang (2):
net: dsa: Add protocol support for 802.1AD when adding or deleting
vlan for dsa switch and port
net: dsa: ocelot: Add support for QinQ Operation
drivers/net/dsa/ocelot/felix.c | 8 ++++++
drivers/net/ethernet/mscc/ocelot.c | 44 ++++++++++++++++++++++++------
include/net/switchdev.h | 1 +
include/soc/mscc/ocelot.h | 1 +
net/dsa/dsa_priv.h | 4 +--
net/dsa/port.c | 6 ++--
net/dsa/slave.c | 9 +++---
net/dsa/tag_8021q.c | 4 +--
8 files changed, 59 insertions(+), 18 deletions(-)
--
2.17.1
From: "hongbo.wang" <[email protected]>
This featue can be test using network test tools
TX-tool -----> swp0 -----> swp1 -----> RX-tool
TX-tool simulates Customer that will send and receive packets with single
VLAN tag(CTAG), RX-tool simulates Service-Provider that will send and
receive packets with double VLAN tag(STAG and CTAG). This refers to
"4.3.3 Provider Bridges and Q-in-Q Operation" in VSC99599_1_00_TS.pdf.
The related test commands:
1.
ip link add dev br0 type bridge
ip link set dev swp0 master br0
ip link set dev swp1 master br0
2.
ip link add link swp0 name swp0.111 type vlan id 111
ip link add link swp1 name swp1.111 type vlan protocol 802.1ad id 111
3.
bridge vlan add dev swp0 vid 100 pvid
bridge vlan add dev swp1 vid 100
bridge vlan del dev swp1 vid 1 pvid
bridge vlan add dev swp1 vid 200 pvid untagged
Result:
Customer(tpid:8100 vid:111) -> swp0 -> swp1 -> Service-Provider(STAG \
tpid:88A8 vid:100, CTAG tpid:8100 vid:111)
Signed-off-by: hongbo.wang <[email protected]>
---
drivers/net/dsa/ocelot/felix.c | 8 ++++++
drivers/net/ethernet/mscc/ocelot.c | 44 ++++++++++++++++++++++++------
include/soc/mscc/ocelot.h | 1 +
3 files changed, 45 insertions(+), 8 deletions(-)
diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index c69d9592a2b7..12b46cb6549c 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -132,9 +132,13 @@ static void felix_vlan_add(struct dsa_switch *ds, int port,
{
struct ocelot *ocelot = ds->priv;
u16 flags = vlan->flags;
+ struct ocelot_port *ocelot_port = ocelot->ports[port];
u16 vid;
int err;
+ if (vlan->proto == ETH_P_8021AD)
+ ocelot_port->qinq_mode = true;
+
if (dsa_is_cpu_port(ds, port))
flags &= ~BRIDGE_VLAN_INFO_UNTAGGED;
@@ -154,9 +158,13 @@ static int felix_vlan_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
{
struct ocelot *ocelot = ds->priv;
+ struct ocelot_port *ocelot_port = ocelot->ports[port];
u16 vid;
int err;
+ if (vlan->proto == ETH_P_8021AD)
+ ocelot_port->qinq_mode = false;
+
for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
err = ocelot_vlan_del(ocelot, port, vid);
if (err) {
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index f2d94b026d88..621277e875a5 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -144,6 +144,8 @@ static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port,
{
struct ocelot_port *ocelot_port = ocelot->ports[port];
u32 val = 0;
+ u32 tag_tpid = 0;
+ u32 port_tpid = 0;
if (ocelot_port->vid != vid) {
/* Always permit deleting the native VLAN (vid = 0) */
@@ -156,8 +158,14 @@ static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port,
ocelot_port->vid = vid;
}
- ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_VID(vid),
- REW_PORT_VLAN_CFG_PORT_VID_M,
+ if (ocelot_port->qinq_mode)
+ port_tpid = REW_PORT_VLAN_CFG_PORT_TPID(ETH_P_8021AD);
+ else
+ port_tpid = REW_PORT_VLAN_CFG_PORT_TPID(ETH_P_8021Q);
+
+ ocelot_rmw_gix(ocelot, REW_PORT_VLAN_CFG_PORT_VID(vid) | port_tpid,
+ REW_PORT_VLAN_CFG_PORT_VID_M |
+ REW_PORT_VLAN_CFG_PORT_TPID_M,
REW_PORT_VLAN_CFG, port);
if (ocelot_port->vlan_aware && !ocelot_port->vid)
@@ -180,12 +188,28 @@ static int ocelot_port_set_native_vlan(struct ocelot *ocelot, int port,
else
/* Tag all frames */
val = REW_TAG_CFG_TAG_CFG(3);
+
+ if (ocelot_port->qinq_mode)
+ tag_tpid = REW_TAG_CFG_TAG_TPID_CFG(1);
+ else
+ tag_tpid = REW_TAG_CFG_TAG_TPID_CFG(0);
} else {
- /* Port tagging disabled. */
- val = REW_TAG_CFG_TAG_CFG(0);
+ if (ocelot_port->qinq_mode) {
+ if (ocelot_port->vid)
+ val = REW_TAG_CFG_TAG_CFG(1);
+ else
+ val = REW_TAG_CFG_TAG_CFG(3);
+
+ tag_tpid = REW_TAG_CFG_TAG_TPID_CFG(1);
+ } else {
+ /* Port tagging disabled. */
+ val = REW_TAG_CFG_TAG_CFG(0);
+ tag_tpid = REW_TAG_CFG_TAG_TPID_CFG(0);
+ }
}
- ocelot_rmw_gix(ocelot, val,
- REW_TAG_CFG_TAG_CFG_M,
+
+ ocelot_rmw_gix(ocelot, val | tag_tpid,
+ REW_TAG_CFG_TAG_CFG_M | REW_TAG_CFG_TAG_TPID_CFG_M,
REW_TAG_CFG, port);
return 0;
@@ -216,11 +240,15 @@ EXPORT_SYMBOL(ocelot_port_vlan_filtering);
/* Default vlan to clasify for untagged frames (may be zero) */
static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, u16 pvid)
{
+ u32 tag_type = 0;
struct ocelot_port *ocelot_port = ocelot->ports[port];
+ if (ocelot_port->qinq_mode)
+ tag_type = ANA_PORT_VLAN_CFG_VLAN_TAG_TYPE;
+
ocelot_rmw_gix(ocelot,
- ANA_PORT_VLAN_CFG_VLAN_VID(pvid),
- ANA_PORT_VLAN_CFG_VLAN_VID_M,
+ ANA_PORT_VLAN_CFG_VLAN_VID(pvid) | tag_type,
+ ANA_PORT_VLAN_CFG_VLAN_VID_M | tag_type,
ANA_PORT_VLAN_CFG, port);
ocelot_port->pvid = pvid;
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index da369b12005f..cc394740078e 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -556,6 +556,7 @@ struct ocelot_port {
struct regmap *target;
bool vlan_aware;
+ bool qinq_mode;
/* Ingress default VLAN (pvid) */
u16 pvid;
--
2.17.1
On Wed, Jul 22, 2020 at 06:32:00PM +0800, [email protected] wrote:
> From: "hongbo.wang" <[email protected]>
>
> This featue can be test using network test tools
> TX-tool -----> swp0 -----> swp1 -----> RX-tool
>
> TX-tool simulates Customer that will send and receive packets with single
> VLAN tag(CTAG), RX-tool simulates Service-Provider that will send and
> receive packets with double VLAN tag(STAG and CTAG). This refers to
> "4.3.3 Provider Bridges and Q-in-Q Operation" in VSC99599_1_00_TS.pdf.
>
> The related test commands:
> 1.
> ip link add dev br0 type bridge
> ip link set dev swp0 master br0
> ip link set dev swp1 master br0
> 2.
> ip link add link swp0 name swp0.111 type vlan id 111
> ip link add link swp1 name swp1.111 type vlan protocol 802.1ad id 111
> 3.
> bridge vlan add dev swp0 vid 100 pvid
> bridge vlan add dev swp1 vid 100
> bridge vlan del dev swp1 vid 1 pvid
> bridge vlan add dev swp1 vid 200 pvid untagged
> Result:
> Customer(tpid:8100 vid:111) -> swp0 -> swp1 -> Service-Provider(STAG \
> tpid:88A8 vid:100, CTAG tpid:8100 vid:111)
>
> Signed-off-by: hongbo.wang <[email protected]>
> ---
Instead of writing a long email, let me just say this.
I ran your commands on 2 random network cards (not ocelot/felix ports).
They don't produce the same results as you. In fact, no frame with VLAN
111 C-TAG is forwarded (or received) at all by the bridge, not to
mention that no VLAN 1000 S-TAG is pushed on egress.
Have you tried playing with these commands?
ip link add dev br0 type bridge vlan_filtering 1 vlan_protocol 802.1ad
ip link set eth0 master br0
ip link set eth1 master br0
bridge vlan add dev eth0 vid 100 pvid
bridge vlan add dev eth1 vid 100
They produce the same output as yours, but have the benefit of using
the network stack's abstractions and not glue between the 802.1q and the
bridge module, hidden in the network driver.
I am sending the following packet towards eth0:
00:04:9f:05:f4:ad > 00:01:02:03:04:05, ethertype 802.1Q (0x8100), length 102: \
vlan 111, p 0, ethertype IPv4, 10.0.111.1 > 10.0.111.3: \
ICMP echo request, id 63493, seq 991, length 64
and collecting it on the partner of eth1 as follows:
00:04:9f:05:f4:ad > 00:01:02:03:04:05, ethertype 802.1Q-QinQ (0x88a8), length 106: \
vlan 100, p 0, ethertype 802.1Q, vlan 111, p 0, ethertype IPv4, \
10.0.111.1 > 10.0.111.3: ICMP echo request, id 63493, seq 991, length 64
Thanks,
-Vladimir
> Instead of writing a long email, let me just say this.
> I ran your commands on 2 random network cards (not ocelot/felix ports).
> They don't produce the same results as you. In fact, no frame with VLAN
> 111 C-TAG is forwarded (or received) at all by the bridge, not to mention that
> no VLAN 1000 S-TAG is pushed on egress.
>
>
> Have you tried playing with these commands?
>
> ip link add dev br0 type bridge vlan_filtering 1 vlan_protocol 802.1ad ip link
> set eth0 master br0 ip link set eth1 master br0 bridge vlan add dev eth0 vid
> 100 pvid bridge vlan add dev eth1 vid 100
>
> They produce the same output as yours, but have the benefit of using the
> network stack's abstractions and not glue between the 802.1q and the bridge
> module, hidden in the network driver.
>
> I am sending the following packet towards eth0:
>
> 00:04:9f:05:f4:ad > 00:01:02:03:04:05, ethertype 802.1Q (0x8100), length
> 102: \
> vlan 111, p 0, ethertype IPv4, 10.0.111.1 > 10.0.111.3: \
> ICMP echo request, id 63493, seq 991, length 64
>
> and collecting it on the partner of eth1 as follows:
>
> 00:04:9f:05:f4:ad > 00:01:02:03:04:05, ethertype 802.1Q-QinQ (0x88a8),
> length 106: \
> vlan 100, p 0, ethertype 802.1Q, vlan 111, p 0, ethertype IPv4, \
> 10.0.111.1 > 10.0.111.3: ICMP echo request, id 63493, seq 991,
> length 64
>
> Thanks,
> -Vladimir
Hi Vladimir,
the command " ip link add dev br0 type bridge vlan_filtering 1 vlan_protocol
802.1ad " will influence all ports within the bridge, it will enable all ports vlan_filtering
flag and 802.1ad mode, if ocelot port enable vlan_filtering, it will set VLAN_AWARE_ENA
and VLAN_POP_CNT(1), the code is in ocelot_port_vlan_filtering in ocelot.c. it will
pop one tag from ingress frame, it's not my need, so I don't set vlan_filtering.
If enable vlan_filtering, it needs enable VCAP ES0 push double VLAN tag, the code
is in another patch, it's based on VCAP ES0 related code, I will post it after ES0 code
be accepted.
In this case, I only want the egress port(swp1) in QinQ mode, the mode will change swp1's
REW_TAG value, don't need swp0 enter QinQ mode, another issue is that if use " ip link add dev
br0 type bridge ...", it can't pass proto to port driver, in dsa_slave_vlan_rx_add_vid, it will walk
into here:
ret = br_vlan_get_info(dp->bridge_dev, vid, &info);
if (ret == 0) // ret is 0
return -EBUSY;
so I use "ip link add link swp1 name swp1.111 type vlan protocol 802.1ad id 111" to enable only
port swp1's QinQ mode.
Thanks,
hongbo