summaryrefslogtreecommitdiffstats
path: root/src/drivers/net/intelvf.c
diff options
context:
space:
mode:
authorMichael Brown2016-07-11 18:14:14 +0200
committerMichael Brown2016-07-12 10:14:41 +0200
commitdb3443608fe32fffb4f6ad467bfc035a824bff52 (patch)
treef8a2d65147e484ec8eeabc4b2c86d35ac6534119 /src/drivers/net/intelvf.c
parent[ipv4] Send gratuitous ARPs whenever a new IPv4 address is applied (diff)
downloadipxe-db3443608fe32fffb4f6ad467bfc035a824bff52.tar.gz
ipxe-db3443608fe32fffb4f6ad467bfc035a824bff52.tar.xz
ipxe-db3443608fe32fffb4f6ad467bfc035a824bff52.zip
[intel] Strip spurious VLAN tags received by virtual function NICs
The physical function may be configured to transparently insert a VLAN tag into all transmitted packets. Unfortunately, it does not equivalently strip this same VLAN tag from all received packets. This behaviour may be observed in some Amazon EC2 instances with Enhanced Networking enabled: transmissions work as expected but all packets received by iPXE appear to have a spurious VLAN tag. We can configure the receive queue to strip VLAN tags via the RXDCTL.VME bit. We need to find out from the PF driver whether or not we should do so. There exists a "get queue configuration" mailbox message which contains a field labelled IXGBE_VF_TRANS_VLAN in the Linux driver. A comment in the Linux PF driver describes this field as "notify VF of need for VLAN tag stripping, and correct queue". It will be filled with a non-zero value if the PF is enforcing the use of a single VLAN tag. It will also be filled with a non-zero value if the PF is using multiple traffic classes. The Linux VF driver seems to treat this field as being simply the number of traffic classes, and gives it no VLAN-related interpretation. The Linux VF driver instead handles the VLAN tag stripping by simply assuming that any unrecognised VLAN tag ought to be silently dropped. We choose to strip and ignore the VLAN tag if the IXGBE_VF_TRANS_VLAN field has a non-zero value. Reported-by: Leonid Vasetsky <leonidv@velostrata.com> Tested-by: Leonid Vasetsky <leonidv@velostrata.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers/net/intelvf.c')
-rw-r--r--src/drivers/net/intelvf.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/drivers/net/intelvf.c b/src/drivers/net/intelvf.c
index ac6fea74..537e0fbb 100644
--- a/src/drivers/net/intelvf.c
+++ b/src/drivers/net/intelvf.c
@@ -338,3 +338,44 @@ int intelvf_mbox_set_mtu ( struct intel_nic *intel, size_t mtu ) {
return 0;
}
+
+/**
+ * Get queue configuration
+ *
+ * @v intel Intel device
+ * @v vlan_thing VLAN hand-waving thing to fill in
+ * @ret rc Return status code
+ */
+int intelvf_mbox_queues ( struct intel_nic *intel, int *vlan_thing ) {
+ union intelvf_msg msg;
+ int rc;
+
+ /* Send queue configuration message */
+ memset ( &msg, 0, sizeof ( msg ) );
+ msg.hdr = INTELVF_MSG_TYPE_GET_QUEUES;
+ if ( ( rc = intelvf_mbox_msg ( intel, &msg ) ) != 0 ) {
+ DBGC ( intel, "INTEL %p get queue configuration failed: %s\n",
+ intel, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Check response */
+ if ( ( msg.hdr & INTELVF_MSG_TYPE_MASK ) !=INTELVF_MSG_TYPE_GET_QUEUES){
+ DBGC ( intel, "INTEL %p get queue configuration unexpected "
+ "response:\n", intel );
+ DBGC_HDA ( intel, 0, &msg, sizeof ( msg ) );
+ return -EPROTO;
+ }
+
+ /* Check that we were allowed to get the queue configuration */
+ if ( ! ( msg.hdr & INTELVF_MSG_ACK ) ) {
+ DBGC ( intel, "INTEL %p get queue configuration refused\n",
+ intel );
+ return -EPERM;
+ }
+
+ /* Extract VLAN hand-waving thing */
+ *vlan_thing = msg.queues.vlan_thing;
+
+ return 0;
+}