Blame SOURCES/0009-Strip-802.1Q-VLAN-0-priority-tags.patch

593ec3
From 2f542b36b149b32325f85ce89a6823ff97a6d675 Mon Sep 17 00:00:00 2001
40e044
From: Ladi Prosek <lprosek@redhat.com>
40e044
Date: Mon, 11 Jul 2016 14:17:36 +0200
c62b1d
Subject: Strip 802.1Q VLAN 0 priority tags
40e044
40e044
RH-Author: Ladi Prosek <lprosek@redhat.com>
40e044
Message-id: <1468246656-15560-1-git-send-email-lprosek@redhat.com>
40e044
Patchwork-id: 71112
40e044
O-Subject: [RHEL7.3 ipxe PATCH] [netdevice] Strip 802.Q VLAN 0 priority tags
40e044
Bugzilla: 1316329
40e044
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
40e044
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
40e044
RH-Acked-by: Xiao Wang <jasowang@redhat.com>
40e044
40e044
iPXE was unable to receive priority tagged packets specified in
40e044
the 802.1Q standard and supported by all major networking stacks.
40e044
40e044
This commit adds a new function net_pull_tags which is called by
40e044
all consumers of incoming packets after stripping their link-layer
40e044
headers.
40e044
40e044
Upstream patch:
40e044
http://lists.ipxe.org/pipermail/ipxe-devel/2016-July/005099.html
40e044
40e044
There is a difference between the upstream patch and this patch in the
40e044
path prefix of "interface/pxe/pxe_undi.c" because we don't have upstream
40e044
commit f468f12b1eca.
40e044
40e044
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
40e044
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
40e044
---
c62b1d
 src/arch/x86/interface/pxe/pxe_undi.c |  6 +++++
c62b1d
 src/include/ipxe/netdevice.h          |  2 ++
c62b1d
 src/interface/efi/efi_snp.c           |  7 ++++++
c62b1d
 src/net/netdevice.c                   | 44 +++++++++++++++++++++++++++++++++++
40e044
 4 files changed, 59 insertions(+)
40e044
c62b1d
diff --git a/src/arch/x86/interface/pxe/pxe_undi.c b/src/arch/x86/interface/pxe/pxe_undi.c
40e044
index 2eb6817..2ea1451 100644
c62b1d
--- a/src/arch/x86/interface/pxe/pxe_undi.c
c62b1d
+++ b/src/arch/x86/interface/pxe/pxe_undi.c
40e044
@@ -976,6 +976,12 @@ static PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
40e044
 		}
40e044
 		ll_hlen = ( len - iob_len ( iobuf ) );
40e044
 
40e044
+		/* Strip link-layer-independent headers */
40e044
+		if ( ( rc = net_pull_tags ( iobuf, pxe_netdev, &net_proto ) ) != 0 ) {
40e044
+			/* Assume unknown net_proto */
40e044
+			net_proto = 0;
40e044
+		}
40e044
+
40e044
 		/* Determine network-layer protocol */
40e044
 		switch ( net_proto ) {
40e044
 		case htons ( ETH_P_IP ):
40e044
diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h
593ec3
index d498ab6..27dda45 100644
40e044
--- a/src/include/ipxe/netdevice.h
40e044
+++ b/src/include/ipxe/netdevice.h
593ec3
@@ -726,6 +726,8 @@ extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
40e044
 extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
40e044
 		    uint16_t net_proto, const void *ll_dest,
40e044
 		    const void *ll_source, unsigned int flags );
40e044
+extern int net_pull_tags ( struct io_buffer *iobuf, struct net_device *netdev,
40e044
+			   uint16_t *net_proto );
40e044
 extern void net_poll ( void );
40e044
 extern struct net_device_configurator *
40e044
 find_netdev_configurator ( const char *name );
