Skip to content

Commit

Permalink
Merge pull request #899 from ywc689/synproxy-bugfix
Browse files Browse the repository at this point in the history
ipvs: fix synproxy window scale setting problem
  • Loading branch information
ywc689 authored Jul 13, 2023
2 parents f371d84 + 9bcd301 commit 0dd5120
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 29 deletions.
2 changes: 1 addition & 1 deletion conf/dpvs.bond.conf.sample
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ ipvs_defs {
mss 1452
ttl 63
sack
! wscale
! wscale 0
! timestamp
}
! defer_rs_syn
Expand Down
4 changes: 2 additions & 2 deletions conf/dpvs.conf.items
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,10 @@ ipvs_defs {
mss 1452 <1452, 1-65535>
ttl 63 <63, 1-255>
sack <enable>
! wscale <disable>
! wscale <0, 0-14>
! timestamp <disable>
}
close_client_window <enable>
!close_client_window <disable>
!defer_rs_syn <disable>
rs_syn_max_retry 3 <3, 1-99>
ack_storm_thresh 10 <10, 1-999>
Expand Down
2 changes: 1 addition & 1 deletion conf/dpvs.conf.sample
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ ipvs_defs {
mss 1452
ttl 63
sack
! wscale
! wscale 0
! timestamp
}
close_client_window
Expand Down
2 changes: 1 addition & 1 deletion conf/dpvs.conf.single-bond.sample
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ ipvs_defs {
mss 1452
ttl 63
sack
! wscale
! wscale 0
! timestamp
}
close_client_window
Expand Down
2 changes: 1 addition & 1 deletion conf/dpvs.conf.single-nic.sample
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ ipvs_defs {
mss 1452
ttl 63
sack
! wscale
! wscale 0
! timestamp
}
close_client_window
Expand Down
4 changes: 3 additions & 1 deletion include/ipvs/conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,9 @@ struct dp_vs_conn {
/* synproxy related members */
struct dp_vs_seq syn_proxy_seq; /* seq used in synproxy */
struct list_head ack_mbuf; /* ack mbuf saved in step2 */
uint32_t ack_num; /* ack mbuf number stored */
uint16_t ack_num; /* ack mbuf number stored */
uint8_t wscale_vs; /* outbound wscale factor to client */
uint8_t wscale_rs; /* outbound wscale factor from rs */
struct rte_mbuf *syn_mbuf; /* saved rs syn packet for retransmition */
rte_atomic32_t syn_retry_max; /* syn retransmition max packets */

Expand Down
12 changes: 12 additions & 0 deletions src/ipvs/ip_vs_proto_tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,16 @@ static void tcp_out_save_seq(struct rte_mbuf *mbuf,
conn->rs_end_ack = th->ack_seq;
}

static void tcp_out_adjust_window(struct dp_vs_conn *conn, struct tcphdr *th)
{
uint32_t wnd_client;

wnd_client = ntohs(th->window) * (1 << conn->wscale_rs) / (1 << conn->wscale_vs);
if (unlikely(wnd_client > 0xffff))
wnd_client = 0xffff;
th->window = htons(wnd_client);
}

static void tcp_out_adjust_mss(int af, struct tcphdr *tcph)
{
unsigned char *ptr;
Expand Down Expand Up @@ -763,6 +773,8 @@ static int tcp_fnat_out_handler(struct dp_vs_proto *proto,
th->source = conn->vport;
th->dest = conn->cport;

tcp_out_adjust_window(conn, th);

if (th->syn && th->ack)
tcp_out_adjust_mss(af, th);

Expand Down
93 changes: 71 additions & 22 deletions src/ipvs/ip_vs_synproxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
#define DP_VS_SYNPROXY_SACK_DEFAULT 1
#define DP_VS_SYNPROXY_WSCALE_DEFAULT 0
#define DP_VS_SYNPROXY_TIMESTAMP_DEFAULT 0
#define DP_VS_SYNPROXY_CLWND_DEFAULT 1
#define DP_VS_SYNPROXY_CLWND_DEFAULT 0
#define DP_VS_SYNPROXY_DEFER_DEFAULT 0
#define DP_VS_SYNPROXY_DUP_ACK_DEFAULT 10
#define DP_VS_SYNPROXY_MAX_ACK_SAVED_DEFAULT 3
Expand All @@ -55,7 +55,7 @@ int dp_vs_synproxy_ctrl_sack = DP_VS_SYNPROXY_SACK_DEFAULT;
int dp_vs_synproxy_ctrl_wscale = DP_VS_SYNPROXY_WSCALE_DEFAULT;
int dp_vs_synproxy_ctrl_timestamp = DP_VS_SYNPROXY_TIMESTAMP_DEFAULT;
int dp_vs_synproxy_ctrl_synack_ttl = DP_VS_SYNPROXY_TTL_DEFAULT;
int dp_synproxy_ctrl_clwnd = DP_VS_SYNPROXY_CLWND_DEFAULT;
int dp_vs_synproxy_ctrl_clwnd = DP_VS_SYNPROXY_CLWND_DEFAULT;
int dp_vs_synproxy_ctrl_defer = DP_VS_SYNPROXY_DEFER_DEFAULT;
int dp_vs_synproxy_ctrl_conn_reuse = DP_VS_SYNPROXY_CONN_REUSE_DEFAULT;
int dp_vs_synproxy_ctrl_conn_reuse_cl = DP_VS_SYNPROXY_CONN_REUSE_CL_DEFAULT;
Expand Down Expand Up @@ -414,12 +414,11 @@ syn_proxy_v4_cookie_check(struct rte_mbuf *mbuf, uint32_t cookie,
th->source, th->dest, seq, rte_atomic32_read(&g_minute_count),
DP_VS_SYNPROXY_COUNTER_TRIES);

memset(opt, 0, sizeof(struct dp_vs_synproxy_opt));
if ((uint32_t) -1 == res) /* count is invalid, g_minute_count' >> g_minute_count */
return 0;

mssind = (res & DP_VS_SYNPROXY_MSS_MASK) >> DP_VS_SYNPROXY_MSS_BITS;

memset(opt, 0, sizeof(struct dp_vs_synproxy_opt));
if ((mssind < NUM_MSS) && ((res & DP_VS_SYNPROXY_OTHER_MASK) == 0)) {
opt->mss_clamp = msstab[mssind] + 1;
opt->sack_ok = (res & DP_VS_SYNPROXY_SACKOK_MASK) >> DP_VS_SYNPROXY_SACKOK_BIT;
Expand Down Expand Up @@ -451,12 +450,11 @@ syn_proxy_v6_cookie_check(struct rte_mbuf *mbuf, uint32_t cookie,
th->source, th->dest, seq, rte_atomic32_read(&g_minute_count),
DP_VS_SYNPROXY_COUNTER_TRIES);

memset(opt, 0, sizeof(struct dp_vs_synproxy_opt));
if ((uint32_t) -1 == res) /* count is invalid, g_minute_count' >> g_minute_count */
return 0;

mssind = (res & DP_VS_SYNPROXY_MSS_MASK) >> DP_VS_SYNPROXY_MSS_BITS;

memset(opt, 0, sizeof(struct dp_vs_synproxy_opt));
if ((mssind < NUM_MSS) && ((res & DP_VS_SYNPROXY_OTHER_MASK) == 0)) {
opt->mss_clamp = msstab[mssind] + 1;
opt->sack_ok = (res & DP_VS_SYNPROXY_SACKOK_MASK) >> DP_VS_SYNPROXY_SACKOK_BIT;
Expand All @@ -479,6 +477,40 @@ syn_proxy_v6_cookie_check(struct rte_mbuf *mbuf, uint32_t cookie,
* Synproxy implementation
*/

static unsigned char syn_proxy_parse_wscale_opt(struct rte_mbuf *mbuf, struct tcphdr *th)
{
int length;
unsigned char opcode, opsize;
unsigned char *ptr;

length = (th->doff * 4) - sizeof(struct tcphdr);
ptr = (unsigned char *)(th + 1);
while (length > 0) {
opcode = *ptr++;
switch (opcode) {
case TCPOPT_EOL:
return 0;
case TCPOPT_NOP:
length--;
continue;
default:
opsize = *ptr++;
if (opsize < 2) /* silly options */
return 0;
if (opsize > length) /* partial options */
return 0;
if (opcode == TCPOPT_WINDOW) {
if (*ptr > DP_VS_SYNPROXY_WSCALE_MAX) /* invalid wscale opt */
return 0;
return *ptr;
}
ptr += opsize -2;
length -= opsize;
}
}
return 0; /* should never reach here */
}

/* Replace tcp options in tcp header, called by syn_proxy_reuse_mbuf() */
static void syn_proxy_parse_set_opts(struct rte_mbuf *mbuf, struct tcphdr *th,
struct dp_vs_synproxy_opt *opt)
Expand Down Expand Up @@ -613,7 +645,7 @@ static void syn_proxy_reuse_mbuf(int af, struct rte_mbuf *mbuf,
th->dest = th->source;
th->source = tmpport;
/* set window size to zero if enabled */
if (dp_synproxy_ctrl_clwnd && !dp_vs_synproxy_ctrl_defer)
if (dp_vs_synproxy_ctrl_clwnd && !dp_vs_synproxy_ctrl_defer)
th->window = 0;
/* set seq(cookie) and ack_seq */
th->ack_seq = htonl(ntohl(th->seq) + 1);
Expand Down Expand Up @@ -1191,6 +1223,9 @@ int dp_vs_synproxy_ack_rcv(int af, struct rte_mbuf *mbuf,
return 0;
}

if (opt.wscale_ok)
(*cpp)->wscale_vs = dp_vs_synproxy_ctrl_wscale;

/* Do nothing but print a error msg when fail, because session will be
* correctly freed in dp_vs_conn_expire */
if (EDPVS_OK != (res = syn_proxy_send_rs_syn(af, th, *cpp, mbuf, pp, &opt))) {
Expand Down Expand Up @@ -1409,6 +1444,7 @@ int dp_vs_synproxy_synack_rcv(struct rte_mbuf *mbuf, struct dp_vs_conn *cp,
if ((th->syn) && (th->ack) && (!th->rst) &&
(cp->flags & DPVS_CONN_F_SYNPROXY) &&
(cp->state == DPVS_TCP_S_SYN_SENT)) {
cp->wscale_rs = syn_proxy_parse_wscale_opt(mbuf, th);
cp->syn_proxy_seq.delta = ntohl(cp->syn_proxy_seq.isn) - ntohl(th->seq);
cp->state = DPVS_TCP_S_ESTABLISHED;
dp_vs_conn_set_timeout(cp, pp);
Expand Down Expand Up @@ -1459,7 +1495,7 @@ int dp_vs_synproxy_synack_rcv(struct rte_mbuf *mbuf, struct dp_vs_conn *cp,
* The probe will be forward to RS and RS will respond a window update.
* So DPVS has no need to send a window update.
*/
if (dp_synproxy_ctrl_clwnd && !dp_vs_synproxy_ctrl_defer && cp->ack_num <= 1)
if (dp_vs_synproxy_ctrl_clwnd && !dp_vs_synproxy_ctrl_defer && cp->ack_num <= 1)
syn_proxy_send_window_update(tuplehash_out(cp).af, mbuf, cp, pp, th);

list_for_each_entry_safe(tmbuf, tmbuf2, &cp->ack_mbuf, list) {
Expand Down Expand Up @@ -1793,8 +1829,21 @@ static void synack_sack_handler(vector_t tokens)

static void synack_wscale_handler(vector_t tokens)
{
RTE_LOG(INFO, IPVS, "synproxy_synack_options_wscale ON\n");
dp_vs_synproxy_ctrl_wscale = 1;
char *str = set_value(tokens);
int wscale;

assert(str);
wscale = atoi(str);
if (wscale >= 0 && wscale <= DP_VS_SYNPROXY_WSCALE_MAX) {
RTE_LOG(INFO, IPVS, "synproxy_synack_options_wscale = %d\n", wscale);
dp_vs_synproxy_ctrl_wscale = wscale;
} else {
RTE_LOG(WARNING, IPVS, "invalid synproxy_synack_options_wscale %s, using default %d\n",
str, DP_VS_SYNPROXY_WSCALE_DEFAULT);
dp_vs_synproxy_ctrl_init_mss = DP_VS_SYNPROXY_WSCALE_DEFAULT;
}

FREE_PTR(str);
}

static void synack_timestamp_handler(vector_t tokens)
Expand All @@ -1806,7 +1855,7 @@ static void synack_timestamp_handler(vector_t tokens)
static void close_client_window_handler(vector_t tokens)
{
RTE_LOG(INFO, IPVS, "close_client_window ON\n");
dp_synproxy_ctrl_clwnd = 1;
dp_vs_synproxy_ctrl_clwnd = 1;
}

static void defer_rs_syn_handler(vector_t tokens)
Expand Down Expand Up @@ -1914,18 +1963,18 @@ void synproxy_keyword_value_init(void)
}
/* KW_TYPE_NORMAL keyword */
dp_vs_synproxy_ctrl_init_mss = DP_VS_SYNPROXY_INIT_MSS_DEFAULT;
dp_vs_synproxy_ctrl_sack = 0;
dp_vs_synproxy_ctrl_wscale = 0;
dp_vs_synproxy_ctrl_timestamp = 0;
dp_vs_synproxy_ctrl_sack = DP_VS_SYNPROXY_SACK_DEFAULT;
dp_vs_synproxy_ctrl_wscale = DP_VS_SYNPROXY_WSCALE_DEFAULT;
dp_vs_synproxy_ctrl_timestamp = DP_VS_SYNPROXY_TIMESTAMP_DEFAULT;
dp_vs_synproxy_ctrl_synack_ttl = DP_VS_SYNPROXY_TTL_DEFAULT;
dp_synproxy_ctrl_clwnd = 0;
dp_vs_synproxy_ctrl_defer = 0;
dp_vs_synproxy_ctrl_conn_reuse = 0;
dp_vs_synproxy_ctrl_conn_reuse_cl = 0;
dp_vs_synproxy_ctrl_conn_reuse_tw = 0;
dp_vs_synproxy_ctrl_conn_reuse_fw = 0;
dp_vs_synproxy_ctrl_conn_reuse_cw = 0;
dp_vs_synproxy_ctrl_conn_reuse_la = 0;
dp_vs_synproxy_ctrl_clwnd = DP_VS_SYNPROXY_CLWND_DEFAULT;
dp_vs_synproxy_ctrl_defer = DP_VS_SYNPROXY_DEFER_DEFAULT;
dp_vs_synproxy_ctrl_conn_reuse = DP_VS_SYNPROXY_CONN_REUSE_DEFAULT;
dp_vs_synproxy_ctrl_conn_reuse_cl = DP_VS_SYNPROXY_CONN_REUSE_CL_DEFAULT;
dp_vs_synproxy_ctrl_conn_reuse_tw = DP_VS_SYNPROXY_CONN_REUSE_TW_DEFAULT;
dp_vs_synproxy_ctrl_conn_reuse_fw = DP_VS_SYNPROXY_CONN_REUSE_FW_DEFAULT;
dp_vs_synproxy_ctrl_conn_reuse_cw = DP_VS_SYNPROXY_CONN_REUSE_CW_DEFAULT;
dp_vs_synproxy_ctrl_conn_reuse_la = DP_VS_SYNPROXY_CONN_REUSE_LA_DEFAULT;
dp_vs_synproxy_ctrl_dup_ack_thresh = DP_VS_SYNPROXY_DUP_ACK_DEFAULT;
dp_vs_synproxy_ctrl_max_ack_saved = DP_VS_SYNPROXY_MAX_ACK_SAVED_DEFAULT;
dp_vs_synproxy_ctrl_syn_retry = DP_VS_SYNPROXY_SYN_RETRY_DEFAULT;
Expand Down

0 comments on commit 0dd5120

Please sign in to comment.