Commit 50e63d6d authored by Enzo Matsumiya's avatar Enzo Matsumiya Committed by Steve French
Browse files

smb/client: print "Unknown" instead of bogus link speed value



The virtio driver for Linux guests will not set a link speed to its
paravirtualized NICs.  This will be seen as -1 in the ethernet layer, and
when some servers (e.g. samba) fetches it, it's converted to an unsigned
value (and multiplied by 1000 * 1000), so in client side we end up with:

1)      Speed: 4294967295000000 bps

in DebugData.

This patch introduces a helper that returns a speed string (in Mbps or
Gbps) if interface speed is valid (>= SPEED_10 and <= SPEED_800000), or
"Unknown" otherwise.

The reason to not change the value in iface->speed is because we don't
know the real speed of the HW backing the server NIC, so let's keep
considering these as the fastest NICs available.

Also print "Capabilities: None" when the interface doesn't support any.

Signed-off-by: default avatarEnzo Matsumiya <ematsumiya@suse.de>
Reviewed-by: default avatarShyam Prasad N <sprasad@microsoft.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 2a44b389
Loading
Loading
Loading
Loading
+46 −1
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <uapi/linux/ethtool.h>
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
@@ -148,18 +149,62 @@ cifs_dump_channel(struct seq_file *m, int i, struct cifs_chan *chan)
		   atomic_read(&server->num_waiters));
}

static inline const char *smb_speed_to_str(size_t bps)
{
	size_t mbps = bps / 1000 / 1000;

	switch (mbps) {
	case SPEED_10:
		return "10Mbps";
	case SPEED_100:
		return "100Mbps";
	case SPEED_1000:
		return "1Gbps";
	case SPEED_2500:
		return "2.5Gbps";
	case SPEED_5000:
		return "5Gbps";
	case SPEED_10000:
		return "10Gbps";
	case SPEED_14000:
		return "14Gbps";
	case SPEED_20000:
		return "20Gbps";
	case SPEED_25000:
		return "25Gbps";
	case SPEED_40000:
		return "40Gbps";
	case SPEED_50000:
		return "50Gbps";
	case SPEED_56000:
		return "56Gbps";
	case SPEED_100000:
		return "100Gbps";
	case SPEED_200000:
		return "200Gbps";
	case SPEED_400000:
		return "400Gbps";
	case SPEED_800000:
		return "800Gbps";
	default:
		return "Unknown";
	}
}

static void
cifs_dump_iface(struct seq_file *m, struct cifs_server_iface *iface)
{
	struct sockaddr_in *ipv4 = (struct sockaddr_in *)&iface->sockaddr;
	struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&iface->sockaddr;

	seq_printf(m, "\tSpeed: %zu bps\n", iface->speed);
	seq_printf(m, "\tSpeed: %s\n", smb_speed_to_str(iface->speed));
	seq_puts(m, "\t\tCapabilities: ");
	if (iface->rdma_capable)
		seq_puts(m, "rdma ");
	if (iface->rss_capable)
		seq_puts(m, "rss ");
	if (!iface->rdma_capable && !iface->rss_capable)
		seq_puts(m, "None");
	seq_putc(m, '\n');
	if (iface->sockaddr.ss_family == AF_INET)
		seq_printf(m, "\t\tIPv4: %pI4\n", &ipv4->sin_addr);