Commit 603cc149 authored by Karsten Graul's avatar Karsten Graul Committed by David S. Miller

net/smc: provide fallback reason code

Remember the fallback reason code and the peer diagnosis code for
smc sockets, and provide them in smc_diag.c to the netlink interface.
And add more detailed reason codes.
Signed-off-by: default avatarKarsten Graul <kgraul@linux.ibm.com>
Signed-off-by: default avatarUrsula Braun <ubraun@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7005ada6
...@@ -43,6 +43,7 @@ enum { ...@@ -43,6 +43,7 @@ enum {
SMC_DIAG_LGRINFO, SMC_DIAG_LGRINFO,
SMC_DIAG_SHUTDOWN, SMC_DIAG_SHUTDOWN,
SMC_DIAG_DMBINFO, SMC_DIAG_DMBINFO,
SMC_DIAG_FALLBACK,
__SMC_DIAG_MAX, __SMC_DIAG_MAX,
}; };
...@@ -92,6 +93,11 @@ struct smc_diag_lgrinfo { ...@@ -92,6 +93,11 @@ struct smc_diag_lgrinfo {
__u8 role; __u8 role;
}; };
struct smc_diag_fallback {
__u32 reason;
__u32 peer_diagnosis;
};
struct smcd_diag_dmbinfo { /* SMC-D Socket internals */ struct smcd_diag_dmbinfo { /* SMC-D Socket internals */
__u32 linkid; /* Link identifier */ __u32 linkid; /* Link identifier */
__u64 peer_gid; /* Peer GID */ __u64 peer_gid; /* Peer GID */
......
...@@ -344,17 +344,17 @@ static int smc_clnt_conf_first_link(struct smc_sock *smc) ...@@ -344,17 +344,17 @@ static int smc_clnt_conf_first_link(struct smc_sock *smc)
rc = smc_ib_modify_qp_rts(link); rc = smc_ib_modify_qp_rts(link);
if (rc) if (rc)
return SMC_CLC_DECL_INTERR; return SMC_CLC_DECL_ERR_RDYLNK;
smc_wr_remember_qp_attr(link); smc_wr_remember_qp_attr(link);
if (smc_reg_rmb(link, smc->conn.rmb_desc, false)) if (smc_reg_rmb(link, smc->conn.rmb_desc, false))
return SMC_CLC_DECL_INTERR; return SMC_CLC_DECL_ERR_REGRMB;
/* send CONFIRM LINK response over RoCE fabric */ /* send CONFIRM LINK response over RoCE fabric */
rc = smc_llc_send_confirm_link(link, SMC_LLC_RESP); rc = smc_llc_send_confirm_link(link, SMC_LLC_RESP);
if (rc < 0) if (rc < 0)
return SMC_CLC_DECL_TCL; return SMC_CLC_DECL_TIMEOUT_CL;
/* receive ADD LINK request from server over RoCE fabric */ /* receive ADD LINK request from server over RoCE fabric */
rest = wait_for_completion_interruptible_timeout(&link->llc_add, rest = wait_for_completion_interruptible_timeout(&link->llc_add,
...@@ -372,7 +372,7 @@ static int smc_clnt_conf_first_link(struct smc_sock *smc) ...@@ -372,7 +372,7 @@ static int smc_clnt_conf_first_link(struct smc_sock *smc)
link->smcibdev->mac[link->ibport - 1], link->smcibdev->mac[link->ibport - 1],
link->gid, SMC_LLC_RESP); link->gid, SMC_LLC_RESP);
if (rc < 0) if (rc < 0)
return SMC_CLC_DECL_TCL; return SMC_CLC_DECL_TIMEOUT_AL;
smc_llc_link_active(link, net->ipv4.sysctl_tcp_keepalive_time); smc_llc_link_active(link, net->ipv4.sysctl_tcp_keepalive_time);
...@@ -424,9 +424,10 @@ static void smc_link_save_peer_info(struct smc_link *link, ...@@ -424,9 +424,10 @@ static void smc_link_save_peer_info(struct smc_link *link,
} }
/* fall back during connect */ /* fall back during connect */
static int smc_connect_fallback(struct smc_sock *smc) static int smc_connect_fallback(struct smc_sock *smc, int reason_code)
{ {
smc->use_fallback = true; smc->use_fallback = true;
smc->fallback_rsn = reason_code;
smc_copy_sock_settings_to_clc(smc); smc_copy_sock_settings_to_clc(smc);
if (smc->sk.sk_state == SMC_INIT) if (smc->sk.sk_state == SMC_INIT)
smc->sk.sk_state = SMC_ACTIVE; smc->sk.sk_state = SMC_ACTIVE;
...@@ -443,7 +444,7 @@ static int smc_connect_decline_fallback(struct smc_sock *smc, int reason_code) ...@@ -443,7 +444,7 @@ static int smc_connect_decline_fallback(struct smc_sock *smc, int reason_code)
sock_put(&smc->sk); /* passive closing */ sock_put(&smc->sk); /* passive closing */
return reason_code; return reason_code;
} }
if (reason_code != SMC_CLC_DECL_REPLY) { if (reason_code != SMC_CLC_DECL_PEERDECL) {
rc = smc_clc_send_decline(smc, reason_code); rc = smc_clc_send_decline(smc, reason_code);
if (rc < 0) { if (rc < 0) {
if (smc->sk.sk_state == SMC_INIT) if (smc->sk.sk_state == SMC_INIT)
...@@ -451,7 +452,7 @@ static int smc_connect_decline_fallback(struct smc_sock *smc, int reason_code) ...@@ -451,7 +452,7 @@ static int smc_connect_decline_fallback(struct smc_sock *smc, int reason_code)
return rc; return rc;
} }
} }
return smc_connect_fallback(smc); return smc_connect_fallback(smc, reason_code);
} }
/* abort connecting */ /* abort connecting */
...@@ -568,7 +569,7 @@ static int smc_connect_rdma(struct smc_sock *smc, ...@@ -568,7 +569,7 @@ static int smc_connect_rdma(struct smc_sock *smc,
smc_link_save_peer_info(link, aclc); smc_link_save_peer_info(link, aclc);
if (smc_rmb_rtoken_handling(&smc->conn, aclc)) if (smc_rmb_rtoken_handling(&smc->conn, aclc))
return smc_connect_abort(smc, SMC_CLC_DECL_INTERR, return smc_connect_abort(smc, SMC_CLC_DECL_ERR_RTOK,
local_contact); local_contact);
smc_close_init(smc); smc_close_init(smc);
...@@ -576,12 +577,12 @@ static int smc_connect_rdma(struct smc_sock *smc, ...@@ -576,12 +577,12 @@ static int smc_connect_rdma(struct smc_sock *smc,
if (local_contact == SMC_FIRST_CONTACT) { if (local_contact == SMC_FIRST_CONTACT) {
if (smc_ib_ready_link(link)) if (smc_ib_ready_link(link))
return smc_connect_abort(smc, SMC_CLC_DECL_INTERR, return smc_connect_abort(smc, SMC_CLC_DECL_ERR_RDYLNK,
local_contact); local_contact);
} else { } else {
if (!smc->conn.rmb_desc->reused && if (!smc->conn.rmb_desc->reused &&
smc_reg_rmb(link, smc->conn.rmb_desc, true)) smc_reg_rmb(link, smc->conn.rmb_desc, true))
return smc_connect_abort(smc, SMC_CLC_DECL_INTERR, return smc_connect_abort(smc, SMC_CLC_DECL_ERR_REGRMB,
local_contact); local_contact);
} }
smc_rmb_sync_sg_for_device(&smc->conn); smc_rmb_sync_sg_for_device(&smc->conn);
...@@ -659,11 +660,11 @@ static int __smc_connect(struct smc_sock *smc) ...@@ -659,11 +660,11 @@ static int __smc_connect(struct smc_sock *smc)
sock_hold(&smc->sk); /* sock put in passive closing */ sock_hold(&smc->sk); /* sock put in passive closing */
if (smc->use_fallback) if (smc->use_fallback)
return smc_connect_fallback(smc); return smc_connect_fallback(smc, smc->fallback_rsn);
/* if peer has not signalled SMC-capability, fall back */ /* if peer has not signalled SMC-capability, fall back */
if (!tcp_sk(smc->clcsock->sk)->syn_smc) if (!tcp_sk(smc->clcsock->sk)->syn_smc)
return smc_connect_fallback(smc); return smc_connect_fallback(smc, SMC_CLC_DECL_PEERNOSMC);
/* IPSec connections opt out of SMC-R optimizations */ /* IPSec connections opt out of SMC-R optimizations */
if (using_ipsec(smc)) if (using_ipsec(smc))
...@@ -693,7 +694,7 @@ static int __smc_connect(struct smc_sock *smc) ...@@ -693,7 +694,7 @@ static int __smc_connect(struct smc_sock *smc)
/* if neither ISM nor RDMA are supported, fallback */ /* if neither ISM nor RDMA are supported, fallback */
if (!rdma_supported && !ism_supported) if (!rdma_supported && !ism_supported)
return smc_connect_decline_fallback(smc, SMC_CLC_DECL_CNFERR); return smc_connect_decline_fallback(smc, SMC_CLC_DECL_NOSMCDEV);
/* perform CLC handshake */ /* perform CLC handshake */
rc = smc_connect_clc(smc, smc_type, &aclc, ibdev, ibport, gid, ismdev); rc = smc_connect_clc(smc, smc_type, &aclc, ibdev, ibport, gid, ismdev);
...@@ -708,7 +709,7 @@ static int __smc_connect(struct smc_sock *smc) ...@@ -708,7 +709,7 @@ static int __smc_connect(struct smc_sock *smc)
else if (ism_supported && aclc.hdr.path == SMC_TYPE_D) else if (ism_supported && aclc.hdr.path == SMC_TYPE_D)
rc = smc_connect_ism(smc, &aclc, ismdev); rc = smc_connect_ism(smc, &aclc, ismdev);
else else
rc = SMC_CLC_DECL_CNFERR; rc = SMC_CLC_DECL_MODEUNSUPP;
if (rc) { if (rc) {
smc_connect_ism_vlan_cleanup(smc, ism_supported, ismdev, vlan); smc_connect_ism_vlan_cleanup(smc, ism_supported, ismdev, vlan);
return smc_connect_decline_fallback(smc, rc); return smc_connect_decline_fallback(smc, rc);
...@@ -946,12 +947,12 @@ static int smc_serv_conf_first_link(struct smc_sock *smc) ...@@ -946,12 +947,12 @@ static int smc_serv_conf_first_link(struct smc_sock *smc)
link = &lgr->lnk[SMC_SINGLE_LINK]; link = &lgr->lnk[SMC_SINGLE_LINK];
if (smc_reg_rmb(link, smc->conn.rmb_desc, false)) if (smc_reg_rmb(link, smc->conn.rmb_desc, false))
return SMC_CLC_DECL_INTERR; return SMC_CLC_DECL_ERR_REGRMB;
/* send CONFIRM LINK request to client over the RoCE fabric */ /* send CONFIRM LINK request to client over the RoCE fabric */
rc = smc_llc_send_confirm_link(link, SMC_LLC_REQ); rc = smc_llc_send_confirm_link(link, SMC_LLC_REQ);
if (rc < 0) if (rc < 0)
return SMC_CLC_DECL_TCL; return SMC_CLC_DECL_TIMEOUT_CL;
/* receive CONFIRM LINK response from client over the RoCE fabric */ /* receive CONFIRM LINK response from client over the RoCE fabric */
rest = wait_for_completion_interruptible_timeout( rest = wait_for_completion_interruptible_timeout(
...@@ -973,7 +974,7 @@ static int smc_serv_conf_first_link(struct smc_sock *smc) ...@@ -973,7 +974,7 @@ static int smc_serv_conf_first_link(struct smc_sock *smc)
link->smcibdev->mac[link->ibport - 1], link->smcibdev->mac[link->ibport - 1],
link->gid, SMC_LLC_REQ); link->gid, SMC_LLC_REQ);
if (rc < 0) if (rc < 0)
return SMC_CLC_DECL_TCL; return SMC_CLC_DECL_TIMEOUT_AL;
/* receive ADD LINK response from client over the RoCE fabric */ /* receive ADD LINK response from client over the RoCE fabric */
rest = wait_for_completion_interruptible_timeout(&link->llc_add_resp, rest = wait_for_completion_interruptible_timeout(&link->llc_add_resp,
...@@ -1048,7 +1049,8 @@ static void smc_listen_decline(struct smc_sock *new_smc, int reason_code, ...@@ -1048,7 +1049,8 @@ static void smc_listen_decline(struct smc_sock *new_smc, int reason_code,
} }
smc_conn_free(&new_smc->conn); smc_conn_free(&new_smc->conn);
new_smc->use_fallback = true; new_smc->use_fallback = true;
if (reason_code && reason_code != SMC_CLC_DECL_REPLY) { new_smc->fallback_rsn = reason_code;
if (reason_code && reason_code != SMC_CLC_DECL_PEERDECL) {
if (smc_clc_send_decline(new_smc, reason_code) < 0) { if (smc_clc_send_decline(new_smc, reason_code) < 0) {
smc_listen_out_err(new_smc); smc_listen_out_err(new_smc);
return; return;
...@@ -1139,7 +1141,7 @@ static int smc_listen_rdma_reg(struct smc_sock *new_smc, int local_contact) ...@@ -1139,7 +1141,7 @@ static int smc_listen_rdma_reg(struct smc_sock *new_smc, int local_contact)
if (local_contact != SMC_FIRST_CONTACT) { if (local_contact != SMC_FIRST_CONTACT) {
if (!new_smc->conn.rmb_desc->reused) { if (!new_smc->conn.rmb_desc->reused) {
if (smc_reg_rmb(link, new_smc->conn.rmb_desc, true)) if (smc_reg_rmb(link, new_smc->conn.rmb_desc, true))
return SMC_CLC_DECL_INTERR; return SMC_CLC_DECL_ERR_REGRMB;
} }
} }
smc_rmb_sync_sg_for_device(&new_smc->conn); smc_rmb_sync_sg_for_device(&new_smc->conn);
...@@ -1159,13 +1161,13 @@ static void smc_listen_rdma_finish(struct smc_sock *new_smc, ...@@ -1159,13 +1161,13 @@ static void smc_listen_rdma_finish(struct smc_sock *new_smc,
smc_link_save_peer_info(link, cclc); smc_link_save_peer_info(link, cclc);
if (smc_rmb_rtoken_handling(&new_smc->conn, cclc)) { if (smc_rmb_rtoken_handling(&new_smc->conn, cclc)) {
reason_code = SMC_CLC_DECL_INTERR; reason_code = SMC_CLC_DECL_ERR_RTOK;
goto decline; goto decline;
} }
if (local_contact == SMC_FIRST_CONTACT) { if (local_contact == SMC_FIRST_CONTACT) {
if (smc_ib_ready_link(link)) { if (smc_ib_ready_link(link)) {
reason_code = SMC_CLC_DECL_INTERR; reason_code = SMC_CLC_DECL_ERR_RDYLNK;
goto decline; goto decline;
} }
/* QP confirmation over RoCE fabric */ /* QP confirmation over RoCE fabric */
...@@ -1206,6 +1208,7 @@ static void smc_listen_work(struct work_struct *work) ...@@ -1206,6 +1208,7 @@ static void smc_listen_work(struct work_struct *work)
/* check if peer is smc capable */ /* check if peer is smc capable */
if (!tcp_sk(newclcsock->sk)->syn_smc) { if (!tcp_sk(newclcsock->sk)->syn_smc) {
new_smc->use_fallback = true; new_smc->use_fallback = true;
new_smc->fallback_rsn = SMC_CLC_DECL_PEERNOSMC;
smc_listen_out_connected(new_smc); smc_listen_out_connected(new_smc);
return; return;
} }
...@@ -1250,7 +1253,8 @@ static void smc_listen_work(struct work_struct *work) ...@@ -1250,7 +1253,8 @@ static void smc_listen_work(struct work_struct *work)
smc_listen_rdma_reg(new_smc, local_contact))) { smc_listen_rdma_reg(new_smc, local_contact))) {
/* SMC not supported, decline */ /* SMC not supported, decline */
mutex_unlock(&smc_create_lgr_pending); mutex_unlock(&smc_create_lgr_pending);
smc_listen_decline(new_smc, SMC_CLC_DECL_CNFERR, local_contact); smc_listen_decline(new_smc, SMC_CLC_DECL_MODEUNSUPP,
local_contact);
return; return;
} }
...@@ -1297,6 +1301,7 @@ static void smc_tcp_listen_work(struct work_struct *work) ...@@ -1297,6 +1301,7 @@ static void smc_tcp_listen_work(struct work_struct *work)
new_smc->listen_smc = lsmc; new_smc->listen_smc = lsmc;
new_smc->use_fallback = lsmc->use_fallback; new_smc->use_fallback = lsmc->use_fallback;
new_smc->fallback_rsn = lsmc->fallback_rsn;
sock_hold(lsk); /* sock_put in smc_listen_work */ sock_hold(lsk); /* sock_put in smc_listen_work */
INIT_WORK(&new_smc->smc_listen_work, smc_listen_work); INIT_WORK(&new_smc->smc_listen_work, smc_listen_work);
smc_copy_sock_settings_to_smc(new_smc); smc_copy_sock_settings_to_smc(new_smc);
...@@ -1451,6 +1456,7 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) ...@@ -1451,6 +1456,7 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
if (msg->msg_flags & MSG_FASTOPEN) { if (msg->msg_flags & MSG_FASTOPEN) {
if (sk->sk_state == SMC_INIT) { if (sk->sk_state == SMC_INIT) {
smc->use_fallback = true; smc->use_fallback = true;
smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP;
} else { } else {
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
...@@ -1648,6 +1654,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname, ...@@ -1648,6 +1654,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
/* option not supported by SMC */ /* option not supported by SMC */
if (sk->sk_state == SMC_INIT) { if (sk->sk_state == SMC_INIT) {
smc->use_fallback = true; smc->use_fallback = true;
smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP;
} else { } else {
if (!smc->use_fallback) if (!smc->use_fallback)
rc = -EINVAL; rc = -EINVAL;
...@@ -1885,6 +1892,7 @@ static int smc_create(struct net *net, struct socket *sock, int protocol, ...@@ -1885,6 +1892,7 @@ static int smc_create(struct net *net, struct socket *sock, int protocol,
/* create internal TCP socket for CLC handshake and fallback */ /* create internal TCP socket for CLC handshake and fallback */
smc = smc_sk(sk); smc = smc_sk(sk);
smc->use_fallback = false; /* assume rdma capability first */ smc->use_fallback = false; /* assume rdma capability first */
smc->fallback_rsn = 0;
rc = sock_create_kern(net, family, SOCK_STREAM, IPPROTO_TCP, rc = sock_create_kern(net, family, SOCK_STREAM, IPPROTO_TCP,
&smc->clcsock); &smc->clcsock);
if (rc) { if (rc) {
......
...@@ -208,6 +208,8 @@ struct smc_sock { /* smc sock container */ ...@@ -208,6 +208,8 @@ struct smc_sock { /* smc sock container */
struct list_head accept_q; /* sockets to be accepted */ struct list_head accept_q; /* sockets to be accepted */
spinlock_t accept_q_lock; /* protects accept_q */ spinlock_t accept_q_lock; /* protects accept_q */
bool use_fallback; /* fallback to tcp */ bool use_fallback; /* fallback to tcp */
int fallback_rsn; /* reason for fallback */
u32 peer_diagnosis; /* decline reason from peer */
int sockopt_defer_accept; int sockopt_defer_accept;
/* sockopt TCP_DEFER_ACCEPT /* sockopt TCP_DEFER_ACCEPT
* value * value
......
...@@ -334,7 +334,11 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, ...@@ -334,7 +334,11 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
goto out; goto out;
} }
if (clcm->type == SMC_CLC_DECLINE) { if (clcm->type == SMC_CLC_DECLINE) {
reason_code = SMC_CLC_DECL_REPLY; struct smc_clc_msg_decline *dclc;
dclc = (struct smc_clc_msg_decline *)clcm;
reason_code = SMC_CLC_DECL_PEERDECL;
smc->peer_diagnosis = ntohl(dclc->peer_diagnosis);
if (((struct smc_clc_msg_decline *)buf)->hdr.flag) { if (((struct smc_clc_msg_decline *)buf)->hdr.flag) {
smc->conn.lgr->sync_err = 1; smc->conn.lgr->sync_err = 1;
smc_lgr_terminate(smc->conn.lgr); smc_lgr_terminate(smc->conn.lgr);
......
...@@ -28,15 +28,21 @@ ...@@ -28,15 +28,21 @@
#define SMC_TYPE_B 3 /* SMC-R and SMC-D */ #define SMC_TYPE_B 3 /* SMC-R and SMC-D */
#define CLC_WAIT_TIME (6 * HZ) /* max. wait time on clcsock */ #define CLC_WAIT_TIME (6 * HZ) /* max. wait time on clcsock */
#define SMC_CLC_DECL_MEM 0x01010000 /* insufficient memory resources */ #define SMC_CLC_DECL_MEM 0x01010000 /* insufficient memory resources */
#define SMC_CLC_DECL_TIMEOUT 0x02000000 /* timeout */ #define SMC_CLC_DECL_TIMEOUT_CL 0x02010000 /* timeout w4 QP confirm link */
#define SMC_CLC_DECL_TIMEOUT_AL 0x02020000 /* timeout w4 QP add link */
#define SMC_CLC_DECL_CNFERR 0x03000000 /* configuration error */ #define SMC_CLC_DECL_CNFERR 0x03000000 /* configuration error */
#define SMC_CLC_DECL_IPSEC 0x03030000 /* IPsec usage */ #define SMC_CLC_DECL_PEERNOSMC 0x03010000 /* peer did not indicate SMC */
#define SMC_CLC_DECL_IPSEC 0x03020000 /* IPsec usage */
#define SMC_CLC_DECL_NOSMCDEV 0x03030000 /* no SMC device found */
#define SMC_CLC_DECL_MODEUNSUPP 0x03040000 /* smc modes do not match (R or D)*/
#define SMC_CLC_DECL_RMBE_EC 0x03050000 /* peer has eyecatcher in RMBE */
#define SMC_CLC_DECL_OPTUNSUPP 0x03060000 /* fastopen sockopt not supported */
#define SMC_CLC_DECL_SYNCERR 0x04000000 /* synchronization error */ #define SMC_CLC_DECL_SYNCERR 0x04000000 /* synchronization error */
#define SMC_CLC_DECL_REPLY 0x06000000 /* reply to a received decline */ #define SMC_CLC_DECL_PEERDECL 0x05000000 /* peer declined during handshake */
#define SMC_CLC_DECL_INTERR 0x99990000 /* internal error */ #define SMC_CLC_DECL_INTERR 0x99990000 /* internal error */
#define SMC_CLC_DECL_TCL 0x02040000 /* timeout w4 QP confirm */ #define SMC_CLC_DECL_ERR_RTOK 0x99990001 /* rtoken handling failed */
#define SMC_CLC_DECL_SEND 0x07000000 /* sending problem */ #define SMC_CLC_DECL_ERR_RDYLNK 0x99990002 /* ib ready link failed */
#define SMC_CLC_DECL_RMBE_EC 0x08000000 /* peer has eyecatcher in RMBE */ #define SMC_CLC_DECL_ERR_REGRMB 0x99990003 /* reg rmb failed */
struct smc_clc_msg_hdr { /* header1 of clc messages */ struct smc_clc_msg_hdr { /* header1 of clc messages */
u8 eyecatcher[4]; /* eye catcher */ u8 eyecatcher[4]; /* eye catcher */
......
...@@ -79,6 +79,7 @@ static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb, ...@@ -79,6 +79,7 @@ static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb,
struct nlattr *bc) struct nlattr *bc)
{ {
struct smc_sock *smc = smc_sk(sk); struct smc_sock *smc = smc_sk(sk);
struct smc_diag_fallback fallback;
struct user_namespace *user_ns; struct user_namespace *user_ns;
struct smc_diag_msg *r; struct smc_diag_msg *r;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
...@@ -101,6 +102,11 @@ static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb, ...@@ -101,6 +102,11 @@ static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb,
if (smc_diag_msg_attrs_fill(sk, skb, r, user_ns)) if (smc_diag_msg_attrs_fill(sk, skb, r, user_ns))
goto errout; goto errout;
fallback.reason = smc->fallback_rsn;
fallback.peer_diagnosis = smc->peer_diagnosis;
if (nla_put(skb, SMC_DIAG_FALLBACK, sizeof(fallback), &fallback) < 0)
goto errout;
if ((req->diag_ext & (1 << (SMC_DIAG_CONNINFO - 1))) && if ((req->diag_ext & (1 << (SMC_DIAG_CONNINFO - 1))) &&
smc->conn.alert_token_local) { smc->conn.alert_token_local) {
struct smc_connection *conn = &smc->conn; struct smc_connection *conn = &smc->conn;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment