Commit 0c3a16be authored by Atul Gupta's avatar Atul Gupta Committed by David S. Miller

crypto/chelsio/chtls: send/recv window update

recalculated send and receive window using linkspeed.
Determine correct value of eck_ok from SYN received and
option configured on local system.
Signed-off-by: default avatarAtul Gupta <atul.gupta@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 848dd1c1
...@@ -220,6 +220,8 @@ struct chtls_sock { ...@@ -220,6 +220,8 @@ struct chtls_sock {
u16 resv2; u16 resv2;
u32 delack_mode; u32 delack_mode;
u32 delack_seq; u32 delack_seq;
u32 snd_win;
u32 rcv_win;
void *passive_reap_next; /* placeholder for passive */ void *passive_reap_next; /* placeholder for passive */
struct chtls_hws tlshws; struct chtls_hws tlshws;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/kallsyms.h> #include <linux/kallsyms.h>
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <net/inet_common.h>
#include <net/tcp.h> #include <net/tcp.h>
#include <net/dst.h> #include <net/dst.h>
...@@ -887,24 +888,6 @@ static unsigned int chtls_select_mss(const struct chtls_sock *csk, ...@@ -887,24 +888,6 @@ static unsigned int chtls_select_mss(const struct chtls_sock *csk,
return mtu_idx; return mtu_idx;
} }
static unsigned int select_rcv_wnd(struct chtls_sock *csk)
{
unsigned int rcvwnd;
unsigned int wnd;
struct sock *sk;
sk = csk->sk;
wnd = tcp_full_space(sk);
if (wnd < MIN_RCV_WND)
wnd = MIN_RCV_WND;
rcvwnd = MAX_RCV_WND;
csk_set_flag(csk, CSK_UPDATE_RCV_WND);
return min(wnd, rcvwnd);
}
static unsigned int select_rcv_wscale(int space, int wscale_ok, int win_clamp) static unsigned int select_rcv_wscale(int space, int wscale_ok, int win_clamp)
{ {
int wscale = 0; int wscale = 0;
...@@ -951,7 +934,7 @@ static void chtls_pass_accept_rpl(struct sk_buff *skb, ...@@ -951,7 +934,7 @@ static void chtls_pass_accept_rpl(struct sk_buff *skb,
csk->mtu_idx = chtls_select_mss(csk, dst_mtu(__sk_dst_get(sk)), csk->mtu_idx = chtls_select_mss(csk, dst_mtu(__sk_dst_get(sk)),
req); req);
opt0 = TCAM_BYPASS_F | opt0 = TCAM_BYPASS_F |
WND_SCALE_V((tp)->rx_opt.rcv_wscale) | WND_SCALE_V(RCV_WSCALE(tp)) |
MSS_IDX_V(csk->mtu_idx) | MSS_IDX_V(csk->mtu_idx) |
L2T_IDX_V(csk->l2t_entry->idx) | L2T_IDX_V(csk->l2t_entry->idx) |
NAGLE_V(!(tp->nonagle & TCP_NAGLE_OFF)) | NAGLE_V(!(tp->nonagle & TCP_NAGLE_OFF)) |
...@@ -1005,6 +988,25 @@ static int chtls_backlog_rcv(struct sock *sk, struct sk_buff *skb) ...@@ -1005,6 +988,25 @@ static int chtls_backlog_rcv(struct sock *sk, struct sk_buff *skb)
return 0; return 0;
} }
static void chtls_set_tcp_window(struct chtls_sock *csk)
{
struct net_device *ndev = csk->egress_dev;
struct port_info *pi = netdev_priv(ndev);
unsigned int linkspeed;
u8 scale;
linkspeed = pi->link_cfg.speed;
scale = linkspeed / SPEED_10000;
#define CHTLS_10G_RCVWIN (256 * 1024)
csk->rcv_win = CHTLS_10G_RCVWIN;
if (scale)
csk->rcv_win *= scale;
#define CHTLS_10G_SNDWIN (256 * 1024)
csk->snd_win = CHTLS_10G_SNDWIN;
if (scale)
csk->snd_win *= scale;
}
static struct sock *chtls_recv_sock(struct sock *lsk, static struct sock *chtls_recv_sock(struct sock *lsk,
struct request_sock *oreq, struct request_sock *oreq,
void *network_hdr, void *network_hdr,
...@@ -1067,6 +1069,9 @@ static struct sock *chtls_recv_sock(struct sock *lsk, ...@@ -1067,6 +1069,9 @@ static struct sock *chtls_recv_sock(struct sock *lsk,
csk->port_id = port_id; csk->port_id = port_id;
csk->egress_dev = ndev; csk->egress_dev = ndev;
csk->tos = PASS_OPEN_TOS_G(ntohl(req->tos_stid)); csk->tos = PASS_OPEN_TOS_G(ntohl(req->tos_stid));
chtls_set_tcp_window(csk);
tp->rcv_wnd = csk->rcv_win;
csk->sndbuf = csk->snd_win;
csk->ulp_mode = ULP_MODE_TLS; csk->ulp_mode = ULP_MODE_TLS;
step = cdev->lldi->nrxq / cdev->lldi->nchan; step = cdev->lldi->nrxq / cdev->lldi->nchan;
csk->rss_qid = cdev->lldi->rxq_ids[port_id * step]; csk->rss_qid = cdev->lldi->rxq_ids[port_id * step];
...@@ -1076,9 +1081,9 @@ static struct sock *chtls_recv_sock(struct sock *lsk, ...@@ -1076,9 +1081,9 @@ static struct sock *chtls_recv_sock(struct sock *lsk,
csk->sndbuf = newsk->sk_sndbuf; csk->sndbuf = newsk->sk_sndbuf;
csk->smac_idx = cxgb4_tp_smt_idx(cdev->lldi->adapter_type, csk->smac_idx = cxgb4_tp_smt_idx(cdev->lldi->adapter_type,
cxgb4_port_viid(ndev)); cxgb4_port_viid(ndev));
tp->rcv_wnd = select_rcv_wnd(csk);
RCV_WSCALE(tp) = select_rcv_wscale(tcp_full_space(newsk), RCV_WSCALE(tp) = select_rcv_wscale(tcp_full_space(newsk),
WSCALE_OK(tp), sock_net(newsk)->
ipv4.sysctl_tcp_window_scaling,
tp->window_clamp); tp->window_clamp);
neigh_release(n); neigh_release(n);
inet_inherit_port(&tcp_hashinfo, lsk, newsk); inet_inherit_port(&tcp_hashinfo, lsk, newsk);
...@@ -1130,6 +1135,7 @@ static void chtls_pass_accept_request(struct sock *sk, ...@@ -1130,6 +1135,7 @@ static void chtls_pass_accept_request(struct sock *sk,
struct cpl_t5_pass_accept_rpl *rpl; struct cpl_t5_pass_accept_rpl *rpl;
struct cpl_pass_accept_req *req; struct cpl_pass_accept_req *req;
struct listen_ctx *listen_ctx; struct listen_ctx *listen_ctx;
struct vlan_ethhdr *vlan_eh;
struct request_sock *oreq; struct request_sock *oreq;
struct sk_buff *reply_skb; struct sk_buff *reply_skb;
struct chtls_sock *csk; struct chtls_sock *csk;
...@@ -1142,6 +1148,10 @@ static void chtls_pass_accept_request(struct sock *sk, ...@@ -1142,6 +1148,10 @@ static void chtls_pass_accept_request(struct sock *sk,
unsigned int stid; unsigned int stid;
unsigned int len; unsigned int len;
unsigned int tid; unsigned int tid;
bool th_ecn, ect;
__u8 ip_dsfield; /* IPv4 tos or IPv6 dsfield */
u16 eth_hdr_len;
bool ecn_ok;
req = cplhdr(skb) + RSS_HDR; req = cplhdr(skb) + RSS_HDR;
tid = GET_TID(req); tid = GET_TID(req);
...@@ -1180,24 +1190,40 @@ static void chtls_pass_accept_request(struct sock *sk, ...@@ -1180,24 +1190,40 @@ static void chtls_pass_accept_request(struct sock *sk,
oreq->mss = 0; oreq->mss = 0;
oreq->ts_recent = 0; oreq->ts_recent = 0;
eh = (struct ethhdr *)(req + 1); eth_hdr_len = T6_ETH_HDR_LEN_G(ntohl(req->hdr_len));
iph = (struct iphdr *)(eh + 1); if (eth_hdr_len == ETH_HLEN) {
eh = (struct ethhdr *)(req + 1);
iph = (struct iphdr *)(eh + 1);
network_hdr = (void *)(eh + 1);
} else {
vlan_eh = (struct vlan_ethhdr *)(req + 1);
iph = (struct iphdr *)(vlan_eh + 1);
network_hdr = (void *)(vlan_eh + 1);
}
if (iph->version != 0x4) if (iph->version != 0x4)
goto free_oreq; goto free_oreq;
network_hdr = (void *)(eh + 1);
tcph = (struct tcphdr *)(iph + 1); tcph = (struct tcphdr *)(iph + 1);
skb_set_network_header(skb, (void *)iph - (void *)req);
tcp_rsk(oreq)->tfo_listener = false; tcp_rsk(oreq)->tfo_listener = false;
tcp_rsk(oreq)->rcv_isn = ntohl(tcph->seq); tcp_rsk(oreq)->rcv_isn = ntohl(tcph->seq);
chtls_set_req_port(oreq, tcph->source, tcph->dest); chtls_set_req_port(oreq, tcph->source, tcph->dest);
inet_rsk(oreq)->ecn_ok = 0;
chtls_set_req_addr(oreq, iph->daddr, iph->saddr); chtls_set_req_addr(oreq, iph->daddr, iph->saddr);
if (req->tcpopt.wsf <= 14) { ip_dsfield = ipv4_get_dsfield(iph);
if (req->tcpopt.wsf <= 14 &&
sock_net(sk)->ipv4.sysctl_tcp_window_scaling) {
inet_rsk(oreq)->wscale_ok = 1; inet_rsk(oreq)->wscale_ok = 1;
inet_rsk(oreq)->snd_wscale = req->tcpopt.wsf; inet_rsk(oreq)->snd_wscale = req->tcpopt.wsf;
} }
inet_rsk(oreq)->ir_iif = sk->sk_bound_dev_if; inet_rsk(oreq)->ir_iif = sk->sk_bound_dev_if;
th_ecn = tcph->ece && tcph->cwr;
if (th_ecn) {
ect = !INET_ECN_is_not_ect(ip_dsfield);
ecn_ok = sock_net(sk)->ipv4.sysctl_tcp_ecn;
if ((!ect && ecn_ok) || tcp_ca_needs_ecn(sk))
inet_rsk(oreq)->ecn_ok = 1;
}
newsk = chtls_recv_sock(sk, oreq, network_hdr, req, cdev); newsk = chtls_recv_sock(sk, oreq, network_hdr, req, cdev);
if (!newsk) if (!newsk)
......
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