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

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: default avatarKarsten Graul <kgraul@linux.vnet.ibm.com>
Signed-off-by: default avatarUrsula Braun <ubraun@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8b7372c1
...@@ -767,8 +767,6 @@ static void smc_listen_work(struct work_struct *work) ...@@ -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) ...@@ -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,15 +74,35 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm) ...@@ -74,15 +74,35 @@ 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 dst_entry *dst = sk_dst_get(clcsock->sk);
struct in_device *in_dev; struct sockaddr_storage addrs;
struct sockaddr_in addr; struct sockaddr_in *addr;
int rc = -ENOENT; int rc = -ENOENT;
memset(prop, 0, sizeof(*prop));
if (!dst) { if (!dst) {
rc = -ENOTCONN; rc = -ENOTCONN;
goto out; goto out;
...@@ -91,22 +111,58 @@ int smc_clc_netinfo_by_tcpsk(struct socket *clcsock, ...@@ -91,22 +111,58 @@ 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 */ /* get address to which the internal TCP socket is bound */
kernel_getsockname(clcsock, (struct sockaddr *)&addr); kernel_getsockname(clcsock, (struct sockaddr *)&addrs);
/* analyze IPv4 specific data of net_device belonging to TCP socket */ /* analyze IP specific data of net_device belonging to TCP socket */
rcu_read_lock(); rcu_read_lock();
in_dev = __in_dev_get_rcu(dst->dev); 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) { for_ifa(in_dev) {
if (!inet_ifa_match(addr.sin_addr.s_addr, ifa)) if (prop->prefix_len == inet_mask_len(ifa->ifa_mask) &&
continue; inet_ifa_match(prop->outgoing_subnet, ifa))
*prefix_len = inet_mask_len(ifa->ifa_mask); return 0;
*subnet = ifa->ifa_address & ifa->ifa_mask;
rc = 0;
break;
} endfor_ifa(in_dev); } endfor_ifa(in_dev);
rcu_read_unlock();
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);
int rc = -ENOENT;
if (!dst) {
rc = -ENOTCONN;
goto out;
}
if (!dst->dev) {
rc = -ENODEV;
goto out_rel;
}
rcu_read_lock();
if (!prop->ipv6_prefixes_cnt)
rc = smc_clc_prfx_match4_rcu(dst->dev, prop);
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, ...@@ -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, ...@@ -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) ...@@ -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);
......
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