From: Sowmini Varadhan Date: Fri, 16 Jun 2017 20:30:20 +0000 (-0700) Subject: rds: tcp: various endian-ness fixes X-Git-Tag: v4.1.12-104.0.20170618_1145~9 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=827ce89751a9a89666615d507d897c7a111fbe5a;p=users%2Fjedix%2Flinux-maple.git rds: tcp: various endian-ness fixes Found when testing between sparc and x86 machines on different subnets, so the address comparison patterns hit the corner cases and brought out some bugs fixed by this patch. Orabug: 26289770 (Cherry-pick of upstream commit 00354de5779db4aa9c019db787ef89bd1a6b149b) Signed-off-by: Sowmini Varadhan Tested-by: Imanti Mendez Acked-by: Santosh Shilimkar Signed-off-by: David S. Miller --- diff --git a/net/rds/rds.h b/net/rds/rds.h index acb0efaae371..5cb7109da4bd 100644 --- a/net/rds/rds.h +++ b/net/rds/rds.h @@ -223,6 +223,8 @@ enum rds_conn_drop_src { DR_TCP_SEND_FAIL, }; +#define IS_CANONICAL(laddr, faddr) (htonl(laddr) < htonl(faddr)) + /* Per mpath connection state */ struct rds_conn_path { struct rds_connection *cp_conn; diff --git a/net/rds/recv.c b/net/rds/recv.c index e4ba384a1575..bf8c8b55a7a0 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c @@ -266,10 +266,10 @@ static void rds_recv_hs_exthdrs(struct rds_header *hdr, switch (type) { case RDS_EXTHDR_NPATHS: conn->c_npaths = min_t(int, RDS_MPATH_WORKERS, - buffer.rds_npaths); + be16_to_cpu(buffer.rds_npaths)); break; case RDS_EXTHDR_GEN_NUM: - new_peer_gen_num = buffer.rds_gen_num; + new_peer_gen_num = be32_to_cpu(buffer.rds_gen_num); break; default: pr_warn_ratelimited("ignoring unknown exthdr type " @@ -305,7 +305,8 @@ static void rds_start_mprds(struct rds_connection *conn) int i; struct rds_conn_path *cp; - if (conn->c_npaths > 1 && conn->c_laddr < conn->c_faddr) { + if (conn->c_npaths > 1 && + IS_CANONICAL(conn->c_laddr, conn->c_faddr)) { for (i = 1; i < conn->c_npaths; i++) { cp = &conn->c_path[i]; rds_conn_path_connect_if_down(cp); @@ -668,15 +669,15 @@ rds_recv_local(struct rds_conn_path *cp, __be32 saddr, __be32 daddr, /* if this is a handshake ping, * start multipath if necessary */ - if (RDS_HS_PROBE(inc->i_hdr.h_sport, - inc->i_hdr.h_dport)) { + if (RDS_HS_PROBE(be16_to_cpu(inc->i_hdr.h_sport), + be16_to_cpu(inc->i_hdr.h_dport))) { rds_recv_hs_exthdrs(&inc->i_hdr, cp->cp_conn); rds_start_mprds(cp->cp_conn); } } goto out; } - if (inc->i_hdr.h_dport == RDS_FLAG_PROBE_PORT && + if (be16_to_cpu(inc->i_hdr.h_dport) == RDS_FLAG_PROBE_PORT && inc->i_hdr.h_sport == 0) { rds_recv_hs_exthdrs(&inc->i_hdr, cp->cp_conn); /* if this is a handshake pong, start multipath if necessary */ diff --git a/net/rds/send.c b/net/rds/send.c index 3491d7ef24a1..1a700869054e 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -1644,15 +1644,17 @@ rds_send_probe(struct rds_conn_path *cp, __be16 sport, rm->m_inc.i_hdr.h_flags |= h_flags; cp->cp_next_tx_seq++; - if (RDS_HS_PROBE(sport, dport) && cp->cp_conn->c_trans->t_mp_capable) { - u16 npaths = RDS_MPATH_WORKERS; + if (RDS_HS_PROBE(be16_to_cpu(sport), be16_to_cpu(dport)) && + cp->cp_conn->c_trans->t_mp_capable) { + u16 npaths = cpu_to_be16(RDS_MPATH_WORKERS); + u32 my_gen_num = cpu_to_be32(cp->cp_conn->c_my_gen_num); rds_message_add_extension(&rm->m_inc.i_hdr, RDS_EXTHDR_NPATHS, &npaths, sizeof(npaths)); rds_message_add_extension(&rm->m_inc.i_hdr, RDS_EXTHDR_GEN_NUM, - &cp->cp_conn->c_my_gen_num, + &my_gen_num, sizeof(u32)); } spin_unlock_irqrestore(&cp->cp_lock, flags); @@ -1735,5 +1737,6 @@ rds_send_ping(struct rds_connection *conn) } conn->c_ping_triggered = 1; spin_unlock_irqrestore(&cp->cp_lock, flags); - rds_send_probe(&conn->c_path[0], RDS_FLAG_PROBE_PORT, 0, 0); + rds_send_probe(&conn->c_path[0], cpu_to_be16(RDS_FLAG_PROBE_PORT), + 0, 0); } diff --git a/net/rds/tcp_connect.c b/net/rds/tcp_connect.c index ead79debd205..17d8936b9d92 100644 --- a/net/rds/tcp_connect.c +++ b/net/rds/tcp_connect.c @@ -60,7 +60,8 @@ void rds_tcp_state_change(struct sock *sk) case TCP_SYN_RECV: break; case TCP_ESTABLISHED: - if (cp->cp_conn->c_laddr > cp->cp_conn->c_faddr && + if (!IS_CANONICAL(cp->cp_conn->c_laddr, + cp->cp_conn->c_faddr) && rds_conn_path_transition(cp, RDS_CONN_CONNECTING, RDS_CONN_ERROR)) { rds_conn_path_drop(cp, DR_TCP_STATE_CLOSE); diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c index f78a83af6509..66090ded4033 100644 --- a/net/rds/tcp_listen.c +++ b/net/rds/tcp_listen.c @@ -81,7 +81,7 @@ bail: struct rds_tcp_connection *rds_tcp_accept_one_path(struct rds_connection *conn) { int i; - bool peer_is_smaller = (conn->c_faddr < conn->c_laddr); + bool peer_is_smaller = IS_CANONICAL(conn->c_faddr, conn->c_laddr); int npaths = max_t(int, 1, conn->c_npaths); if (!peer_is_smaller) { diff --git a/net/rds/threads.c b/net/rds/threads.c index 1e0ea785e4db..dda33cda1331 100644 --- a/net/rds/threads.c +++ b/net/rds/threads.c @@ -144,7 +144,7 @@ void rds_queue_reconnect(struct rds_conn_path *cp) cp->cp_reconnect_jiffies); /* let peer with smaller addr initiate reconnect, to avoid duels */ - if (is_tcp && conn->c_laddr > conn->c_faddr) + if (is_tcp && !IS_CANONICAL(conn->c_laddr, conn->c_faddr)) return; set_bit(RDS_RECONNECT_PENDING, &cp->cp_flags); @@ -178,7 +178,7 @@ void rds_connect_worker(struct work_struct *work) bool is_tcp = conn->c_trans->t_type == RDS_TRANS_TCP; if (is_tcp && cp->cp_index > 0 && - cp->cp_conn->c_laddr > cp->cp_conn->c_faddr) + !IS_CANONICAL(cp->cp_conn->c_laddr, cp->cp_conn->c_faddr)) return; clear_bit(RDS_RECONNECT_PENDING, &cp->cp_flags); ret = rds_conn_path_transition(cp, RDS_CONN_DOWN, RDS_CONN_CONNECTING);