Blame SOURCES/ipxe-netdevice-Strip-802.Q-VLAN-0-priority-tags.patch

22decc
From ff3a5af3d7f78577899626b2f8b612369e051916 Mon Sep 17 00:00:00 2001
22decc
From: Miroslav Rezanina <mrezanin@redhat.com>
22decc
Date: Mon, 2 Aug 2021 08:32:33 -0400
22decc
Subject: [PATCH 3/5] [netdevice] Strip 802.Q VLAN 0 priority tags
22decc
22decc
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
22decc
RH-MergeRequest: 6: Forwardport  missing RHEL 8 downsteream changes
22decc
RH-Commit: [3/5] 440560659da2028f365a71b4ed4991955022dce5 (mrezanin/centos-src-ipxe)
22decc
RH-Bugzilla: 1985658
22decc
22decc
iPXE was unable to receive priority tagged packets specified in
22decc
the 802.1Q standard and supported by all major networking stacks.
22decc
22decc
This commit adds a new function net_pull_tags which is called by
22decc
all consumers of incoming packets after stripping their link-layer
22decc
headers.
22decc
22decc
Upstream patch:
22decc
http://lists.ipxe.org/pipermail/ipxe-devel/2016-July/005099.html
22decc
22decc
Downstream changes:
22decc
Upstream commit fe680c822856 made vlan_find static. This prevents
22decc
it's usage int this patch. Reverting changes adding static for
22decc
vlan_find.
22decc
22decc
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
22decc
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
22decc
---
22decc
 src/arch/x86/interface/pxe/pxe_undi.c |  6 +++
22decc
 src/include/ipxe/netdevice.h          |  2 +
22decc
 src/include/ipxe/vlan.h               |  2 +
22decc
 src/interface/efi/efi_snp.c           |  7 ++++
22decc
 src/net/netdevice.c                   | 57 +++++++++++++++++++++++++++
22decc
 src/net/vlan.c                        |  2 +-
22decc
 6 files changed, 75 insertions(+), 1 deletion(-)
22decc
22decc
diff --git a/src/arch/x86/interface/pxe/pxe_undi.c b/src/arch/x86/interface/pxe/pxe_undi.c
22decc
index 2eb68178..2ea14515 100644
22decc
--- a/src/arch/x86/interface/pxe/pxe_undi.c
22decc
+++ b/src/arch/x86/interface/pxe/pxe_undi.c
22decc
@@ -976,6 +976,12 @@ static PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
22decc
 		}
22decc
 		ll_hlen = ( len - iob_len ( iobuf ) );
22decc
 
22decc
+		/* Strip link-layer-independent headers */
22decc
+		if ( ( rc = net_pull_tags ( iobuf, pxe_netdev, &net_proto ) ) != 0 ) {
22decc
+			/* Assume unknown net_proto */
22decc
+			net_proto = 0;
22decc
+		}
22decc
+
22decc
 		/* Determine network-layer protocol */
22decc
 		switch ( net_proto ) {
22decc
 		case htons ( ETH_P_IP ):
22decc
diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h
22decc
index d498ab69..27dda45d 100644
22decc
--- a/src/include/ipxe/netdevice.h
22decc
+++ b/src/include/ipxe/netdevice.h
22decc
@@ -726,6 +726,8 @@ extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
22decc
 extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
22decc
 		    uint16_t net_proto, const void *ll_dest,
22decc
 		    const void *ll_source, unsigned int flags );
22decc
+extern int net_pull_tags ( struct io_buffer *iobuf, struct net_device *netdev,
22decc
+			   uint16_t *net_proto );
22decc
 extern void net_poll ( void );
22decc
 extern struct net_device_configurator *
22decc
 find_netdev_configurator ( const char *name );
22decc
diff --git a/src/include/ipxe/vlan.h b/src/include/ipxe/vlan.h
22decc
index 7f93439b..b82f3806 100644
22decc
--- a/src/include/ipxe/vlan.h
22decc
+++ b/src/include/ipxe/vlan.h
22decc
@@ -61,6 +61,8 @@ struct vlan_header {
22decc
  */
22decc
 #define VLAN_PRIORITY_IS_VALID( priority ) ( (priority) <= 7 )
22decc
 
22decc
+extern struct net_device * vlan_find ( struct net_device *trunk,
22decc
+                                      unsigned int tag );
22decc
 extern unsigned int vlan_tag ( struct net_device *netdev );
22decc
 extern int vlan_can_be_trunk ( struct net_device *trunk );
22decc
 extern int vlan_create ( struct net_device *trunk, unsigned int tag,
22decc
diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c
22decc
index d648700f..a8f2ac8e 100644
22decc
--- a/src/interface/efi/efi_snp.c
22decc
+++ b/src/interface/efi/efi_snp.c
22decc
@@ -813,6 +813,13 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
22decc
 		goto out_bad_ll_header;
22decc
 	}
22decc
 
22decc
+	/* Strip link-layer-independent headers */
22decc
+	if ( ( rc = net_pull_tags ( iobuf, snpdev->netdev, &iob_net_proto ) ) ) {
22decc
+		DBGC ( snpdev, "SNPDEV %p could not parse tags: %s\n",
22decc
+		       snpdev, strerror ( rc ) );
22decc
+		goto out_bad_ll_header;
22decc
+	}
22decc
+
22decc
 	/* Return link-layer header parameters to caller, if required */
22decc
 	if ( ll_header_len )
22decc
 		*ll_header_len = ll_protocol->ll_header_len;
22decc
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
22decc
index 3b02e64b..95803f26 100644
22decc
--- a/src/net/netdevice.c
22decc
+++ b/src/net/netdevice.c
22decc
@@ -1043,6 +1043,45 @@ int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
22decc
 	return -ENOTSUP;
22decc
 }
