net/smc: add netlink support for SMC-Rv2
authorKarsten Graul <kgraul@linux.ibm.com>
Sat, 16 Oct 2021 09:37:51 +0000 (11:37 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sat, 16 Oct 2021 13:58:13 +0000 (14:58 +0100)
Implement the netlink support for SMC-Rv2 related attributes that are
provided to user space.

Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/smc.h
net/smc/smc_core.c

index b175bd0..20f33b2 100644 (file)
@@ -84,17 +84,28 @@ enum {
        SMC_NLA_SYS_IS_ISM_V2,          /* u8 */
        SMC_NLA_SYS_LOCAL_HOST,         /* string */
        SMC_NLA_SYS_SEID,               /* string */
+       SMC_NLA_SYS_IS_SMCR_V2,         /* u8 */
        __SMC_NLA_SYS_MAX,
        SMC_NLA_SYS_MAX = __SMC_NLA_SYS_MAX - 1
 };
 
-/* SMC_NLA_LGR_V2 nested attributes */
+/* SMC_NLA_LGR_D_V2_COMMON and SMC_NLA_LGR_R_V2_COMMON nested attributes */
 enum {
        SMC_NLA_LGR_V2_VER,             /* u8 */
        SMC_NLA_LGR_V2_REL,             /* u8 */
        SMC_NLA_LGR_V2_OS,              /* u8 */
        SMC_NLA_LGR_V2_NEG_EID,         /* string */
        SMC_NLA_LGR_V2_PEER_HOST,       /* string */
+       __SMC_NLA_LGR_V2_MAX,
+       SMC_NLA_LGR_V2_MAX = __SMC_NLA_LGR_V2_MAX - 1
+};
+
+/* SMC_NLA_LGR_R_V2 nested attributes */
+enum {
+       SMC_NLA_LGR_R_V2_UNSPEC,
+       SMC_NLA_LGR_R_V2_DIRECT,        /* u8 */
+       __SMC_NLA_LGR_R_V2_MAX,
+       SMC_NLA_LGR_R_V2_MAX = __SMC_NLA_LGR_R_V2_MAX - 1
 };
 
 /* SMC_GEN_LGR_SMCR attributes */
@@ -106,6 +117,8 @@ enum {
        SMC_NLA_LGR_R_PNETID,           /* string */
        SMC_NLA_LGR_R_VLAN_ID,          /* u8 */
        SMC_NLA_LGR_R_CONNS_NUM,        /* u32 */
+       SMC_NLA_LGR_R_V2_COMMON,        /* nest */
+       SMC_NLA_LGR_R_V2,               /* nest */
        __SMC_NLA_LGR_R_MAX,
        SMC_NLA_LGR_R_MAX = __SMC_NLA_LGR_R_MAX - 1
 };
@@ -138,7 +151,7 @@ enum {
        SMC_NLA_LGR_D_PNETID,           /* string */
        SMC_NLA_LGR_D_CHID,             /* u16 */
        SMC_NLA_LGR_D_PAD,              /* flag */
-       SMC_NLA_LGR_V2,                 /* nest */
+       SMC_NLA_LGR_D_V2_COMMON,        /* nest */
        __SMC_NLA_LGR_D_MAX,
        SMC_NLA_LGR_D_MAX = __SMC_NLA_LGR_D_MAX - 1
 };
index 1ccab99..8e642f8 100644 (file)
@@ -244,6 +244,8 @@ int smc_nl_get_sys_info(struct sk_buff *skb, struct netlink_callback *cb)
                goto errattr;
        if (nla_put_u8(skb, SMC_NLA_SYS_IS_ISM_V2, smc_ism_is_v2_capable()))
                goto errattr;
+       if (nla_put_u8(skb, SMC_NLA_SYS_IS_SMCR_V2, true))
+               goto errattr;
        smc_clc_get_hostname(&host);
        if (host) {
                memcpy(hostname, host, SMC_MAX_HOSTNAME_LEN);
@@ -271,12 +273,65 @@ errmsg:
        return skb->len;
 }
 
+/* Fill SMC_NLA_LGR_D_V2_COMMON/SMC_NLA_LGR_R_V2_COMMON nested attributes */
+static int smc_nl_fill_lgr_v2_common(struct smc_link_group *lgr,
+                                    struct sk_buff *skb,
+                                    struct netlink_callback *cb,
+                                    struct nlattr *v2_attrs)
+{
+       char smc_host[SMC_MAX_HOSTNAME_LEN + 1];
+       char smc_eid[SMC_MAX_EID_LEN + 1];
+
+       if (nla_put_u8(skb, SMC_NLA_LGR_V2_VER, lgr->smc_version))
+               goto errv2attr;
+       if (nla_put_u8(skb, SMC_NLA_LGR_V2_REL, lgr->peer_smc_release))
+               goto errv2attr;
+       if (nla_put_u8(skb, SMC_NLA_LGR_V2_OS, lgr->peer_os))
+               goto errv2attr;
+       memcpy(smc_host, lgr->peer_hostname, SMC_MAX_HOSTNAME_LEN);
+       smc_host[SMC_MAX_HOSTNAME_LEN] = 0;
+       if (nla_put_string(skb, SMC_NLA_LGR_V2_PEER_HOST, smc_host))
+               goto errv2attr;
+       memcpy(smc_eid, lgr->negotiated_eid, SMC_MAX_EID_LEN);
+       smc_eid[SMC_MAX_EID_LEN] = 0;
+       if (nla_put_string(skb, SMC_NLA_LGR_V2_NEG_EID, smc_eid))
+               goto errv2attr;
+
+       nla_nest_end(skb, v2_attrs);
+       return 0;
+
+errv2attr:
+       nla_nest_cancel(skb, v2_attrs);
+       return -EMSGSIZE;
+}
+
+static int smc_nl_fill_smcr_lgr_v2(struct smc_link_group *lgr,
+                                  struct sk_buff *skb,
+                                  struct netlink_callback *cb)
+{
+       struct nlattr *v2_attrs;
+
+       v2_attrs = nla_nest_start(skb, SMC_NLA_LGR_R_V2);
+       if (!v2_attrs)
+               goto errattr;
+       if (nla_put_u8(skb, SMC_NLA_LGR_R_V2_DIRECT, !lgr->uses_gateway))
+               goto errv2attr;
+
+       nla_nest_end(skb, v2_attrs);
+       return 0;
+
+errv2attr:
+       nla_nest_cancel(skb, v2_attrs);
+errattr:
+       return -EMSGSIZE;
+}
+
 static int smc_nl_fill_lgr(struct smc_link_group *lgr,
                           struct sk_buff *skb,
                           struct netlink_callback *cb)
 {
        char smc_target[SMC_MAX_PNETID_LEN + 1];
-       struct nlattr *attrs;
+       struct nlattr *attrs, *v2_attrs;
 
        attrs = nla_nest_start(skb, SMC_GEN_LGR_SMCR);
        if (!attrs)
@@ -296,6 +351,15 @@ static int smc_nl_fill_lgr(struct smc_link_group *lgr,
        smc_target[SMC_MAX_PNETID_LEN] = 0;
        if (nla_put_string(skb, SMC_NLA_LGR_R_PNETID, smc_target))
                goto errattr;
+       if (lgr->smc_version > SMC_V1) {
+               v2_attrs = nla_nest_start(skb, SMC_NLA_LGR_R_V2_COMMON);
+               if (!v2_attrs)
+                       goto errattr;
+               if (smc_nl_fill_lgr_v2_common(lgr, skb, cb, v2_attrs))
+                       goto errattr;
+               if (smc_nl_fill_smcr_lgr_v2(lgr, skb, cb))
+                       goto errattr;
+       }
 
        nla_nest_end(skb, attrs);
        return 0;
@@ -428,10 +492,7 @@ static int smc_nl_fill_smcd_lgr(struct smc_link_group *lgr,
                                struct sk_buff *skb,
                                struct netlink_callback *cb)
 {
-       char smc_host[SMC_MAX_HOSTNAME_LEN + 1];
        char smc_pnet[SMC_MAX_PNETID_LEN + 1];
-       char smc_eid[SMC_MAX_EID_LEN + 1];
-       struct nlattr *v2_attrs;
        struct nlattr *attrs;
        void *nlh;
 
@@ -463,32 +524,19 @@ static int smc_nl_fill_smcd_lgr(struct smc_link_group *lgr,
        smc_pnet[SMC_MAX_PNETID_LEN] = 0;
        if (nla_put_string(skb, SMC_NLA_LGR_D_PNETID, smc_pnet))
                goto errattr;
+       if (lgr->smc_version > SMC_V1) {
+               struct nlattr *v2_attrs;
 
-       v2_attrs = nla_nest_start(skb, SMC_NLA_LGR_V2);
-       if (!v2_attrs)
-               goto errattr;
-       if (nla_put_u8(skb, SMC_NLA_LGR_V2_VER, lgr->smc_version))
-               goto errv2attr;
-       if (nla_put_u8(skb, SMC_NLA_LGR_V2_REL, lgr->peer_smc_release))
-               goto errv2attr;
-       if (nla_put_u8(skb, SMC_NLA_LGR_V2_OS, lgr->peer_os))
-               goto errv2attr;
-       memcpy(smc_host, lgr->peer_hostname, SMC_MAX_HOSTNAME_LEN);
-       smc_host[SMC_MAX_HOSTNAME_LEN] = 0;
-       if (nla_put_string(skb, SMC_NLA_LGR_V2_PEER_HOST, smc_host))
-               goto errv2attr;
-       memcpy(smc_eid, lgr->negotiated_eid, SMC_MAX_EID_LEN);
-       smc_eid[SMC_MAX_EID_LEN] = 0;
-       if (nla_put_string(skb, SMC_NLA_LGR_V2_NEG_EID, smc_eid))
-               goto errv2attr;
-
-       nla_nest_end(skb, v2_attrs);
+               v2_attrs = nla_nest_start(skb, SMC_NLA_LGR_D_V2_COMMON);
+               if (!v2_attrs)
+                       goto errattr;
+               if (smc_nl_fill_lgr_v2_common(lgr, skb, cb, v2_attrs))
+                       goto errattr;
+       }
        nla_nest_end(skb, attrs);
        genlmsg_end(skb, nlh);
        return 0;
 
-errv2attr:
-       nla_nest_cancel(skb, v2_attrs);
 errattr:
        nla_nest_cancel(skb, attrs);
 errout: