net/smc: restructure netinfo for CLC proposal msgs
Introduce functions smc_clc_prfx_set to retrieve IP information for the CLC proposal msg and smc_clc_prfx_match to match the contents of a proposal message against the IP addresses of the net device. The new functions replace the functionality provided by smc_clc_netinfo_by_tcpsk, which is removed by this patch. The match functionality is extended to scan all ipv4 addresses of the net device for a match against the ipv4 subnet from the proposal msg. Signed-off-by: Karsten Graul <kgraul@linux.vnet.ibm.com> Signed-off-by: Ursula Braun <ubraun@linux.vnet.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
8b7372c101
commit
c246d942ea
3 changed files with 85 additions and 39 deletions
|
@ -767,8 +767,6 @@ static void smc_listen_work(struct work_struct *work)
|
||||||
struct smc_link *link;
|
struct smc_link *link;
|
||||||
int reason_code = 0;
|
int reason_code = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
__be32 subnet;
|
|
||||||
u8 prefix_len;
|
|
||||||
u8 ibport;
|
u8 ibport;
|
||||||
|
|
||||||
/* check if peer is smc capable */
|
/* check if peer is smc capable */
|
||||||
|
@ -803,17 +801,11 @@ static void smc_listen_work(struct work_struct *work)
|
||||||
goto decline_rdma;
|
goto decline_rdma;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* determine subnet and mask from internal TCP socket */
|
|
||||||
rc = smc_clc_netinfo_by_tcpsk(newclcsock, &subnet, &prefix_len);
|
|
||||||
if (rc) {
|
|
||||||
reason_code = SMC_CLC_DECL_CNFERR; /* configuration error */
|
|
||||||
goto decline_rdma;
|
|
||||||
}
|
|
||||||
|
|
||||||
pclc = (struct smc_clc_msg_proposal *)&buf;
|
pclc = (struct smc_clc_msg_proposal *)&buf;
|
||||||
pclc_prfx = smc_clc_proposal_get_prefix(pclc);
|
pclc_prfx = smc_clc_proposal_get_prefix(pclc);
|
||||||
if (pclc_prfx->outgoing_subnet != subnet ||
|
|
||||||
pclc_prfx->prefix_len != prefix_len) {
|
rc = smc_clc_prfx_match(newclcsock, pclc_prfx);
|
||||||
|
if (rc) {
|
||||||
reason_code = SMC_CLC_DECL_CNFERR; /* configuration error */
|
reason_code = SMC_CLC_DECL_CNFERR; /* configuration error */
|
||||||
goto decline_rdma;
|
goto decline_rdma;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,13 +74,81 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* determine subnet and mask of internal TCP socket */
|
/* find ipv4 addr on device and get the prefix len, fill CLC proposal msg */
|
||||||
int smc_clc_netinfo_by_tcpsk(struct socket *clcsock,
|
static int smc_clc_prfx_set4_rcu(struct dst_entry *dst, __be32 ipv4,
|
||||||
__be32 *subnet, u8 *prefix_len)
|
struct smc_clc_msg_proposal_prefix *prop)
|
||||||
|
{
|
||||||
|
struct in_device *in_dev = __in_dev_get_rcu(dst->dev);
|
||||||
|
|
||||||
|
if (!in_dev)
|
||||||
|
return -ENODEV;
|
||||||
|
for_ifa(in_dev) {
|
||||||
|
if (!inet_ifa_match(ipv4, ifa))
|
||||||
|
continue;
|
||||||
|
prop->prefix_len = inet_mask_len(ifa->ifa_mask);
|
||||||
|
prop->outgoing_subnet = ifa->ifa_address & ifa->ifa_mask;
|
||||||
|
/* prop->ipv6_prefixes_cnt = 0; already done by memset before */
|
||||||
|
return 0;
|
||||||
|
} endfor_ifa(in_dev);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* retrieve and set prefixes in CLC proposal msg */
|
||||||
|
static int smc_clc_prfx_set(struct socket *clcsock,
|
||||||
|
struct smc_clc_msg_proposal_prefix *prop)
|
||||||
|
{
|
||||||
|
struct dst_entry *dst = sk_dst_get(clcsock->sk);
|
||||||
|
struct sockaddr_storage addrs;
|
||||||
|
struct sockaddr_in *addr;
|
||||||
|
int rc = -ENOENT;
|
||||||
|
|
||||||
|
memset(prop, 0, sizeof(*prop));
|
||||||
|
if (!dst) {
|
||||||
|
rc = -ENOTCONN;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!dst->dev) {
|
||||||
|
rc = -ENODEV;
|
||||||
|
goto out_rel;
|
||||||
|
}
|
||||||
|
/* get address to which the internal TCP socket is bound */
|
||||||
|
kernel_getsockname(clcsock, (struct sockaddr *)&addrs);
|
||||||
|
/* analyze IP specific data of net_device belonging to TCP socket */
|
||||||
|
rcu_read_lock();
|
||||||
|
if (addrs.ss_family == PF_INET) {
|
||||||
|
/* IPv4 */
|
||||||
|
addr = (struct sockaddr_in *)&addrs;
|
||||||
|
rc = smc_clc_prfx_set4_rcu(dst, addr->sin_addr.s_addr, prop);
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
out_rel:
|
||||||
|
dst_release(dst);
|
||||||
|
out:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* match ipv4 addrs of dev against addr in CLC proposal */
|
||||||
|
static int smc_clc_prfx_match4_rcu(struct net_device *dev,
|
||||||
|
struct smc_clc_msg_proposal_prefix *prop)
|
||||||
|
{
|
||||||
|
struct in_device *in_dev = __in_dev_get_rcu(dev);
|
||||||
|
|
||||||
|
if (!in_dev)
|
||||||
|
return -ENODEV;
|
||||||
|
for_ifa(in_dev) {
|
||||||
|
if (prop->prefix_len == inet_mask_len(ifa->ifa_mask) &&
|
||||||
|
inet_ifa_match(prop->outgoing_subnet, ifa))
|
||||||
|
return 0;
|
||||||
|
} endfor_ifa(in_dev);
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if proposed prefixes match one of our device prefixes */
|
||||||
|
int smc_clc_prfx_match(struct socket *clcsock,
|
||||||
|
struct smc_clc_msg_proposal_prefix *prop)
|
||||||
{
|
{
|
||||||
struct dst_entry *dst = sk_dst_get(clcsock->sk);
|
struct dst_entry *dst = sk_dst_get(clcsock->sk);
|
||||||
struct in_device *in_dev;
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
int rc = -ENOENT;
|
int rc = -ENOENT;
|
||||||
|
|
||||||
if (!dst) {
|
if (!dst) {
|
||||||
|
@ -91,22 +159,10 @@ int smc_clc_netinfo_by_tcpsk(struct socket *clcsock,
|
||||||
rc = -ENODEV;
|
rc = -ENODEV;
|
||||||
goto out_rel;
|
goto out_rel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get address to which the internal TCP socket is bound */
|
|
||||||
kernel_getsockname(clcsock, (struct sockaddr *)&addr);
|
|
||||||
/* analyze IPv4 specific data of net_device belonging to TCP socket */
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
in_dev = __in_dev_get_rcu(dst->dev);
|
if (!prop->ipv6_prefixes_cnt)
|
||||||
for_ifa(in_dev) {
|
rc = smc_clc_prfx_match4_rcu(dst->dev, prop);
|
||||||
if (!inet_ifa_match(addr.sin_addr.s_addr, ifa))
|
|
||||||
continue;
|
|
||||||
*prefix_len = inet_mask_len(ifa->ifa_mask);
|
|
||||||
*subnet = ifa->ifa_address & ifa->ifa_mask;
|
|
||||||
rc = 0;
|
|
||||||
break;
|
|
||||||
} endfor_ifa(in_dev);
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
out_rel:
|
out_rel:
|
||||||
dst_release(dst);
|
dst_release(dst);
|
||||||
out:
|
out:
|
||||||
|
@ -240,6 +296,11 @@ int smc_clc_send_proposal(struct smc_sock *smc,
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
int len, plen, rc;
|
int len, plen, rc;
|
||||||
|
|
||||||
|
/* retrieve ip prefixes for CLC proposal msg */
|
||||||
|
rc = smc_clc_prfx_set(smc->clcsock, &pclc_prfx);
|
||||||
|
if (rc)
|
||||||
|
return SMC_CLC_DECL_CNFERR; /* configuration error */
|
||||||
|
|
||||||
/* send SMC Proposal CLC message */
|
/* send SMC Proposal CLC message */
|
||||||
plen = sizeof(pclc) + sizeof(pclc_prfx) + sizeof(trl);
|
plen = sizeof(pclc) + sizeof(pclc_prfx) + sizeof(trl);
|
||||||
memset(&pclc, 0, sizeof(pclc));
|
memset(&pclc, 0, sizeof(pclc));
|
||||||
|
@ -252,13 +313,6 @@ int smc_clc_send_proposal(struct smc_sock *smc,
|
||||||
memcpy(&pclc.lcl.mac, &smcibdev->mac[ibport - 1], ETH_ALEN);
|
memcpy(&pclc.lcl.mac, &smcibdev->mac[ibport - 1], ETH_ALEN);
|
||||||
pclc.iparea_offset = htons(0);
|
pclc.iparea_offset = htons(0);
|
||||||
|
|
||||||
memset(&pclc_prfx, 0, sizeof(pclc_prfx));
|
|
||||||
/* determine subnet and mask from internal TCP socket */
|
|
||||||
rc = smc_clc_netinfo_by_tcpsk(smc->clcsock, &pclc_prfx.outgoing_subnet,
|
|
||||||
&pclc_prfx.prefix_len);
|
|
||||||
if (rc)
|
|
||||||
return SMC_CLC_DECL_CNFERR; /* configuration error */
|
|
||||||
pclc_prfx.ipv6_prefixes_cnt = 0;
|
|
||||||
memcpy(trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
|
memcpy(trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
|
||||||
memset(&msg, 0, sizeof(msg));
|
memset(&msg, 0, sizeof(msg));
|
||||||
vec[0].iov_base = &pclc;
|
vec[0].iov_base = &pclc;
|
||||||
|
|
|
@ -122,8 +122,8 @@ smc_clc_proposal_get_prefix(struct smc_clc_msg_proposal *pclc)
|
||||||
((u8 *)pclc + sizeof(*pclc) + ntohs(pclc->iparea_offset));
|
((u8 *)pclc + sizeof(*pclc) + ntohs(pclc->iparea_offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
int smc_clc_netinfo_by_tcpsk(struct socket *clcsock, __be32 *subnet,
|
int smc_clc_prfx_match(struct socket *clcsock,
|
||||||
u8 *prefix_len);
|
struct smc_clc_msg_proposal_prefix *prop);
|
||||||
int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
|
int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
|
||||||
u8 expected_type);
|
u8 expected_type);
|
||||||
int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info);
|
int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info);
|
||||||
|
|
Loading…
Add table
Reference in a new issue