diff mbox series

[net-next,v2,11/15] net/smc: Add SMC-D Linkgroup diagnostic support

Message ID 20201103102531.91710-12-kgraul@linux.ibm.com
State Changes Requested
Delegated to: Netdev Driver Reviewers
Headers show
Series net/smc: extend diagnostic netlink interface | expand

Checks

Context Check Description
jkicinski/cover_letter success Link
jkicinski/fixes_present success Link
jkicinski/patch_count success Link
jkicinski/tree_selection success Clearly marked for net-next
jkicinski/subject_prefix success Link
jkicinski/source_inline success Was 0 now: 0
jkicinski/verify_signedoff success Link
jkicinski/module_param success Was 0 now: 0
jkicinski/build_32bit success Errors and warnings before: 0 this patch: 0
jkicinski/kdoc success Errors and warnings before: 0 this patch: 0
jkicinski/verify_fixes success Link
jkicinski/checkpatch success total: 0 errors, 0 warnings, 0 checks, 165 lines checked
jkicinski/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
jkicinski/header_inline success Link
jkicinski/stable success Stable not CCed

Commit Message

Karsten Graul Nov. 3, 2020, 10:25 a.m. UTC
From: Guvenc Gulce <guvenc@linux.ibm.com>

Deliver SMCD Linkgroup information via netlink based
diagnostic interface.

Signed-off-by: Guvenc Gulce <guvenc@linux.ibm.com>
Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
---
 include/uapi/linux/smc_diag.h |   7 +++
 net/smc/smc_diag.c            | 108 ++++++++++++++++++++++++++++++++++
 net/smc/smc_ism.c             |   2 +
 3 files changed, 117 insertions(+)

Comments

Saeed Mahameed Nov. 4, 2020, 1:26 a.m. UTC | #1
On Tue, 2020-11-03 at 11:25 +0100, Karsten Graul wrote:
> From: Guvenc Gulce <guvenc@linux.ibm.com>
> 
> Deliver SMCD Linkgroup information via netlink based
> diagnostic interface.
> 
> Signed-off-by: Guvenc Gulce <guvenc@linux.ibm.com>
> Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
> ---
>  include/uapi/linux/smc_diag.h |   7 +++
>  net/smc/smc_diag.c            | 108
> ++++++++++++++++++++++++++++++++++
>  net/smc/smc_ism.c             |   2 +
>  3 files changed, 117 insertions(+)
> 
> diff --git a/include/uapi/linux/smc_diag.h
> b/include/uapi/linux/smc_diag.h
> index a57df0296aa4..5a80172df757 100644
> --- a/include/uapi/linux/smc_diag.h
> +++ b/include/uapi/linux/smc_diag.h
> @@ -81,6 +81,7 @@ enum {
>  enum {
>  	SMC_DIAG_LGR_INFO_SMCR = 1,
>  	SMC_DIAG_LGR_INFO_SMCR_LINK,
> +	SMC_DIAG_LGR_INFO_SMCD,
>  };
>  
> 
> +
> +static int smc_diag_fill_smcd_dev(struct smcd_dev_list *dev_list,
> +				  struct sk_buff *skb,
> +				  struct netlink_callback *cb,
> +				  struct smc_diag_req_v2 *req)
> +{
> +	struct smc_diag_dump_ctx *cb_ctx = smc_dump_context(cb);
> +	struct smcd_dev *smcd_dev;
> +	int snum = cb_ctx->pos[0];
> +	int rc = 0, num = 0;
> +
> +	mutex_lock(&dev_list->mutex);
> +	list_for_each_entry(smcd_dev, &dev_list->list, list) {
> +		if (!list_empty(&smcd_dev->lgr_list)) {

You could use early continue every where in this patch to avoid
indentation. 

> +			if (num < snum)
> +				goto next;
> +			rc = smc_diag_handle_smcd_lgr(smcd_dev, skb,
> +						      cb, req);
> +			if (rc < 0)
> +				goto errout;
> +next:
> +			num++;
> +		}
> +	}
> +errout:
> +	mutex_unlock(&dev_list->mutex);
> +	cb_ctx->pos[0] = num;
> +	return rc;
> +}
> +
>  static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb,
>  			   struct netlink_callback *cb,
>  			   const struct smc_diag_req *req)
> @@ -441,6 +546,9 @@ static int smc_diag_dump_ext(struct sk_buff *skb,
> struct netlink_callback *cb)
>  		if ((req->cmd_ext & (1 << (SMC_DIAG_LGR_INFO_SMCR -
> 1))))
>  			smc_diag_fill_lgr_list(&smc_lgr_list, skb, cb,
>  					       req);
> +		if ((req->cmd_ext & (1 << (SMC_DIAG_LGR_INFO_SMCD -
> 1))))
> +			smc_diag_fill_smcd_dev(&smcd_dev_list, skb, cb,
> +					       req);
>  	}
>  
>  	return skb->len;
> diff --git a/net/smc/smc_ism.c b/net/smc/smc_ism.c
> index 6abbdd09a580..5bb2c7fb4ea8 100644
> --- a/net/smc/smc_ism.c
> +++ b/net/smc/smc_ism.c
> @@ -20,6 +20,7 @@ struct smcd_dev_list smcd_dev_list = {
>  	.list = LIST_HEAD_INIT(smcd_dev_list.list),
>  	.mutex = __MUTEX_INITIALIZER(smcd_dev_list.mutex)
>  };
> +EXPORT_SYMBOL_GPL(smcd_dev_list);
>  
>  bool smc_ism_v2_capable;
>  
> @@ -50,6 +51,7 @@ u16 smc_ism_get_chid(struct smcd_dev *smcd)
>  {
>  	return smcd->ops->get_chid(smcd);
>  }
> +EXPORT_SYMBOL_GPL(smc_ism_get_chid);
>  