40e044
diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c
593ec3
index 9c1b14d..6b974d4 100644
40e044
--- a/src/interface/efi/efi_snp.c
40e044
+++ b/src/interface/efi/efi_snp.c
593ec3
@@ -813,6 +813,13 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
40e044
 		goto out_bad_ll_header;
40e044
 	}
40e044
 
40e044
+	/* Strip link-layer-independent headers */
40e044
+	if ( ( rc = net_pull_tags ( iobuf, snpdev->netdev, &iob_net_proto ) ) ) {
40e044
+		DBGC ( snpdev, "SNPDEV %p could not parse tags: %s\n",
40e044
+		       snpdev, strerror ( rc ) );
40e044
+		goto out_bad_ll_header;
40e044
+	}
40e044
+
40e044
 	/* Return link-layer header parameters to caller, if required */
40e044
 	if ( ll_header_len )
40e044
 		*ll_header_len = ll_protocol->ll_header_len;
40e044
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
593ec3
index 71a37ec..fdf541b 100644
40e044
--- a/src/net/netdevice.c
40e044
+++ b/src/net/netdevice.c
593ec3
@@ -1044,6 +1044,44 @@ int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
40e044
 }
40e044
 
40e044
 /**
40e044
+ * Strip extra link-layer-independent tags from a received packet
40e044
+ *
40e044
+ * @v iobuf		I/O buffer
40e044
+ * @v netdev		Network device
40e044
+ * @v net_proto		Network-layer protocol, in network-byte order
40e044
+ * @ret rc		Return status code
40e044
+ *
40e044
+ * This function should be called after stripping link-layer headers but
40e044
+ * before inspecting the network-layer protocol.
40e044
+ */
40e044
+int net_pull_tags ( struct io_buffer *iobuf, struct net_device *netdev,
40e044
+		    uint16_t *net_proto ) {
40e044
+	struct vlan_header *vlanhdr;
40e044
+	uint16_t tag;
40e044
+
40e044
+	/* Strip 802.1Q VLAN 0 priority tags if present */
40e044
+	while ( *net_proto == htons ( ETH_P_8021Q ) ) {
40e044
+		if ( iob_len ( iobuf ) < sizeof ( *vlanhdr ) ) {
40e044
+			DBG ( "VLAN header too short at %zd bytes (min %zd bytes)\n",
40e044
+			      iob_len ( iobuf ), sizeof ( *vlanhdr ) );
40e044
+			return -EINVAL;
40e044
+		}
40e044
+		vlanhdr = ( struct vlan_header * ) iobuf->data;
40e044
+		tag = VLAN_TAG ( ntohs ( vlanhdr->tci ) );
40e044
+
40e044
+		if ( tag == 0 && ! vlan_find ( netdev, tag ) ) {
40e044
+			/* VLAN 0, strip and continue */
40e044
+			*net_proto = vlanhdr->net_proto;
40e044
+			iob_pull ( iobuf, sizeof ( *vlanhdr ) );
40e044
+		} else {
40e044
+			/* Real VLAN tag, leave it alone */
40e044
+			break;
40e044
+		}
40e044
+	}
40e044
+	return 0;
40e044
+}
40e044
+
40e044
+/**
40e044
  * Poll the network stack
40e044
  *
40e044
  * This polls all interfaces for received packets, and processes
593ec3
@@ -1094,6 +1132,12 @@ void net_poll ( void ) {
40e044
 				continue;
40e044
 			}
40e044
 
40e044
+			/* Remove link-layer-independent headers */
40e044
+			if ( ( rc = net_pull_tags ( iobuf, netdev, &net_proto ) ) ) {
40e044
+				free_iob ( iobuf );
40e044
+				continue;
40e044
+			}
40e044
+
40e044
 			/* Hand packet to network layer */
40e044
 			if ( ( rc = net_rx ( iob_disown ( iobuf ), netdev,
40e044
 					     net_proto, ll_dest,
40e044
-- 
40e044
1.8.3.1
40e044