22decc
 
22decc
+
22decc
+/**
22decc
+ * Strip extra link-layer-independent tags from a received packet
22decc
+ *
22decc
+ * @v iobuf		I/O buffer
22decc
+ * @v netdev		Network device
22decc
+ * @v net_proto		Network-layer protocol, in network-byte order
22decc
+ * @ret rc		Return status code
22decc
+ *
22decc
+ * This function should be called after stripping link-layer headers but
22decc
+ * before inspecting the network-layer protocol.
22decc
+ */
22decc
+int net_pull_tags ( struct io_buffer *iobuf, struct net_device *netdev,
22decc
+		    uint16_t *net_proto ) {
22decc
+	struct vlan_header *vlanhdr;
22decc
+	uint16_t tag;
22decc
+
22decc
+	/* Strip 802.1Q VLAN 0 priority tags if present */
22decc
+	while ( *net_proto == htons ( ETH_P_8021Q ) ) {
22decc
+		if ( iob_len ( iobuf ) < sizeof ( *vlanhdr ) ) {
22decc
+			DBG ( "VLAN header too short at %zd bytes (min %zd bytes)\n",
22decc
+			      iob_len ( iobuf ), sizeof ( *vlanhdr ) );
22decc
+			return -EINVAL;
22decc
+		}
22decc
+		vlanhdr = ( struct vlan_header * ) iobuf->data;
22decc
+		tag = VLAN_TAG ( ntohs ( vlanhdr->tci ) );
22decc
+
22decc
+		if ( tag == 0 && ! vlan_find ( netdev, tag ) ) {
22decc
+			/* VLAN 0, strip and continue */
22decc
+			*net_proto = vlanhdr->net_proto;
22decc
+			iob_pull ( iobuf, sizeof ( *vlanhdr ) );
22decc
+		} else {
22decc
+			/* Real VLAN tag, leave it alone */
22decc
+			break;
22decc
+		}
22decc
+	}
22decc
+	return 0;
22decc
+}
22decc
+
22decc
 /**
22decc
  * Poll the network stack
22decc
  *
22decc
@@ -1094,6 +1133,12 @@ void net_poll ( void ) {
22decc
 				continue;
22decc
 			}
22decc
 
22decc
+			/* Remove link-layer-independent headers */
22decc
+			if ( ( rc = net_pull_tags ( iobuf, netdev, &net_proto ) ) ) {
22decc
+				free_iob ( iobuf );
22decc
+				continue;
22decc
+			}
22decc
+
22decc
 			/* Hand packet to network layer */
22decc
 			if ( ( rc = net_rx ( iob_disown ( iobuf ), netdev,
22decc
 					     net_proto, ll_dest,
22decc
@@ -1125,6 +1170,18 @@ __weak unsigned int vlan_tag ( struct net_device *netdev __unused ) {
22decc
 	return 0;
22decc
 }
22decc
 
22decc
+/**
22decc
+ * Identify VLAN device (when VLAN support is not present)
22decc
+ *
22decc
+ * @v netdev           Network device
22decc
+ * @v tag              VLAN tag, or zero
22decc
+ * @v iobuf            I/O buffer
22decc
+ */
22decc
+__weak struct net_device * vlan_find ( struct net_device *trunk __unused,
22decc
+                                      unsigned int tag __unused ) {
22decc
+       return NULL;
22decc
+}
22decc
+
22decc
 /**
22decc
  * Add VLAN tag-stripped packet to queue (when VLAN support is not present)
22decc
  *
22decc
diff --git a/src/net/vlan.c b/src/net/vlan.c
22decc
index 90f2934d..0f234ea5 100644
22decc
--- a/src/net/vlan.c
22decc
+++ b/src/net/vlan.c
22decc
@@ -199,7 +199,7 @@ static void vlan_sync ( struct net_device *netdev ) {
22decc
  * @v tag		VLAN tag
22decc
  * @ret netdev		VLAN device, if any
22decc
  */
22decc
-static struct net_device * vlan_find ( struct net_device *trunk,
22decc
+struct net_device * vlan_find ( struct net_device *trunk,
22decc
 				       unsigned int tag ) {
22decc
 	struct net_device *netdev;
22decc
 	struct vlan_device *vlan;
22decc
-- 
22decc
2.27.0
22decc