This is the 3rd EXPORT SYMBOL until now in this series,
IMHO it is unhealthy to contaminate the kernel symbol table just for
device specific diag purposes.
diff mbox series

Patch

diff --git a/include/uapi/linux/smc_diag.h b/include/uapi/linux/smc_diag.h
index a57df0296aa4..5a80172df757 100644
--- a/include/uapi/linux/smc_diag.h
+++ b/include/uapi/linux/smc_diag.h
@@ -81,6 +81,7 @@  enum {
 enum {
 	SMC_DIAG_LGR_INFO_SMCR = 1,
 	SMC_DIAG_LGR_INFO_SMCR_LINK,
+	SMC_DIAG_LGR_INFO_SMCD,
 };
 
 #define SMC_DIAG_MAX (__SMC_DIAG_MAX - 1)
@@ -155,6 +156,12 @@  struct smcd_diag_dmbinfo {		/* SMC-D Socket internals */
 	__aligned_u64	my_gid;		/* My GID */
 	__aligned_u64	token;		/* Token of DMB */
 	__aligned_u64	peer_token;	/* Token of remote DMBE */
+	/* Fields above used by legacy v1 code */
+	__u8		pnet_id[SMC_MAX_PNETID_LEN]; /* Pnet ID */
+	__u32		conns_num;	/* Number of connections */
+	__u16		chid;		/* Linkgroup CHID */
+	__u8		vlan_id;	/* Linkgroup vlan id */
+	struct smc_diag_v2_lgr_info v2_lgr_info; /* SMCv2 info */
 };
 
 struct smc_diag_lgr {
diff --git a/net/smc/smc_diag.c b/net/smc/smc_diag.c
index 6885814b6e4f..fcff07a9ea47 100644
--- a/net/smc/smc_diag.c
+++ b/net/smc/smc_diag.c
@@ -21,6 +21,7 @@ 
 
 #include "smc.h"
 #include "smc_ib.h"
+#include "smc_ism.h"
 #include "smc_core.h"
 
 struct smc_diag_dump_ctx {
@@ -252,6 +253,53 @@  static int smc_diag_fill_lgr_link(struct smc_link_group *lgr,
 	return -EMSGSIZE;
 }
 
+static int smc_diag_fill_smcd_lgr(struct smc_link_group *lgr,
+				  struct sk_buff *skb,
+				  struct netlink_callback *cb,
+				  struct smc_diag_req_v2 *req)
+{
+	struct smcd_diag_dmbinfo smcd_lgr;
+	struct nlmsghdr *nlh;
+	int dummy = 0;
+	int rc = 0;
+
+	nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, MAGIC_SEQ_V2_ACK,
+			cb->nlh->nlmsg_type, 0, NLM_F_MULTI);
+	if (!nlh)
+		return -EMSGSIZE;
+
+	memset(&smcd_lgr, 0, sizeof(smcd_lgr));
+	memcpy(&smcd_lgr.linkid, lgr->id, sizeof(lgr->id));
+	smcd_lgr.conns_num = lgr->conns_num;
+	smcd_lgr.vlan_id = lgr->vlan_id;
+	smcd_lgr.peer_gid = lgr->peer_gid;
+	smcd_lgr.my_gid = lgr->smcd->local_gid;
+	smcd_lgr.chid = smc_ism_get_chid(lgr->smcd);
+	memcpy(&smcd_lgr.v2_lgr_info.negotiated_eid, lgr->negotiated_eid,
+	       sizeof(smcd_lgr.v2_lgr_info.negotiated_eid));
+	memcpy(&smcd_lgr.v2_lgr_info.peer_hostname, lgr->peer_hostname,
+	       sizeof(smcd_lgr.v2_lgr_info.peer_hostname));
+	smcd_lgr.v2_lgr_info.peer_os = lgr->peer_os;
+	smcd_lgr.v2_lgr_info.peer_smc_release = lgr->peer_smc_release;
+	smcd_lgr.v2_lgr_info.smc_version = lgr->smc_version;
+	snprintf(smcd_lgr.pnet_id, sizeof(smcd_lgr.pnet_id), "%s",
+		 lgr->smcd->pnetid);
+
+	/* Just a command place holder to signal back the command reply type */
+	if (nla_put(skb, SMC_DIAG_GET_LGR_INFO, sizeof(dummy), &dummy) < 0)
+		goto errout;
+
+	if (nla_put(skb, SMC_DIAG_LGR_INFO_SMCD,
+		    sizeof(smcd_lgr), &smcd_lgr) < 0)
+		goto errout;
+
+	nlmsg_end(skb, nlh);
+	return rc;
+errout:
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
+}
+
 static int smc_diag_fill_lgr(struct smc_link_group *lgr,
 			     struct sk_buff *skb,
 			     struct netlink_callback *cb,
@@ -343,6 +391,63 @@  static int smc_diag_fill_lgr_list(struct smc_lgr_list *smc_lgr,
 	return rc;
 }
 
+static int smc_diag_handle_smcd_lgr(struct smcd_dev *dev,
+				    struct sk_buff *skb,
+				    struct netlink_callback *cb,
+				    struct smc_diag_req_v2 *req)
+{
+	struct smc_diag_dump_ctx *cb_ctx = smc_dump_context(cb);
+	struct smc_link_group *lgr;
+	int snum = cb_ctx->pos[1];
+	int rc = 0, num = 0;
+
+	spin_lock_bh(&dev->lgr_lock);
+	list_for_each_entry(lgr, &dev->lgr_list, list) {
+		if (lgr->is_smcd) {
+			if (num < snum)
+				goto next;
+			rc = smc_diag_fill_smcd_lgr(lgr, skb, cb, req);
+			if (rc < 0)
+				goto errout;
+next:
+			num++;
+		}
+	}
+errout:
+	spin_unlock_bh(&dev->lgr_lock);
+	cb_ctx->pos[1] = num;
+	return rc;
+}
+
+static int smc_diag_fill_smcd_dev(struct smcd_dev_list *dev_list,
+				  struct sk_buff *skb,
+				  struct netlink_callback *cb,
+				  struct smc_diag_req_v2 *req)
+{
+	struct smc_diag_dump_ctx *cb_ctx = smc_dump_context(cb);
+	struct smcd_dev *smcd_dev;
+	int snum = cb_ctx->pos[0];
+	int rc = 0, num = 0;
+
+	mutex_lock(&dev_list->mutex);
+	list_for_each_entry(smcd_dev, &dev_list->list, list) {
+		if (!list_empty(&smcd_dev->lgr_list)) {
+			if (num < snum)
+				goto next;
+			rc = smc_diag_handle_smcd_lgr(smcd_dev, skb,
+						      cb, req);
+			if (rc < 0)
+				goto errout;
+next:
+			num++;
+		}
+	}
+errout:
+	mutex_unlock(&dev_list->mutex);
+	cb_ctx->pos[0] = num;
+	return rc;
+}
+
 static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb,
 			   struct netlink_callback *cb,
 			   const struct smc_diag_req *req)
@@ -441,6 +546,9 @@  static int smc_diag_dump_ext(struct sk_buff *skb, struct netlink_callback *cb)
 		if ((req->cmd_ext & (1 << (SMC_DIAG_LGR_INFO_SMCR - 1))))
 			smc_diag_fill_lgr_list(&smc_lgr_list, skb, cb,
 					       req);
+		if ((req->cmd_ext & (1 << (SMC_DIAG_LGR_INFO_SMCD - 1))))
+			smc_diag_fill_smcd_dev(&smcd_dev_list, skb, cb,
+					       req);
 	}
 
 	return skb->len;
diff --git a/net/smc/smc_ism.c b/net/smc/smc_ism.c
index 6abbdd09a580..5bb2c7fb4ea8 100644
--- a/net/smc/smc_ism.c
+++ b/net/smc/smc_ism.c
@@ -20,6 +20,7 @@  struct smcd_dev_list smcd_dev_list = {
 	.list = LIST_HEAD_INIT(smcd_dev_list.list),
 	.mutex = __MUTEX_INITIALIZER(smcd_dev_list.mutex)
 };
+EXPORT_SYMBOL_GPL(smcd_dev_list);
 
 bool smc_ism_v2_capable;
 
@@ -50,6 +51,7 @@  u16 smc_ism_get_chid(struct smcd_dev *smcd)
 {
 	return smcd->ops->get_chid(smcd);
 }
+EXPORT_SYMBOL_GPL(smc_ism_get_chid);
 
 /* Set a connection using this DMBE. */
 void smc_ism_set_conn(struct smc_connection *conn)