Skip to content

Commit

Permalink
Merge branch 'smc-next'
Browse files Browse the repository at this point in the history
Ursula Braun says:

====================
net/smc: patches 2019-04-12

here are patches for SMC:
* patch 1 improves behavior of non-blocking connect
* patches 2, 3, 5, 7, and 8 improve connecting return codes
* patches 4 and 6 are a cleanups without functional change
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 12, 2019
2 parents 6dc400a + 7a62725 commit e0a092e
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 274 deletions.
355 changes: 182 additions & 173 deletions net/smc/af_smc.c

Large diffs are not rendered by default.

11 changes: 4 additions & 7 deletions net/smc/smc.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,18 +190,11 @@ struct smc_connection {
u64 peer_token; /* SMC-D token of peer */
};

struct smc_connect_info {
int flags;
int alen;
struct sockaddr addr;
};

struct smc_sock { /* smc sock container */
struct sock sk;
struct socket *clcsock; /* internal tcp socket */
struct smc_connection conn; /* smc connection */
struct smc_sock *listen_smc; /* listen parent */
struct smc_connect_info *connect_info; /* connect address & flags */
struct work_struct connect_work; /* handle non-blocking connect*/
struct work_struct tcp_listen_work;/* handle tcp socket accepts */
struct work_struct smc_listen_work;/* prepare new accept socket */
Expand All @@ -219,6 +212,10 @@ struct smc_sock { /* smc sock container */
* started, waiting for unsent
* data to be sent
*/
u8 connect_nonblock : 1;
/* non-blocking connect in
* flight
*/
struct mutex clcsock_release_lock;
/* protects clcsock of a listen
* socket
Expand Down
10 changes: 5 additions & 5 deletions net/smc/smc_clc.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,7 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info)

/* send CLC PROPOSAL message across internal TCP socket */
int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
struct smc_ib_device *ibdev, u8 ibport, u8 gid[],
struct smcd_dev *ismdev)
struct smc_init_info *ini)
{
struct smc_clc_ipv6_prefix ipv6_prfx[SMC_CLC_MAX_V6_PREFIX];
struct smc_clc_msg_proposal_prefix pclc_prfx;
Expand Down Expand Up @@ -416,16 +415,17 @@ int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
/* add SMC-R specifics */
memcpy(pclc.lcl.id_for_peer, local_systemid,
sizeof(local_systemid));
memcpy(&pclc.lcl.gid, gid, SMC_GID_SIZE);
memcpy(&pclc.lcl.mac, &ibdev->mac[ibport - 1], ETH_ALEN);
memcpy(&pclc.lcl.gid, ini->ib_gid, SMC_GID_SIZE);
memcpy(&pclc.lcl.mac, &ini->ib_dev->mac[ini->ib_port - 1],
ETH_ALEN);
pclc.iparea_offset = htons(0);
}
if (smc_type == SMC_TYPE_D || smc_type == SMC_TYPE_B) {
/* add SMC-D specifics */
memset(&pclc_smcd, 0, sizeof(pclc_smcd));
plen += sizeof(pclc_smcd);
pclc.iparea_offset = htons(SMC_CLC_PROPOSAL_MAX_OFFSET);
pclc_smcd.gid = ismdev->local_gid;
pclc_smcd.gid = ini->ism_dev->local_gid;
}
pclc.hdr.length = htons(plen);

Expand Down
20 changes: 13 additions & 7 deletions net/smc/smc_clc.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,22 @@
#define SMC_CLC_DECL_CNFERR 0x03000000 /* configuration error */
#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_NOSMCDEV 0x03030000 /* no SMC device found (R or D) */
#define SMC_CLC_DECL_NOSMCDDEV 0x03030001 /* no SMC-D device found */
#define SMC_CLC_DECL_NOSMCRDEV 0x03030002 /* no SMC-R device found */
#define SMC_CLC_DECL_SMCDNOTALK 0x03030003 /* SMC-D dev can't talk to peer */
#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_DIFFPREFIX 0x03070000 /* IP prefix / subnet mismatch */
#define SMC_CLC_DECL_GETVLANERR 0x03080000 /* err to get vlan id of ip device*/
#define SMC_CLC_DECL_ISMVLANERR 0x03090000 /* err to reg vlan id on ism dev */
#define SMC_CLC_DECL_SYNCERR 0x04000000 /* synchronization error */
#define SMC_CLC_DECL_PEERDECL 0x05000000 /* peer declined during handshake */
#define SMC_CLC_DECL_INTERR 0x99990000 /* internal error */
#define SMC_CLC_DECL_ERR_RTOK 0x99990001 /* rtoken handling failed */
#define SMC_CLC_DECL_ERR_RDYLNK 0x99990002 /* ib ready link failed */
#define SMC_CLC_DECL_ERR_REGRMB 0x99990003 /* reg rmb failed */
#define SMC_CLC_DECL_INTERR 0x09990000 /* internal error */
#define SMC_CLC_DECL_ERR_RTOK 0x09990001 /* rtoken handling failed */
#define SMC_CLC_DECL_ERR_RDYLNK 0x09990002 /* ib ready link failed */
#define SMC_CLC_DECL_ERR_REGRMB 0x09990003 /* reg rmb failed */

