lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1493786681-27468-6-git-send-email-gwshan@linux.vnet.ibm.com>
Date:   Wed,  3 May 2017 14:44:36 +1000
From:   Gavin Shan <gwshan@...ux.vnet.ibm.com>
To:     netdev@...r.kernel.org
Cc:     joe@...ches.com, kubakici@...pl, f.fainelli@...il.com,
        davem@...emloft.net, Gavin Shan <gwshan@...ux.vnet.ibm.com>
Subject: [PATCH v4 net-next 05/10] net/ncsi: Ethtool operation to get NCSI channel info

This adds ethtool command (ETHTOOL_GNCSICINFO) to retrieve the
NCSI channel information for the specified one. The simplified
output of this command is shown as follows from the modified
(private) ethtool:

 # ethtool --ncsi eth0 info
 NCSI channel 0:0 version:
   version:        00000000
   alpha2:         00000000
   f/w name:
   f/w version:    00000000
   PCI IDs:        0000 0000 0000 0000
   Manufacture ID: 00000000

   Generic capability:   0000000f (0000000f)
   Multicast capability: 00000007 (00000000)
   Buffer capability:    00004000
   AEN capability:       00000007 (00000000)
   VLAN capability:      00000007 (00000000)
   Filters:              VLAN (2), Mixed (0), MC (2), UC (4)

   Link status:             000ff66b 00000000 00000000
   MAC filter entries:
   00:00:00:00:00:00
   48:c4:b6:f0:a6:d4
   b6:fa:8f:70:00:00
   00:00:00:01:07:34
   VLAN filter entries:
   0004
   bc84

Signed-off-by: Gavin Shan <gwshan@...ux.vnet.ibm.com>
---
 include/linux/ethtool.h      |   2 +
 include/uapi/linux/ethtool.h | 151 +++++++++++++++++++++++++++++++++++++++++++
 net/core/ethtool.c           |  22 +++++++
 net/ncsi/ncsi-ethtool.c      | 120 ++++++++++++++++++++++++++++++++++
 4 files changed, 295 insertions(+)

diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 720bb4d..5704b8b 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -376,5 +376,7 @@ struct ethtool_ops {
 				      const struct ethtool_link_ksettings *);
 	int	(*get_ncsi_channels)(struct net_device *,
 				     struct ethtool_ncsi_channels *);
+	int	(*get_ncsi_channel_info)(struct net_device *,
+					 struct ethtool_ncsi_channel_info *);
 };
 #endif /* _LINUX_ETHTOOL_H */
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index e43aacf..81fbd51 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -1332,6 +1332,7 @@ struct ethtool_per_queue_op {
 #define ETHTOOL_PHY_STUNABLE	0x0000004f /* Set PHY tunable configuration */
 
 #define ETHTOOL_GNCSICHANNELS	0x00000050 /* Get NCSI channels */
+#define ETHTOOL_GNCSICINFO	0x00000051 /* Get NCSI channel information */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
@@ -1780,4 +1781,154 @@ struct ethtool_ncsi_channels {
 #define ETHTOOL_NCSI_CHANNEL_ACTIVE	(1 << 8)
 #define ETHTOOL_NCSI_CHANNEL_FLAGS	0x100
 };
+
+/**
+ * struct ethtool_ncsi_channel_info - NCSI channel information
+ *
+ * @cmd: Command number = %ETHTOOL_GNCSICINFO
+ * @id:  NCSI channel identifier
+ * @version: BCD encoded NCSI version
+ * @alpha2: BCD encoded NCSI version
+ * @fw_name: Firmware name string
+ * @fw_version: Firmware version
+ * @pci_ids: PCI identifier
+ * @mf_id: Manufacture identifier
+ * @cap_generic: Generic capability list
+ * @cap_bc: Broadcast capability list
+ * @setting_bc: Broadcast filtering setting
+ * @cap_mc: Multicast capability list
+ * @setting_mc: Multicast filtering setting
+ * @cap_buf: Length of receive buffer
+ * @cap_aen: AEN capability list
+ * @setting_aen: AEN setting
+ * @cap_vlan: VLAN filtering capability list
+ * @setting_vlan: VLAN filltering setting
+ * @cap_vlan_filter: Number of VLAN filtering entries
+ * @cap_mixed_filter: Number of mixed filtering entries
+ * @cap_mc_filter: Number of multicast filtering entries
+ * @cap_uc_filter: Number of unicast filtering entries
+ * @link_status: Link status
+ * @link_other_ind: Link other indication
+ * @link_oem: Link OEM information
+ * @mac_valid_bits: Bitmap for valid MAC filtering entries
+ * @mac: MAC filtering entries
+ * @vlan_valid_bits: Bitmap for valid VLAN filtering entries
+ * @vlan: VLAN filtering entries
+ */
+struct ethtool_ncsi_channel_info {
+	__u32	cmd;
+	__u32	id;
+	__u32	version;
+	__u32	alpha2;
+	__u8	fw_name[12];
+	__u32	fw_version;
+	__u16	pci_ids[4];
+	__u32	mf_id;
+	__u32	cap_generic;
+#define ETHTOOL_NCSI_G_HWA             (1 << 0) /* HW arbitration           */
+#define ETHTOOL_NCSI_G_HDS             (1 << 1) /* HNC driver status change */
+#define ETHTOOL_NCSI_G_FC              (1 << 2) /* HNC to MC flow control   */
+#define ETHTOOL_NCSI_G_FC1             (1 << 3) /* MC to HNC flow control   */
+#define ETHTOOL_NCSI_G_MC              (1 << 4) /* Global MC filtering      */
+#define ETHTOOL_NCSI_G_HWA_MASK        0x60
+#define ETHTOOL_NCSI_G_HWA_UNKNOWN     0x00     /* Unknown HW arbitration   */
+#define ETHTOOL_NCSI_G_HWA_SUPPORT     0x20     /* Supported HW arbitration */
+#define ETHTOOL_NCSI_G_HWA_NOT_SUPPORT 0x40     /* No HW arbitration        */
+#define ETHTOOL_NCSI_G_HWA_RESERVED    0x60     /* Reserved HW arbitration  */
+#define ETHTOOL_NCSI_G_MASK            0x7f
+	__u32	cap_bc;
+	__u32	setting_bc;
+#define ETHTOOL_NCSI_BC_ARP            (1 << 0) /* ARP packet filtering     */
+#define ETHTOOL_NCSI_BC_DHCPC          (1 << 1) /* DHCP client filtering    */
+#define ETHTOOL_NCSI_BC_DHCPS          (1 << 2) /* DHCP server filtering    */
+#define ETHTOOL_NCSI_BC_NETBIOS        (1 << 3) /* NetBIOS packet filtering */
+#define ETHTOOL_NCSI_BC_MASK           0xf
+	__u32	cap_mc;
+	__u32	setting_mc;
+#define ETHTOOL_NCSI_MC_IPV6_NEIGHBOR     (1 << 0) /* IPv6 neighbor filter  */
+#define ETHTOOL_NCSI_MC_IPV6_ROUTER       (1 << 1) /* IPv6 router filter    */
+#define ETHTOOL_NCSI_MC_DHCPV6_RELAY      (1 << 2) /* DHCPv6 relay/server   */
+#define ETHTOOL_NCSI_MC_DHCPV6_WELL_KNOWN (1 << 3) /* DHCPv6 well-known MC  */
+#define ETHTOOL_NCSI_MC_IPV6_MLD          (1 << 4) /* IPv6 MLD filtering    */
+#define ETHTOOL_NCSI_MC_IPV6_NEIGHBOR_S   (1 << 5) /* IPv6 neighbour filter */
+#define ETHTOOL_NCSI_MC_MASK              0x3f
+	__u32	cap_buf;
+	__u32	cap_aen;
+	__u32	setting_aen;
+#define ETHTOOL_NCSI_AEN_LSC           (1 << 0) /* Link status change       */
+#define ETHTOOL_NCSI_AEN_CR            (1 << 1) /* Configuration required   */
+#define ETHTOOL_NCSI_AEN_HDS           (1 << 2) /* HNC driver status        */
+#define ETHTOOL_NCSI_AEN_MASK          0x07
+	__u32	cap_vlan;
+	__u32	setting_vlan;
+#define ETHTOOL_NCSI_VLAN_ONLY         (1 << 0) /* Filter VLAN packet only  */
+#define ETHTOOL_NCSI_VLAN_NO           (1 << 1) /* Filter VLAN and non-VLAN */
+#define ETHTOOL_NCSI_VLAN_ANY          (1 << 2) /* Filter Any-and-non-VLAN  */
+#define ETHTOOL_NCSI_VLAN_MASK         0x07
+	__u8	cap_vlan_filter;
+	__u8	cap_mixed_filter;
+	__u8	cap_mc_filter;
+	__u8	cap_uc_filter;
+	__u32	link_status;
+#define ETHTOOL_NCSI_LINK_UP               (1 << 0)  /* Link up or down       */
+#define ETHTOOL_NCSI_LINK_SPEED_MASK       0x1e      /* Link speed            */
+#define ETHTOOL_NCSI_LINK_SPEED_INVALID         0x0
+#define ETHTOOL_NCSI_LINK_SPEED_10BASE_T_H      0x2
+#define ETHTOOL_NCSI_LINK_SPEED_10BASE_T_F      0x4
+#define ETHTOOL_NCSI_LINK_SPEED_100BASE_TX_H    0x6
+#define ETHTOOL_NCSI_LINK_SPEED_100BASE_T4      0x8
+#define ETHTOOL_NCSI_LINK_SPEED_100BASE_TX_F    0xa
+#define ETHTOOL_NCSI_LINK_SPEED_1000BASE_T_H    0xc
+#define ETHTOOL_NCSI_LINK_SPEED_1000BASE_T_F    0xe
+#define ETHTOOL_NCSI_LINK_SPEED_10GBASE_T       0x10
+#define ETHTOOL_NCSI_LINK_SPEED_20G             0x12
+#define ETHTOOL_NCSI_LINK_SPEED_25G             0x14
+#define ETHTOOL_NCSI_LINK_SPEED_40G             0x16
+#define ETHTOOL_NCSI_LINK_SPEED_50G             0x18
+#define ETHTOOL_NCSI_LINK_SPEED_100G            0x1a
+#define ETHTOOL_NCSI_LINK_SPEED_2_5G            0x1c
+#define ETHTOOL_NCSI_LINK_SPEED_OPTIONAL        0x1e
+#define ETHTOOL_NCSI_LINK_AUTONEG_ENABLED  (1 << 5)  /* Enabled auto-neg      */
+#define ETHTOOL_NCSI_LINK_AUTONEG_DONE     (1 << 6)  /* Auto-neg is done      */
+#define ETHTOOL_NCSI_LINK_PARALLEL         (1 << 7)  /* Parallel detection    */
+#define ETHTOOL_NCSI_LINK_LPA_1000BASE_T_F (1 << 9)  /* LPA: 1000BASE_T_Full  */
+#define ETHTOOL_NCSI_LINK_LPA_1000BASE_T_H (1 << 10) /* LPA: 1000BASE_T_Half  */
+#define ETHTOOL_NCSI_LINK_LPA_100_T4       (1 << 11) /* LPA: 100T4            */
+#define ETHTOOL_NCSI_LINK_LPA_100BASE_TX_F (1 << 12) /* LPA: 100BASE_TX_Full  */
+#define ETHTOOL_NCSI_LINK_LPA_100BASE_TX_H (1 << 13) /* LPA: 100BASE_TX_Half  */
+#define ETHTOOL_NCSI_LINK_LPA_10BASE_T_F   (1 << 14) /* LPA: 10BASE_T_Full    */
+#define ETHTOOL_NCSI_LINK_LPA_10BASE_T_H   (1 << 15) /* LPA: 10BASE_T_Half    */
+#define ETHTOOL_NCSI_LINK_TX_FC            (1 << 16) /* Tx flow control       */
+#define ETHTOOL_NCSI_LINK_RX_FC            (1 << 17) /* Rx flow control       */
+#define ETHTOOL_NCSI_LINK_LPA_FC_MASK      0xc0000
+#define ETHTOOL_NCSI_LINK_LPA_FC_NONE      0x0
+#define ETHTOOL_NCSI_LINK_LPA_FC_SYNC      0x40000
+#define ETHTOOL_NCSI_LINK_LPA_FC_ASYNC     0x80000
+#define ETHTOOL_NCSI_LINK_SERDES           (1 << 20) /* SerDes used or not    */
+#define ETHTOOL_NCSI_LINK_OEM_VALID        (1 << 21)
+#define ETHTOOL_NCSI_LINK_ESPEED_MASK      0xff000000
+#define ETHTOOL_NCSI_LINK_ESPEED_INVALID          0x0
+#define ETHTOOL_NCSI_LINK_ESPEED_10BASE_T_H       0x01000000
+#define ETHTOOL_NCSI_LINK_ESPEED_10BASE_T_F       0x02000000
+#define ETHTOOL_NCSI_LINK_ESPEED_100BASE_TX_H     0x03000000
+#define ETHTOOL_NCSI_LINK_ESPEED_100BASE_T4       0x04000000
+#define ETHTOOL_NCSI_LINK_ESPEED_100BASE_TX_F     0x05000000
+#define ETHTOOL_NCSI_LINK_ESPEED_1000BASE_T_H     0x06000000
+#define ETHTOOL_NCSI_LINK_ESPEED_1000BASE_T_F     0x07000000
+#define ETHTOOL_NCSI_LINK_ESPEED_10GBASE_T        0x08000000
+#define ETHTOOL_NCSI_LINK_ESPEED_20G              0x09000000
+#define ETHTOOL_NCSI_LINK_ESPEED_25G              0x0a000000
+#define ETHTOOL_NCSI_LINK_ESPEED_40G              0x0b000000
+#define ETHTOOL_NCSI_LINK_ESPEED_50G              0x0c000000
+#define ETHTOOL_NCSI_LINK_ESPEED_100G             0x0d000000
+#define ETHTOOL_NCSI_LINK_ESPEED_2_5G             0x0e000000
+#define ETHTOOL_NCSI_LINK_ESPEED_OPTIONAL         0x0f000000
+	__u32	link_other_ind;
+#define ETHTOOL_NCSI_LINK_HNC_DRV_STATUS   (1 << 0)
+	__u32	link_oem;
+	__u32	mac_valid_bits;
+	__u8	mac[8][6];
+	__u32	vlan_valid_bits;
+	__u16	vlan[16];
+};
 #endif /* _UAPI_LINUX_ETHTOOL_H */
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 7644765..116ef10 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -793,6 +793,25 @@ static int ethtool_get_ncsi_channels(struct net_device *dev,
 	return ret;
 }
 
+static int ethtool_get_ncsi_channel_info(struct net_device *dev,
+					 void __user *useraddr)
+{
+	struct ethtool_ncsi_channel_info enci;
+	int ret;
+
+	if (!dev->ethtool_ops->get_ncsi_channel_info)
+		return -EOPNOTSUPP;
+
+	if (copy_from_user(&enci, useraddr, sizeof(enci)))
+		return -EFAULT;
+
+	ret = dev->ethtool_ops->get_ncsi_channel_info(dev, &enci);
+	if (!ret && copy_to_user(useraddr, &enci, sizeof(enci)))
+		return -EFAULT;
+
+	return ret;
+}
+
 static void
 warn_incomplete_ethtool_legacy_settings_conversion(const char *details)
 {
@@ -2833,6 +2852,9 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 	case ETHTOOL_GNCSICHANNELS:
 		rc = ethtool_get_ncsi_channels(dev, useraddr);
 		break;
+	case ETHTOOL_GNCSICINFO:
+		rc = ethtool_get_ncsi_channel_info(dev, useraddr);
+		break;
 	default:
 		rc = -EOPNOTSUPP;
 	}
diff --git a/net/ncsi/ncsi-ethtool.c b/net/ncsi/ncsi-ethtool.c
index 747aab6..9eee5fb 100644
--- a/net/ncsi/ncsi-ethtool.c
+++ b/net/ncsi/ncsi-ethtool.c
@@ -57,6 +57,124 @@ static int ncsi_get_channels(struct net_device *dev,
 	return 0;
 }
 
+static int ncsi_get_channel_info(struct net_device *dev,
+				 struct ethtool_ncsi_channel_info *enci)
+{
+	struct ncsi_dev *nd;
+	struct ncsi_dev_priv *ndp;
+	struct ncsi_channel *nc;
+	unsigned long flags;
+	int i;
+
+	nd = ncsi_find_dev(dev);
+	if (!nd)
+		return -ENXIO;
+
+	ndp = TO_NCSI_DEV_PRIV(nd);
+	ncsi_find_package_and_channel(ndp, enci->id, NULL, &nc);
+	if (!nc)
+		return -ENXIO;
+
+	spin_lock_irqsave(&nc->lock, flags);
+
+	/* NCSI channel's version */
+	enci->version = nc->version.version;
+	enci->alpha2 = nc->version.alpha2;
+	memcpy(enci->fw_name, nc->version.fw_name, 12);
+	enci->fw_version = nc->version.fw_version;
+	memcpy(enci->pci_ids, nc->version.pci_ids,
+	       4 * sizeof(enci->pci_ids[0]));
+	enci->mf_id = nc->version.mf_id;
+
+	/* NCSI channel's capabilities */
+	enci->cap_generic = (nc->caps[NCSI_CAP_GENERIC].cap &
+			     ETHTOOL_NCSI_G_MASK);
+	enci->cap_bc = (nc->caps[NCSI_CAP_BC].cap &
+			ETHTOOL_NCSI_BC_MASK);
+	enci->cap_mc = (nc->caps[NCSI_CAP_MC].cap &
+			ETHTOOL_NCSI_MC_MASK);
+	enci->cap_buf = nc->caps[NCSI_CAP_BUFFER].cap;
+	enci->cap_aen = (nc->caps[NCSI_CAP_AEN].cap &
+			 ETHTOOL_NCSI_AEN_MASK);
+	enci->cap_vlan = (nc->caps[NCSI_CAP_VLAN].cap &
+			  ETHTOOL_NCSI_VLAN_MASK);
+	for (i = NCSI_FILTER_BASE; i < NCSI_FILTER_MAX; i++) {
+		struct ncsi_channel_filter *ncf;
+		unsigned char *p_cap_filter;
+		unsigned int *p_valid_bits;
+		int entry_size, s_idx, d_idx;
+		void *dest;
+
+		switch (i) {
+		case NCSI_FILTER_VLAN:
+			p_cap_filter = &enci->cap_vlan_filter;
+			entry_size = 2;
+			p_valid_bits = &enci->vlan_valid_bits;
+			dest = enci->vlan;
+			d_idx = 0;
+			break;
+		case NCSI_FILTER_UC:
+			p_cap_filter = &enci->cap_uc_filter;
+			entry_size = 6;
+			p_valid_bits = &enci->mac_valid_bits;
+			dest = enci->mac;
+			d_idx = 0;
+			break;
+		case NCSI_FILTER_MC:
+			p_cap_filter = &enci->cap_mc_filter;
+			entry_size = 6;
+			break;
+		case NCSI_FILTER_MIXED:
+			p_cap_filter = &enci->cap_mixed_filter;
+			entry_size = 6;
+			break;
+		default:
+			continue;
+		}
+
+		*p_cap_filter = 0;
+		ncf = nc->filters[i];
+		if (!ncf)
+			continue;
+
+		*p_cap_filter = ncf->total;
+		s_idx = -1;
+		while ((s_idx = find_next_bit((void *)&ncf->bitmap,
+					      ncf->total, s_idx + 1))
+			< ncf->total) {
+			memcpy(dest + (d_idx * entry_size),
+			       ((void *)(ncf->data)) + (s_idx * entry_size),
+			       entry_size);
+			*p_valid_bits |= (1 << d_idx);
+
+			d_idx++;
+		}
+	}
+
+	/* NCSI channel's settings */
+	enci->setting_bc = nc->modes[NCSI_MODE_BC].enable ?
+			   nc->modes[NCSI_MODE_BC].data[0] : 0;
+	enci->setting_bc &= ETHTOOL_NCSI_BC_MASK;
+	enci->setting_mc = nc->modes[NCSI_MODE_MC].enable ?
+			   nc->modes[NCSI_MODE_MC].data[0] : 0;
+	enci->setting_mc &= ETHTOOL_NCSI_MC_MASK;
+	enci->setting_aen = nc->modes[NCSI_MODE_AEN].enable ?
+			    nc->modes[NCSI_MODE_AEN].data[0] : 0;
+	enci->setting_aen &= ETHTOOL_NCSI_AEN_MASK;
+	enci->setting_vlan = nc->modes[NCSI_MODE_VLAN].enable ?
+			     nc->modes[NCSI_MODE_VLAN].data[0] : 0;
+	enci->setting_vlan &= ETHTOOL_NCSI_VLAN_MASK;
+
+	/* NCSI channel's link status */
+	enci->link_status = nc->modes[NCSI_MODE_LINK].data[2];
+	enci->link_other_ind = nc->modes[NCSI_MODE_LINK].data[3];
+	enci->link_oem = nc->modes[NCSI_MODE_LINK].data[4];
+
+	spin_unlock_irqrestore(&nc->lock, flags);
+
+	return 0;
+}
+
 void ncsi_ethtool_register_dev(struct net_device *dev)
 {
 	struct ethtool_ops *ops;
@@ -66,6 +184,7 @@ void ncsi_ethtool_register_dev(struct net_device *dev)
 		return;
 
 	ops->get_ncsi_channels = ncsi_get_channels;
+	ops->get_ncsi_channel_info = ncsi_get_channel_info;
 }
 
 void ncsi_ethtool_unregister_dev(struct net_device *dev)
@@ -77,4 +196,5 @@ void ncsi_ethtool_unregister_dev(struct net_device *dev)
 		return;
 
 	ops->get_ncsi_channels = NULL;
+	ops->get_ncsi_channel_info = NULL;
 }
-- 
2.7.4

Powered by blists - more mailing lists