From: Guvenc Gulce <guv...@linux.ibm.com>

Add new netlink command to obtain system information
of the smc module.

Signed-off-by: Guvenc Gulce <guv...@linux.ibm.com>
Signed-off-by: Karsten Graul <kgr...@linux.ibm.com>
---
 include/uapi/linux/smc.h      |  1 +
 include/uapi/linux/smc_diag.h | 18 ++++++++++
 net/smc/smc_clc.c             |  6 ++++
 net/smc/smc_clc.h             |  1 +
 net/smc/smc_diag.c            | 62 +++++++++++++++++++++++++++++++++++
 net/smc/smc_ism.c             |  1 +
 6 files changed, 89 insertions(+)

diff --git a/include/uapi/linux/smc.h b/include/uapi/linux/smc.h
index 736e8b98c8a5..04385a98037a 100644
--- a/include/uapi/linux/smc.h
+++ b/include/uapi/linux/smc.h
@@ -38,6 +38,7 @@ enum {                                /* SMC PNET Table 
commands */
 #define SMC_LGR_ID_SIZE                        4
 #define SMC_MAX_HOSTNAME_LEN           32 /* Max length of hostname */
 #define SMC_MAX_EID_LEN                        32 /* Max length of eid */
+#define SMC_MAX_EID                    8 /* Max number of eids */
 #define SMC_MAX_PORTS                  2 /* Max # of ports per ib device */
 #define SMC_PCI_ID_STR_LEN             16 /* Max length of pci id string */
 #endif /* _UAPI_LINUX_SMC_H */
diff --git a/include/uapi/linux/smc_diag.h b/include/uapi/linux/smc_diag.h
index 4c6332785533..7409e7a854df 100644
--- a/include/uapi/linux/smc_diag.h
+++ b/include/uapi/linux/smc_diag.h
@@ -75,6 +75,7 @@ enum {
 enum {
        SMC_DIAG_GET_LGR_INFO = SMC_DIAG_EXTS_PER_CMD,
        SMC_DIAG_GET_DEV_INFO,
+       SMC_DIAG_GET_SYS_INFO,
        __SMC_DIAG_EXT_MAX,
 };
 
@@ -91,6 +92,11 @@ enum {
        SMC_DIAG_DEV_INFO_SMCR,
 };
 
+/* SMC_DIAG_GET_SYS_INFO command extensions */
+enum {
+       SMC_DIAG_SYS_INFO = 1,
+};
+
 #define SMC_DIAG_MAX (__SMC_DIAG_MAX - 1)
 #define SMC_DIAG_EXT_MAX (__SMC_DIAG_EXT_MAX - 1)
 
@@ -131,6 +137,18 @@ struct smc_diag_v2_lgr_info {
        __u8            peer_hostname[SMC_MAX_HOSTNAME_LEN]; /* Peer host */
 };
 
+
+struct smc_system_info {
+       __u8            smc_version;            /* SMC Version */
+       __u8            smc_release;            /* SMC Release */
+       __u8            ueid_count;             /* Number of UEIDs */
+       __u8            smc_ism_is_v2;          /* Is ISM SMC v2 capable */
+       __u32           reserved;               /* Reserved for future use */
+       __u8            local_hostname[SMC_MAX_HOSTNAME_LEN]; /* Hostnames */
+       __u8            seid[SMC_MAX_EID_LEN];  /* System EID */
+       __u8            ueid[SMC_MAX_EID][SMC_MAX_EID_LEN]; /* User EIDs */
+};
+
 /* SMC_DIAG_LINKINFO */
 
 struct smc_diag_linkinfo {
diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c
index 696d89c2dce4..ca887ee6b249 100644
--- a/net/smc/smc_clc.c
+++ b/net/smc/smc_clc.c
@@ -772,6 +772,12 @@ int smc_clc_send_accept(struct smc_sock *new_smc, bool 
srv_first_contact,
        return len > 0 ? 0 : len;
 }
 
+void smc_clc_get_hostname(u8 **host)
+{
+       *host = &smc_hostname[0];
+}
+EXPORT_SYMBOL_GPL(smc_clc_get_hostname);
+
 void __init smc_clc_init(void)
 {
        struct new_utsname *u;
diff --git a/net/smc/smc_clc.h b/net/smc/smc_clc.h
index e7ab05683bc9..9ed9eb3abe46 100644
--- a/net/smc/smc_clc.h
+++ b/net/smc/smc_clc.h
@@ -334,5 +334,6 @@ int smc_clc_send_confirm(struct smc_sock *smc, bool 
clnt_first_contact,
 int smc_clc_send_accept(struct smc_sock *smc, bool srv_first_contact,
                        u8 version);
 void smc_clc_init(void) __init;
+void smc_clc_get_hostname(u8 **host);
 
 #endif
diff --git a/net/smc/smc_diag.c b/net/smc/smc_diag.c
index 58bfbe0bef4d..a69a401329ab 100644
--- a/net/smc/smc_diag.c
+++ b/net/smc/smc_diag.c
@@ -23,6 +23,7 @@
 #include "smc_ib.h"
 #include "smc_ism.h"
 #include "smc_core.h"
+#include "smc_clc.h"
 
 struct smc_diag_dump_ctx {
        int pos[2];
@@ -650,6 +651,63 @@ static int smc_diag_prep_smcr_dev(struct smc_ib_devices 
*dev_list,
        return rc;
 }
 
+static int smc_diag_prep_sys_info(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 smc_system_info smc_sys_info;
+       int dummy = 0, rc = 0, num = 0;
+       struct smcd_dev *smcd_dev;
+       int snum = cb_ctx->pos[0];
+       struct nlmsghdr *nlh;
+       u8 *seid = NULL;
+       u8 *host = NULL;
+
+       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;
+
+       if (snum > num)
+               goto errout;
+
+       memset(&smc_sys_info, 0, sizeof(smc_sys_info));
+       smc_sys_info.smc_ism_is_v2 = smc_ism_is_v2_capable();
+       smc_sys_info.smc_version = SMC_V2;
+       smc_sys_info.smc_release = SMC_RELEASE;
+       smc_clc_get_hostname(&host);
+
+       if (host)
+               memcpy(smc_sys_info.local_hostname, host,
+                      sizeof(smc_sys_info.local_hostname));
+       mutex_lock(&dev_list->mutex);
+       smcd_dev = list_first_entry_or_null(&dev_list->list, struct smcd_dev, 
list);
+       if (smcd_dev)
+               smc_ism_get_system_eid(smcd_dev, &seid);
+       mutex_unlock(&dev_list->mutex);
+
+       if (seid && smc_sys_info.smc_ism_is_v2)
+               memcpy(smc_sys_info.seid, seid, sizeof(smc_sys_info.seid));
+
+       /* Just a command place holder to signal back the command reply type */
+       if (nla_put(skb, SMC_DIAG_GET_SYS_INFO, sizeof(dummy), &dummy) < 0)
+               goto errout;
+
+       if (nla_put(skb, SMC_DIAG_SYS_INFO,
+                   sizeof(smc_sys_info), &smc_sys_info) < 0)
+               goto errout;
+       nlmsg_end(skb, nlh);
+       num++;
+       cb_ctx->pos[0] = num;
+       return rc;
+
+errout:
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
+}
+
 static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb,
                           struct netlink_callback *cb,
                           const struct smc_diag_req *req)
@@ -758,6 +816,10 @@ static int smc_diag_dump_ext(struct sk_buff *skb, struct 
netlink_callback *cb)
                if ((req->cmd_ext & (1 << (SMC_DIAG_DEV_INFO_SMCR - 1))))
                        smc_diag_prep_smcr_dev(&smc_ib_devices, skb, cb,
                                               req);
+       } else if (req->cmd == SMC_DIAG_GET_SYS_INFO) {
+               if ((req->cmd_ext & (1 << (SMC_DIAG_SYS_INFO - 1))))
+                       smc_diag_prep_sys_info(&smcd_dev_list, skb, cb,
+                                              req);
        }
 
        return skb->len;
diff --git a/net/smc/smc_ism.c b/net/smc/smc_ism.c
index 2a2571637bc6..c3bcca3ca1aa 100644
--- a/net/smc/smc_ism.c
+++ b/net/smc/smc_ism.c
@@ -46,6 +46,7 @@ void smc_ism_get_system_eid(struct smcd_dev *smcd, u8 **eid)
 {
        smcd->ops->get_system_eid(smcd, eid);
 }
+EXPORT_SYMBOL_GPL(smc_ism_get_system_eid);
 
 u16 smc_ism_get_chid(struct smcd_dev *smcd)
 {
-- 
2.17.1

Reply via email to