struct smc_clc_msg_hdr { /* header1 of clc messages */
u8 eyecatcher[4]; /* eye catcher */
Expand Down Expand Up @@ -179,15 +185,15 @@ smc_get_clc_msg_smcd(struct smc_clc_msg_proposal *prop)
}

struct smcd_dev;
struct smc_init_info;

int smc_clc_prfx_match(struct socket *clcsock,
struct smc_clc_msg_proposal_prefix *prop);
int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
u8 expected_type, unsigned long timeout);
int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info);
int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
struct smc_ib_device *smcibdev, u8 ibport, u8 gid[],
struct smcd_dev *ismdev);
struct smc_init_info *ini);
int smc_clc_send_confirm(struct smc_sock *smc);
int smc_clc_send_accept(struct smc_sock *smc, int srv_first_contact);

Expand Down
93 changes: 46 additions & 47 deletions net/smc/smc_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,31 +195,29 @@ static void smc_lgr_free_work(struct work_struct *work)
}

/* create a new SMC link group */
static int smc_lgr_create(struct smc_sock *smc, bool is_smcd,
struct smc_ib_device *smcibdev, u8 ibport,
char *peer_systemid, unsigned short vlan_id,
struct smcd_dev *smcismdev, u64 peer_gid)
static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
{
struct smc_link_group *lgr;
struct smc_link *lnk;
u8 rndvec[3];
int rc = 0;
int i;

if (is_smcd && vlan_id) {
rc = smc_ism_get_vlan(smcismdev, vlan_id);
if (rc)
if (ini->is_smcd && ini->vlan_id) {
if (smc_ism_get_vlan(ini->ism_dev, ini->vlan_id)) {
rc = SMC_CLC_DECL_ISMVLANERR;
goto out;
}
}

lgr = kzalloc(sizeof(*lgr), GFP_KERNEL);
if (!lgr) {
rc = -ENOMEM;
rc = SMC_CLC_DECL_MEM;
goto out;
}
lgr->is_smcd = is_smcd;
lgr->is_smcd = ini->is_smcd;
lgr->sync_err = 0;
lgr->vlan_id = vlan_id;
lgr->vlan_id = ini->vlan_id;
rwlock_init(&lgr->sndbufs_lock);
rwlock_init(&lgr->rmbs_lock);
rwlock_init(&lgr->conns_lock);
Expand All @@ -231,29 +229,32 @@ static int smc_lgr_create(struct smc_sock *smc, bool is_smcd,
memcpy(&lgr->id, (u8 *)&smc_lgr_list.num, SMC_LGR_ID_SIZE);
INIT_DELAYED_WORK(&lgr->free_work, smc_lgr_free_work);
lgr->conns_all = RB_ROOT;
if (is_smcd) {
if (ini->is_smcd) {
/* SMC-D specific settings */
lgr->peer_gid = peer_gid;
lgr->smcd = smcismdev;
lgr->peer_gid = ini->ism_gid;
lgr->smcd = ini->ism_dev;
} else {
/* SMC-R specific settings */
lgr->role = smc->listen_smc ? SMC_SERV : SMC_CLNT;
memcpy(lgr->peer_systemid, peer_systemid, SMC_SYSTEMID_LEN);
memcpy(lgr->peer_systemid, ini->ib_lcl->id_for_peer,
SMC_SYSTEMID_LEN);

lnk = &lgr->lnk[SMC_SINGLE_LINK];
/* initialize link */
lnk->state = SMC_LNK_ACTIVATING;
lnk->link_id = SMC_SINGLE_LINK;
lnk->smcibdev = smcibdev;
lnk->ibport = ibport;
lnk->path_mtu = smcibdev->pattr[ibport - 1].active_mtu;
if (!smcibdev->initialized)
smc_ib_setup_per_ibdev(smcibdev);
lnk->smcibdev = ini->ib_dev;
lnk->ibport = ini->ib_port;
lnk->path_mtu =
ini->ib_dev->pattr[ini->ib_port - 1].active_mtu;
if (!ini->ib_dev->initialized)
smc_ib_setup_per_ibdev(ini->ib_dev);
get_random_bytes(rndvec, sizeof(rndvec));
lnk->psn_initial = rndvec[0] + (rndvec[1] << 8) +
(rndvec[2] << 16);
rc = smc_ib_determine_gid(lnk->smcibdev, lnk->ibport,
vlan_id, lnk->gid, &lnk->sgid_index);
ini->vlan_id, lnk->gid,
&lnk->sgid_index);
if (rc)
goto free_lgr;
rc = smc_llc_link_init(lnk);
Expand Down Expand Up @@ -289,6 +290,12 @@ static int smc_lgr_create(struct smc_sock *smc, bool is_smcd,
free_lgr:
kfree(lgr);
out:
if (rc < 0) {
if (rc == -ENOMEM)
rc = SMC_CLC_DECL_MEM;
else
rc = SMC_CLC_DECL_INTERR;
}
return rc;
}

Expand Down Expand Up @@ -528,13 +535,13 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan)
/* Determine vlan of internal TCP socket.
* @vlan_id: address to store the determined vlan id into
*/
int smc_vlan_by_tcpsk(struct socket *clcsock, unsigned short *vlan_id)
int smc_vlan_by_tcpsk(struct socket *clcsock, struct smc_init_info *ini)
{
struct dst_entry *dst = sk_dst_get(clcsock->sk);
struct net_device *ndev;
int i, nest_lvl, rc = 0;

*vlan_id = 0;
ini->vlan_id = 0;
if (!dst) {
rc = -ENOTCONN;
goto out;
Expand All @@ -546,7 +553,7 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, unsigned short *vlan_id)

ndev = dst->dev;
if (is_vlan_dev(ndev)) {
*vlan_id = vlan_dev_vlan_id(ndev);
ini->vlan_id = vlan_dev_vlan_id(ndev);
goto out_rel;
}

Expand All @@ -560,7 +567,7 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, unsigned short *vlan_id)
lower = lower->next;
ndev = (struct net_device *)netdev_lower_get_next(ndev, &lower);
if (is_vlan_dev(ndev)) {
*vlan_id = vlan_dev_vlan_id(ndev);
ini->vlan_id = vlan_dev_vlan_id(ndev);
break;
}
}
Expand Down Expand Up @@ -594,39 +601,32 @@ static bool smcd_lgr_match(struct smc_link_group *lgr,
}

/* create a new SMC connection (and a new link group if necessary) */
int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
struct smc_ib_device *smcibdev, u8 ibport, u32 clcqpn,
struct smc_clc_msg_local *lcl, struct smcd_dev *smcd,
u64 peer_gid)
int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
{
struct smc_connection *conn = &smc->conn;
int local_contact = SMC_FIRST_CONTACT;
struct smc_link_group *lgr;
unsigned short vlan_id;
enum smc_lgr_role role;
int rc = 0;

ini->cln_first_contact = SMC_FIRST_CONTACT;
role = smc->listen_smc ? SMC_SERV : SMC_CLNT;
rc = smc_vlan_by_tcpsk(smc->clcsock, &vlan_id);
if (rc)
return rc;

if ((role == SMC_CLNT) && srv_first_contact)
if (role == SMC_CLNT && ini->srv_first_contact)
/* create new link group as well */
goto create;

/* determine if an existing link group can be reused */
spin_lock_bh(&smc_lgr_list.lock);
list_for_each_entry(lgr, &smc_lgr_list.list, list) {
write_lock_bh(&lgr->conns_lock);
if ((is_smcd ? smcd_lgr_match(lgr, smcd, peer_gid) :
smcr_lgr_match(lgr, lcl, role, clcqpn)) &&
if ((ini->is_smcd ?
smcd_lgr_match(lgr, ini->ism_dev, ini->ism_gid) :
smcr_lgr_match(lgr, ini->ib_lcl, role, ini->ib_clcqpn)) &&
!lgr->sync_err &&
lgr->vlan_id == vlan_id &&
lgr->vlan_id == ini->vlan_id &&
(role == SMC_CLNT ||
lgr->conns_num < SMC_RMBS_PER_LGR_MAX)) {
/* link group found */
local_contact = SMC_REUSE_CONTACT;
ini->cln_first_contact = SMC_REUSE_CONTACT;
conn->lgr = lgr;
smc_lgr_register_conn(conn); /* add smc conn to lgr */
if (delayed_work_pending(&lgr->free_work))
Expand All @@ -638,27 +638,26 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
}
spin_unlock_bh(&smc_lgr_list.lock);

if (role == SMC_CLNT && !srv_first_contact &&
(local_contact == SMC_FIRST_CONTACT)) {
if (role == SMC_CLNT && !ini->srv_first_contact &&
ini->cln_first_contact == SMC_FIRST_CONTACT) {
/* Server reuses a link group, but Client wants to start
* a new one
* send out_of_sync decline, reason synchr. error
*/
return -ENOLINK;
return SMC_CLC_DECL_SYNCERR;
}

create:
if (local_contact == SMC_FIRST_CONTACT) {
rc = smc_lgr_create(smc, is_smcd, smcibdev, ibport,
lcl->id_for_peer, vlan_id, smcd, peer_gid);
if (ini->cln_first_contact == SMC_FIRST_CONTACT) {
rc = smc_lgr_create(smc, ini);
if (rc)
goto out;
smc_lgr_register_conn(conn); /* add smc conn to lgr */
}
conn->local_tx_ctrl.common.type = SMC_CDC_MSG_TYPE;
conn->local_tx_ctrl.len = SMC_WR_TX_SIZE;
conn->urg_state = SMC_URG_READ;
if (is_smcd) {
if (ini->is_smcd) {
conn->rx_off = sizeof(struct smcd_cdc_msg);
smcd_cdc_rx_init(conn); /* init tasklet for this conn */
}
Expand All @@ -667,7 +666,7 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
#endif

out:
return rc ? rc : local_contact;
return rc;
}

/* convert the RMB size into the compressed notation - minimum 16K.
Expand Down
25 changes: 20 additions & 5 deletions net/smc/smc_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,24 @@ struct smc_link_group {
};
};

struct smc_clc_msg_local;

struct smc_init_info {
u8 is_smcd;
unsigned short vlan_id;
int srv_first_contact;
int cln_first_contact;
/* SMC-R */
struct smc_clc_msg_local *ib_lcl;
struct smc_ib_device *ib_dev;
u8 ib_gid[SMC_GID_SIZE];
u8 ib_port;
u32 ib_clcqpn;
/* SMC-D */
u64 ism_gid;
struct smcd_dev *ism_dev;
};

/* Find the connection associated with the given alert token in the link group.
* To use rbtrees we have to implement our own search core.
* Requires @conns_lock
Expand Down Expand Up @@ -281,13 +299,10 @@ void smc_sndbuf_sync_sg_for_cpu(struct smc_connection *conn);
void smc_sndbuf_sync_sg_for_device(struct smc_connection *conn);
void smc_rmb_sync_sg_for_cpu(struct smc_connection *conn);
void smc_rmb_sync_sg_for_device(struct smc_connection *conn);
int smc_vlan_by_tcpsk(struct socket *clcsock, unsigned short *vlan_id);
int smc_vlan_by_tcpsk(struct socket *clcsock, struct smc_init_info *ini);

void smc_conn_free(struct smc_connection *conn);
int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
struct smc_ib_device *smcibdev, u8 ibport, u32 clcqpn,
struct smc_clc_msg_local *lcl, struct smcd_dev *smcd,
u64 peer_gid);
int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini);
void smcd_conn_free(struct smc_connection *conn);
void smc_lgr_schedule_free_work_fast(struct smc_link_group *lgr);
void smc_core_exit(void);
Expand Down
Loading

0 comments on commit e0a092e

Please sign in to comment.