net/smc: small features 2018/04/30
v2 cover net/smc: small features 2018/04/30
From: Ursula Braun <[email protected]>
Dave,
here are 4 smc patches for net-next covering small new features in different areas:
* link health check
* diagnostics for IPv6 smc sockets
* ioctl
* improvement for vlan determination
v2 changes:
* better title
* patch 2 - remove compile problem for disabled CONFIG_IPV6
Thanks, Ursula
Karsten Graul (2):
net/smc: periodic testlink support
net/smc: ipv6 support for smc_diag.c
Ursula Braun (2):
net/smc: handle ioctls SIOCINQ, SIOCOUTQ, and SIOCOUTQNSD net/smc: determine vlan_id of stacked net_device
net/smc/af_smc.c | 39 +++++++++++++++++++++++++++++----- net/smc/smc_core.c | 28 +++++++++++++++++++++--- net/smc/smc_core.h | 4 ++++ net/smc/smc_diag.c | 39 ++++++++++++++++++++++++++-------- net/smc/smc_llc.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++- net/smc/smc_llc.h | 3 +++ net/smc/smc_wr.c | 1 + 7 files changed, 158 insertions(+), 18 deletions(-)
Signature · 1 line
2.13.5
PATCH v2 1/4 net/smc: periodic testlink support
From: Karsten Graul <[email protected]>
Add periodic LLC testlink support to ensure the link is still active. The interval time is initialized using the value of sysctl_tcp_keepalive_time.
--- net/smc/af_smc.c | 6 ++++-- net/smc/smc_core.c | 2 ++ net/smc/smc_core.h | 4 ++++ net/smc/smc_llc.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++- net/smc/smc_llc.h | 3 +++ net/smc/smc_wr.c | 1 + 6 files changed, 75 insertions(+), 3 deletions(-)
net/smc/af_smc.c +4 -2
@@ -294,6 +294,7 @@ static void smc_copy_sock_settings_to_smc(struct smc_sock *smc)static int smc_clnt_conf_first_link (struct smc_sock *smc) { +struct net *net =sock_net (smc->clcsock->sk);struct smc_link_group *lgr = smc->conn.lgr;struct smc_link *link;int rest;
@@ -353,7 +354,7 @@ static int smc_clnt_conf_first_link(struct smc_sock *smc)if (rc <0 )return SMC_CLC_DECL_TCL ; - link->state =SMC_LNK_ACTIVE ; +smc_llc_link_active (link, net->ipv4.sysctl_tcp_keepalive_time);return 0 ; }
@@ -715,6 +716,7 @@ void smc_close_non_accepted(struct sock *sk)static int smc_serv_conf_first_link (struct smc_sock *smc) { +struct net *net =sock_net (smc->clcsock->sk);struct smc_link_group *lgr = smc->conn.lgr;struct smc_link *link;int rest;
@@ -769,7 +771,7 @@ static int smc_serv_conf_first_link(struct smc_sock *smc)return rc; } - link->state =SMC_LNK_ACTIVE ; +smc_llc_link_active (link, net->ipv4.sysctl_tcp_keepalive_time);return 0 ; }
net/smc/smc_core.c +2 -0
@@ -310,6 +310,7 @@ static void smc_lgr_free_bufs(struct smc_link_group *lgr)/* remove a link group */ void smc_lgr_free (struct smc_link_group *lgr) { +smc_llc_link_flush (&lgr->lnk[SMC_SINGLE_LINK ]);smc_lgr_free_bufs (lgr);smc_link_clear (&lgr->lnk[SMC_SINGLE_LINK ]);kfree (lgr);
@@ -332,6 +333,7 @@ void smc_lgr_terminate(struct smc_link_group *lgr)struct rb_node *node;smc_lgr_forget (lgr); +smc_llc_link_inactive (&lgr->lnk[SMC_SINGLE_LINK ]);write_lock_bh (&lgr->conns_lock); node =rb_first (&lgr->conns_all);
net/smc/smc_core.h +4 -0
@@ -79,6 +79,7 @@ struct smc_link {dma_addr_t wr_rx_dma_addr;/* DMA address of wr_rx_bufs */ u64 wr_rx_id;/* seq # of last recv WR */ u32 wr_rx_cnt;/* number of WR recv buffers */ +unsigned long wr_rx_tstamp;/* jiffies when last buf rx */ struct ib_reg_wr wr_reg;/* WR register memory region */ wait_queue_head_t wr_reg_wait;/* wait for wr_reg result */
@@ -101,6 +102,9 @@ struct smc_link {int llc_confirm_resp_rc;/* rc from conf_resp msg */ struct completion llc_add;/* wait for rx of add link */ struct completion llc_add_resp;/* wait for rx of add link rsp*/ +struct delayed_work llc_testlink_wrk;/* testlink worker */ +struct completion llc_testlink_resp;/* wait for rx of testlink */ +int llc_testlink_time;/* testlink interval */ };/* For now we just allow one parallel link per link group. The SMC protocol
net/smc/smc_llc.c +61 -1
74 lines not on this page · raw message
net/smc/smc_llc.h +3 -0
@@ -44,6 +44,9 @@ int smc_llc_send_delete_link(struct smc_link *link, enum smc_llc_reqresp reqresp);int smc_llc_send_test_link (struct smc_link *lnk,u8 user_data[16 ],enum smc_llc_reqresp reqresp); +void smc_llc_link_active (struct smc_link *link,int testlink_time); +void smc_llc_link_inactive (struct smc_link *link); +void smc_llc_link_flush (struct smc_link *link);int smc_llc_init (void )__init ;#endif /* SMC_LLC_H */
net/smc/smc_wr.c +1 -0
@@ -376,6 +376,7 @@ static inline void smc_wr_rx_process_cqes(struct ib_wc wc[], int num)for (i =0 ; i < num; i++) { link = wc[i].qp->qp_context;if (wc[i].status ==IB_WC_SUCCESS ) { + link->wr_rx_tstamp = jiffies;smc_wr_rx_demultiplex (&wc[i]);smc_wr_rx_post (link);/* refill WR RX */ }else {
Signature · 1 line
2.13.5
PATCH v2 2/4 net/smc: ipv6 support for smc_diag.c
In reply to Ursula BraunFrom: Karsten Graul <[email protected]>
Update smc_diag.c to support ipv6 addresses on the diagnosis interface.
--- net/smc/smc_diag.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-)
net/smc/smc_diag.c +30 -9
@@ -38,17 +38,27 @@ static void smc_diag_msg_common_fill(struct smc_diag_msg *r, struct sock *sk) {struct smc_sock *smc =smc_sk (sk); - r->diag_family = sk->sk_family;if (!smc->clcsock)return ; r->id.idiag_sport =htons (smc->clcsock->sk->sk_num); r->id.idiag_dport = smc->clcsock->sk->sk_dport; r->id.idiag_if = smc->clcsock->sk->sk_bound_dev_if;sock_diag_save_cookie (sk, r->id.idiag_cookie); -memset (&r->id.idiag_src,0 ,sizeof (r->id.idiag_src)); -memset (&r->id.idiag_dst,0 ,sizeof (r->id.idiag_dst)); - r->id.idiag_src[0 ] = smc->clcsock->sk->sk_rcv_saddr; - r->id.idiag_dst[0 ] = smc->clcsock->sk->sk_daddr; +if (sk->sk_protocol ==SMCPROTO_SMC ) { + r->diag_family =PF_INET ; +memset (&r->id.idiag_src,0 ,sizeof (r->id.idiag_src)); +memset (&r->id.idiag_dst,0 ,sizeof (r->id.idiag_dst)); + r->id.idiag_src[0 ] = smc->clcsock->sk->sk_rcv_saddr; + r->id.idiag_dst[0 ] = smc->clcsock->sk->sk_daddr; +#if IS_ENABLED (CONFIG_IPV6 ) + } else if (sk->sk_protocol == SMCPROTO_SMC6) { + r->diag_family =PF_INET6 ; +memcpy (&r->id.idiag_src, &smc->clcsock->sk->sk_v6_rcv_saddr, +sizeof (smc->clcsock->sk->sk_v6_rcv_saddr)); +memcpy (&r->id.idiag_dst, &smc->clcsock->sk->sk_v6_daddr, +sizeof (smc->clcsock->sk->sk_v6_daddr)); +#endif + } } static int smc_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
@@ -153,7 +163,8 @@ static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb,return -EMSGSIZE ; } -static int smc_diag_dump (struct sk_buff *skb,struct netlink_callback *cb) +static int smc_diag_dump_proto (struct proto *prot,struct sk_buff *skb, +struct netlink_callback *cb) {struct net *net =sock_net (skb->sk);struct nlattr *bc =NULL ;
@@ -161,8 +172,8 @@ static int smc_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)struct sock *sk;int rc =0 ; -read_lock (&smc_proto.h.smc_hash->lock); - head = &smc_proto.h.smc_hash->ht; +read_lock (&prot->h.smc_hash->lock); + head = &prot->h.smc_hash->ht;if (hlist_empty (head)) goto out;
@@ -175,7 +186,17 @@ static int smc_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) } out: -read_unlock (&smc_proto.h.smc_hash->lock); +read_unlock (&prot->h.smc_hash->lock); +return rc; +} + +static int smc_diag_dump (struct sk_buff *skb,struct netlink_callback *cb) +{ +int rc =0 ; + + rc =smc_diag_dump_proto (&smc_proto, skb, cb); +if (!rc) + rc =smc_diag_dump_proto (&smc_proto6, skb, cb);return rc; }
Signature · 1 line
2.13.5
Re: [net-next,v2,2/4] net/smc: ipv6 support for smc_diag.c
Quoted 34 lines · Ursula Braun
From: Karsten Graul <[email protected]>
Update
smc_diag.cto support ipv6 addresses on the diagnosis interface.Signed-off-by Karsten Graul <[email protected]>Signed-off-by Ursula Braun <[email protected]>--- net/smc/smc_diag.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-)net/smc/smc_diag.c +5
-5@@ -38,17 +38,27 @@ static void smc_diag_msg_common_fill(struct smc_diag_msg *r, struct sock *sk) {struct smc_sock *smc =smc_sk (sk); - r->diag_family = sk->sk_family;if (!smc->clcsock)return ; r->id.idiag_sport =htons (smc->clcsock->sk->sk_num); r->id.idiag_dport = smc->clcsock->sk->sk_dport; r->id.idiag_if = smc->clcsock->sk->sk_bound_dev_if;sock_diag_save_cookie (sk, r->id.idiag_cookie); -memset (&r->id.idiag_src,0 ,sizeof (r->id.idiag_src)); -memset (&r->id.idiag_dst,0 ,sizeof (r->id.idiag_dst)); - r->id.idiag_src[0 ] = smc->clcsock->sk->sk_rcv_saddr; - r->id.idiag_dst[0 ] = smc->clcsock->sk->sk_daddr; +if (sk->sk_protocol ==SMCPROTO_SMC ) { + r->diag_family =PF_INET ; +memset (&r->id.idiag_src,0 ,sizeof (r->id.idiag_src)); +memset (&r->id.idiag_dst,0 ,sizeof (r->id.idiag_dst)); + r->id.idiag_src[0 ] = smc->clcsock->sk->sk_rcv_saddr;
net/smc/smc_diag.c static void smc_diag_msg_common_fill(struct smc_diag_msg *r, struct sock *sk) · line 61
Quoted 10 lines
net/smc/smc_diag.c +10
-0+ r->id.idiag_dst[0 ] = smc->clcsock->sk->sk_daddr; +#if IS_ENABLED (CONFIG_IPV6 ) + } else if (sk->sk_protocol == SMCPROTO_SMC6) { + r->diag_family =PF_INET6 ; +memcpy (&r->id.idiag_src, &smc->clcsock->sk->sk_v6_rcv_saddr, +sizeof (smc->clcsock->sk->sk_v6_rcv_saddr)); +memcpy (&r->id.idiag_dst, &smc->clcsock->sk->sk_v6_daddr, +sizeof (smc->clcsock->sk->sk_v6_daddr)); +#endif + }
This change makes it impossible to distinguish an inet_sock_diag response message from SMC sock_diag response (previously it reported AF_SMC in diag_family which allows deciding whether that a part of struct smc_diag_msg or struct inet_diag_msg).
Re: [net-next,v2,2/4] net/smc: ipv6 support for smc_diag.c
Quoted 42 lines · Eugene Syromiatnikov
Quoted 41 lines · Ursula Braun
From: Karsten Graul <[email protected]>
Update
smc_diag.cto support ipv6 addresses on the diagnosis interface.Signed-off-by Karsten Graul <[email protected]>Signed-off-by Ursula Braun <[email protected]>--- net/smc/smc_diag.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-)net/smc/smc_diag.c +12
-5@@ -38,17 +38,27 @@ static void smc_diag_msg_common_fill(struct smc_diag_msg *r, struct sock *sk) {struct smc_sock *smc =smc_sk (sk); - r->diag_family = sk->sk_family;if (!smc->clcsock)return ; r->id.idiag_sport =htons (smc->clcsock->sk->sk_num); r->id.idiag_dport = smc->clcsock->sk->sk_dport; r->id.idiag_if = smc->clcsock->sk->sk_bound_dev_if;sock_diag_save_cookie (sk, r->id.idiag_cookie); -memset (&r->id.idiag_src,0 ,sizeof (r->id.idiag_src)); -memset (&r->id.idiag_dst,0 ,sizeof (r->id.idiag_dst)); - r->id.idiag_src[0 ] = smc->clcsock->sk->sk_rcv_saddr; - r->id.idiag_dst[0 ] = smc->clcsock->sk->sk_daddr; +if (sk->sk_protocol ==SMCPROTO_SMC ) { + r->diag_family =PF_INET ; +memset (&r->id.idiag_src,0 ,sizeof (r->id.idiag_src)); +memset (&r->id.idiag_dst,0 ,sizeof (r->id.idiag_dst)); + r->id.idiag_src[0 ] = smc->clcsock->sk->sk_rcv_saddr; + r->id.idiag_dst[0 ] = smc->clcsock->sk->sk_daddr; +#if IS_ENABLED (CONFIG_IPV6 ) + } else if (sk->sk_protocol == SMCPROTO_SMC6) { + r->diag_family =PF_INET6 ; +memcpy (&r->id.idiag_src, &smc->clcsock->sk->sk_v6_rcv_saddr, +sizeof (smc->clcsock->sk->sk_v6_rcv_saddr)); + memcpy(&r->id.idiag_dst, &smc->clcsock->sk->sk_v6_daddr,
Quoted 9 lines
net/smc/smc_diag.c static void smc_diag_msg_common_fill(struct smc_diag_msg *r, struct sock *sk) · line 61
Quoted 3 lines
net/smc/smc_diag.c +3
-0+ sizeof(smc->clcsock->sk->sk_v6_daddr)); +#endif + }This change makes it impossible to distinguish an
inet_sock_diagresponse message from SMCsock_diagresponse (previously it reportedAF_SMCindiag_familywhich allows deciding whether that a part of structsmc_diag_msgor structinet_diag_msg).
Eugene,
we are considering the following patch:
--- net/smc/smc_diag.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
net/smc/smc_diag.c +1 -2
@@ -38,6 +38,7 @@ static void smc_diag_msg_common_fill(struct smc_diag_msg *r, struct sock *sk) {struct smc_sock *smc =smc_sk (sk); + r->diag_family = sk->sk_family;if (!smc->clcsock)return ; r->id.idiag_sport =htons (smc->clcsock->sk->sk_num);
@@ -45,14 +46,12 @@ static void smc_diag_msg_common_fill(struct smc_diag_msg *r, struct sock *sk) r->id.idiag_if = smc->clcsock->sk->sk_bound_dev_if;sock_diag_save_cookie (sk, r->id.idiag_cookie);if (sk->sk_protocol ==SMCPROTO_SMC ) { - r->diag_family =PF_INET ;memset (&r->id.idiag_src,0 ,sizeof (r->id.idiag_src));memset (&r->id.idiag_dst,0 ,sizeof (r->id.idiag_dst)); r->id.idiag_src[0 ] = smc->clcsock->sk->sk_rcv_saddr; r->id.idiag_dst[0 ] = smc->clcsock->sk->sk_daddr;#if IS_ENABLED (CONFIG_IPV6 ) } else if (sk->sk_protocol == SMCPROTO_SMC6) { - r->diag_family =PF_INET6 ;memcpy (&r->id.idiag_src, &smc->clcsock->sk->sk_v6_rcv_saddr,sizeof (smc->clcsock->sk->sk_v6_rcv_saddr)); memcpy(&r->id.idiag_dst, &smc->clcsock->sk->sk_v6_daddr,
Re: [net-next,v2,2/4] net/smc: ipv6 support for smc_diag.c
Quoted 37 lines · Ursula Braun
Eugene,
we are considering the following patch:
--- net/smc/smc_diag.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)net/smc/smc_diag.c +1
-3@@ -38,6 +38,7 @@ static void smc_diag_msg_common_fill(struct smc_diag_msg *r, struct sock *sk) {struct smc_sock *smc =smc_sk (sk); + r->diag_family = sk->sk_family;if (!smc->clcsock)return ; r->id.idiag_sport =htons (smc->clcsock->sk->sk_num);@@ -45,14 +46,12 @@ static void smc_diag_msg_common_fill(struct smc_diag_msg *r, struct sock *sk) r->id.idiag_if = smc->clcsock->sk->sk_bound_dev_if;sock_diag_save_cookie (sk, r->id.idiag_cookie);if (sk->sk_protocol ==SMCPROTO_SMC ) { - r->diag_family =PF_INET ;memset (&r->id.idiag_src,0 ,sizeof (r->id.idiag_src));memset (&r->id.idiag_dst,0 ,sizeof (r->id.idiag_dst)); r->id.idiag_src[0 ] = smc->clcsock->sk->sk_rcv_saddr; r->id.idiag_dst[0 ] = smc->clcsock->sk->sk_daddr;#if IS_ENABLED (CONFIG_IPV6 ) } else if (sk->sk_protocol == SMCPROTO_SMC6) { - r->diag_family =PF_INET6 ;memcpy (&r->id.idiag_src, &smc->clcsock->sk->sk_v6_rcv_saddr,sizeof (smc->clcsock->sk->sk_v6_rcv_saddr)); memcpy(&r->id.idiag_dst, &smc->clcsock->sk->sk_v6_daddr, --
Quoted 2 lines
Tools would then need to derive the PF_INET/PF_INET6 info from the
inet_diag_sockidinfo in thesmc_diag_msg.
Unfortunately, struct inet_diag_sockid doesn't provide any clue in order to derive address family.
There's unused (if I haven't missed anything) diag_shutdown field in struct smc_diag_msg (it looks like that the shutdown state is reported via a separate attribute in the current implementation), it probably might be repurposed for providing information about the underlying socket address family.
Quoted 2 lines
However, this problem is in the mainline kernel since 4.18. So, we are not sure if we are allowed to change the user interface again.
Well, anything is better that the current state.
PATCH v2 3/4 net/smc: handle ioctls SIOCINQ, SIOCOUTQ, and SIOCOUTQNSD
In reply to Ursula BraunSIOCINQ returns the amount of unread data in the RMB. SIOCOUTQ returns the amount of unsent or unacked sent data in the send buffer.
SIOCOUTQNSD returns the amount of data prepared for sending, but not yet sent.
--- net/smc/af_smc.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-)
net/smc/af_smc.c +30 -3
@@ -29,6 +29,7 @@#include <net/sock.h> #include <net/tcp.h> #include <net/smc.h> +#include <asm/ioctls.h> #include "smc.h" #include "smc_clc.h"
@@ -1389,12 +1390,38 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) {struct smc_sock *smc; +int answ; smc =smc_sk (sock->sk); -if (smc->use_fallback) +if (smc->use_fallback) { +if (!smc->clcsock) +return -EBADF ;return smc->clcsock->ops->ioctl (smc->clcsock, cmd, arg); -else -return sock_no_ioctl (sock, cmd, arg); + } +switch (cmd) { +case SIOCINQ :/* same as FIONREAD */ +if (smc->sk.sk_state ==SMC_LISTEN ) +return -EINVAL ; + answ =atomic_read (&smc->conn.bytes_to_rcv); +break ; +case SIOCOUTQ : +/* output queue size (not send + not acked) */ +if (smc->sk.sk_state ==SMC_LISTEN ) +return -EINVAL ; + answ = smc->conn.sndbuf_size - +atomic_read (&smc->conn.sndbuf_space); +break ; +case SIOCOUTQNSD : +/* output queue size (not send only) */ +if (smc->sk.sk_state ==SMC_LISTEN ) +return -EINVAL ; + answ =smc_tx_prepared_sends (&smc->conn); +break ; +default : +return -ENOIOCTLCMD ; + } + +return put_user (answ, (int __user *)arg); } static ssize_t smc_sendpage(struct socket *sock, struct page *page,
Signature · 1 line
2.13.5
PATCH v2 4/4 net/smc: determine vlan_id of stacked net_device
In reply to Ursula BraunAn SMC link group is bound to a specific vlan_id. Its link uses the RoCE-GIDs established for the specific vlan_id. This patch makes sure the appropriate vlan_id is determined for stacked scenarios like for instance a master bonding device with vlan devices enslaved.
--- net/smc/smc_core.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-)
net/smc/smc_core.c +23 -3
@@ -360,7 +360,8 @@ void smc_lgr_terminate(struct smc_link_group *lgr)static int smc_vlan_by_tcpsk (struct socket *clcsock,unsigned short *vlan_id) {struct dst_entry *dst =sk_dst_get (clcsock->sk); -int rc =0 ; +struct net_device *ndev; +int i, nest_lvl, rc =0 ; *vlan_id =0 ;if (!dst) {
@@ -372,8 +373,27 @@ static int smc_vlan_by_tcpsk(struct socket *clcsock, unsigned short *vlan_id) goto out_rel; } -if (is_vlan_dev (dst->dev)) - *vlan_id =vlan_dev_vlan_id (dst->dev); + ndev = dst->dev; +if (is_vlan_dev (ndev)) { + *vlan_id =vlan_dev_vlan_id (ndev); + goto out_rel; + } + +rtnl_lock (); + nest_lvl =dev_get_nest_level (ndev); +for (i =0 ; i < nest_lvl; i++) { +struct list_head *lower = &ndev->adj_list.lower; + +if (list_empty (lower)) +break ; + 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); +break ; + } + } +rtnl_unlock (); out_rel:dst_release (dst);
Signature · 1 line
2.13.5
David Miller
maintainerFrom: Ursula Braun <[email protected]>
Date: Wed, 2 May 2018 16:56:43 +0200
Quoted 10 lines
here are 4 smc patches for net-next covering small new features in different areas:
* link health check
* diagnostics for IPv6 smc sockets
* ioctl
* improvement for vlan determinationv2 changes:
* better title
* patch 2 - remove compile problem for disabledCONFIG_IPV6
Series applied, thank you.