diff mbox series

[v7,net] stmmac: added support for 802.1ad vlan stripping

Message ID 82c9c00a-b1b7-bd16-0e9c-8b31291cb618@gmail.com
State Accepted, archived
Delegated to: David Miller
Headers show
Series [v7,net] stmmac: added support for 802.1ad vlan stripping | expand

Commit Message

Elad Nachman June 15, 2018, 6:57 a.m. UTC
stmmac reception handler calls stmmac_rx_vlan() to strip the vlan before 
calling napi_gro_receive().

The function assumes VLAN tagged frames are always tagged with 
802.1Q protocol, and assigns ETH_P_8021Q to the skb by hard-coding
the parameter on call to __vlan_hwaccel_put_tag() .

This causes packets not to be passed to the VLAN slave if it was created 
with 802.1AD protocol
(ip link add link eth0 eth0.100 type vlan proto 802.1ad id 100).

This fix passes the protocol from the VLAN header into 
__vlan_hwaccel_put_tag() instead of using the hard-coded value of
ETH_P_8021Q.

NETIF_F_HW_VLAN_STAG_RX check was added and the strip action is now
dependent on the correct combination of features and the detected vlan tag.

NETIF_F_HW_VLAN_STAG_RX feature was added to be in line with the driver 
actual abilities.

Signed-off-by: Elad Nachman <eladn@gilat.com>



---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

Comments

Toshiaki Makita June 15, 2018, 7:19 a.m. UTC | #1
On 2018/06/15 15:57, Elad Nachman wrote:
> stmmac reception handler calls stmmac_rx_vlan() to strip the vlan before 
> calling napi_gro_receive().
> 
> The function assumes VLAN tagged frames are always tagged with 
> 802.1Q protocol, and assigns ETH_P_8021Q to the skb by hard-coding
> the parameter on call to __vlan_hwaccel_put_tag() .
> 
> This causes packets not to be passed to the VLAN slave if it was created 
> with 802.1AD protocol
> (ip link add link eth0 eth0.100 type vlan proto 802.1ad id 100).
> 
> This fix passes the protocol from the VLAN header into 
> __vlan_hwaccel_put_tag() instead of using the hard-coded value of
> ETH_P_8021Q.
> 
> NETIF_F_HW_VLAN_STAG_RX check was added and the strip action is now
> dependent on the correct combination of features and the detected vlan tag.
> 
> NETIF_F_HW_VLAN_STAG_RX feature was added to be in line with the driver 
> actual abilities.
> 
> Signed-off-by: Elad Nachman <eladn@gilat.com>

Reviewed-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>

> 
> ---
>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 21 +++++++++++++--------
>  1 file changed, 13 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 11fb7c7..c4ffbfb 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -3182,17 +3182,22 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
>  
>  static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
>  {
> -	struct ethhdr *ehdr;
> +	struct vlan_ethhdr *veth;
> +	__be16 vlan_proto;
>  	u16 vlanid;
>  
> -	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) ==
> -	    NETIF_F_HW_VLAN_CTAG_RX &&
> -	    !__vlan_get_tag(skb, &vlanid)) {
> +	veth = (struct vlan_ethhdr *)skb->data;
> +	vlan_proto = veth->h_vlan_proto;
> +
> +	if ((vlan_proto == htons(ETH_P_8021Q) &&
> +	     dev->features & NETIF_F_HW_VLAN_CTAG_RX) ||
> +	    (vlan_proto == htons(ETH_P_8021AD) &&
> +	     dev->features & NETIF_F_HW_VLAN_STAG_RX)) {
>  		/* pop the vlan tag */
> -		ehdr = (struct ethhdr *)skb->data;
> -		memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2);
> +		vlanid = ntohs(veth->h_vlan_TCI);
> +		memmove(skb->data + VLAN_HLEN, veth, ETH_ALEN * 2);
>  		skb_pull(skb, VLAN_HLEN);
> -		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid);
> +		__vlan_hwaccel_put_tag(skb, vlan_proto, vlanid);
>  	}
>  }
>  
> @@ -4235,7 +4240,7 @@ int stmmac_dvr_probe(struct device *device,
>  	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
>  #ifdef STMMAC_VLAN_TAG_USED
>  	/* Both mac100 and gmac support receive VLAN tag detection */
> -	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
> +	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX;
>  #endif
>  	priv->msg_enable = netif_msg_init(debug, default_msg_level);
>  
>
David Miller June 15, 2018, 4:06 p.m. UTC | #2
From: Elad Nachman <eladv6@gmail.com>
Date: Fri, 15 Jun 2018 09:57:39 +0300

> stmmac reception handler calls stmmac_rx_vlan() to strip the vlan before 
> calling napi_gro_receive().
> 
> The function assumes VLAN tagged frames are always tagged with 
> 802.1Q protocol, and assigns ETH_P_8021Q to the skb by hard-coding
> the parameter on call to __vlan_hwaccel_put_tag() .
> 
> This causes packets not to be passed to the VLAN slave if it was created 
> with 802.1AD protocol
> (ip link add link eth0 eth0.100 type vlan proto 802.1ad id 100).
> 
> This fix passes the protocol from the VLAN header into 
> __vlan_hwaccel_put_tag() instead of using the hard-coded value of
> ETH_P_8021Q.
> 
> NETIF_F_HW_VLAN_STAG_RX check was added and the strip action is now
> dependent on the correct combination of features and the detected vlan tag.
> 
> NETIF_F_HW_VLAN_STAG_RX feature was added to be in line with the driver 
> actual abilities.
> 
> Signed-off-by: Elad Nachman <eladn@gilat.com>

Applied, thank you.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 11fb7c7..c4ffbfb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3182,17 +3182,22 @@  static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
 {
-	struct ethhdr *ehdr;
+	struct vlan_ethhdr *veth;
+	__be16 vlan_proto;
 	u16 vlanid;
 
-	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) ==
-	    NETIF_F_HW_VLAN_CTAG_RX &&
-	    !__vlan_get_tag(skb, &vlanid)) {
+	veth = (struct vlan_ethhdr *)skb->data;
+	vlan_proto = veth->h_vlan_proto;
+
+	if ((vlan_proto == htons(ETH_P_8021Q) &&
+	     dev->features & NETIF_F_HW_VLAN_CTAG_RX) ||
+	    (vlan_proto == htons(ETH_P_8021AD) &&
+	     dev->features & NETIF_F_HW_VLAN_STAG_RX)) {
 		/* pop the vlan tag */
-		ehdr = (struct ethhdr *)skb->data;
-		memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2);
+		vlanid = ntohs(veth->h_vlan_TCI);
+		memmove(skb->data + VLAN_HLEN, veth, ETH_ALEN * 2);
 		skb_pull(skb, VLAN_HLEN);
-		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid);
+		__vlan_hwaccel_put_tag(skb, vlan_proto, vlanid);
 	}
 }
 
@@ -4235,7 +4240,7 @@  int stmmac_dvr_probe(struct device *device,
 	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
 #ifdef STMMAC_VLAN_TAG_USED
 	/* Both mac100 and gmac support receive VLAN tag detection */
-	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
+	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX;
 #endif
 	priv->msg_enable = netif_msg_init(debug, default_msg_level);