From: Wei Lin Guay Date: Mon, 19 Mar 2018 13:26:34 +0000 (+0100) Subject: net/rds: prevent RDS connections using stale ARP entries X-Git-Tag: v4.1.12-124.31.3~715 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=48c2d5f5e258;p=users%2Fjedix%2Flinux-maple.git net/rds: prevent RDS connections using stale ARP entries Active bonding fallback is an asynchronous event in the cluster. Thus, there is a potential race where a host has sent out a CM REQ, using a wrong remote gid, before IP migration happens at the remote end. The side effect of this issue causes RDS connections only use one physical IB port. When that particular IB port goes down, it causes send completion error on those RDS connections and eventually increases the brownout time. To avoid this phenomenon, RDS has to reject all incoming CM REQ after RDMA_CM_EVENT_DISCONNECTED or RDMA_CM_EVENT_ADDR_CHANGE events until route resolution has been performed locally. By doing so, we can ensure that the gratituos ARPs are sent to the remote end and RDS connections are established based on the correct ARP entries. Orabug: 28149101 Signed-off-by: Wei Lin Guay Tested-by: Dib Chatterjee (cherry picked from commit d7f00e2a0d30b0f14a763d96e6c8ae2ddb40a281 repo https://linux-git.us.oracle.com/UEK/linux-wguay-public) Signed-off-by: Brian Maly Conflicts: net/rds/rds.h net/rds/ib_cm.c Fixed checkpatch issues. Signed-off-by: HÃ¥kon Bugge Reviewed-by: Shannon Nelson Reviewed-by: Zhu Yanjun Signed-off-by: Brian Maly --- diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index 54a5d3d58461..53debab967c8 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c @@ -1066,6 +1066,18 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id, mutex_lock(&conn->c_cm_lock); ic = conn->c_transport_data; + if (conn->c_route && !rds_conn_self_loopback_passive(conn)) { + rds_rtd_ptr(RDS_RTD_CM, + "no route resolution saddr %pI4 daddr %pI4 RDSv%u.%u lguid 0x%llx fguid 0x%llx tos %d\n", + saddr6, daddr6, + RDS_PROTOCOL_MAJOR(version), + RDS_PROTOCOL_MINOR(version), + (unsigned long long)be64_to_cpu(lguid), + (unsigned long long)be64_to_cpu(fguid), + dp_cmn->ricpc_tos); + goto out; + } + if (ic && cm_seq_check_enable) { if (cm_req_seq != ic->i_prev_seq) { rds_rtd(RDS_RTD_CM_EXT_P, diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c index 6ae9aa0670f6..5d86ab12553f 100644 --- a/net/rds/rdma_transport.c +++ b/net/rds/rdma_transport.c @@ -164,6 +164,7 @@ int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id, * needs to update the sl manually. As for now, RDS is assuming * that it is a 1:1 in tos to sl mapping. */ + conn->c_route = 0; cm_id->route.path_rec[0].sl = TOS_TO_SL(conn->c_tos); cm_id->route.path_rec[0].qos_class = conn->c_tos; ret = trans->cm_initiate_connect(cm_id, isv6); @@ -291,6 +292,8 @@ int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id, &conn->c_laddr, &conn->c_faddr, conn->c_tos); conn->c_reconnect_racing = 0; + /* reset route resolution flag */ + conn->c_route = 1; if (!rds_conn_self_loopback_passive(conn)) rds_conn_drop(conn, DR_IB_ADDR_CHANGE); } @@ -301,6 +304,8 @@ int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id, "DISCONNECT event - dropping connection %pI6c->%pI6c tos %d\n", &conn->c_laddr, &conn->c_faddr, conn->c_tos); conn->c_reconnect_racing = 0; + /* reset route resolution flag */ + conn->c_route = 1; rds_conn_drop(conn, DR_IB_DISCONNECTED_EVENT); break; diff --git a/net/rds/rds.h b/net/rds/rds.h index 59f6063c3032..efd4e2532bdd 100644 --- a/net/rds/rds.h +++ b/net/rds/rds.h @@ -286,7 +286,7 @@ struct rds_conn_path { unsigned int cp_rdsinfo_pending; unsigned int cp_reconnect_racing; - + unsigned int cp_route_resolved; enum rds_conn_drop_src cp_drop_source; unsigned char cp_acl_init; @@ -327,7 +327,6 @@ struct rds_connection { int c_to_index; unsigned int c_reconnect; - /* Qos support */ u8 c_tos; diff --git a/net/rds/threads.c b/net/rds/threads.c index cc58563c6ba9..5a81e321d13c 100644 --- a/net/rds/threads.c +++ b/net/rds/threads.c @@ -102,6 +102,8 @@ void rds_connect_path_complete(struct rds_conn_path *cp, int curr) cp->cp_connection_start = get_seconds(); cp->cp_reconnect = 1; + /* reset route resolution flag */ + cp->cp_route_resolved = 0; conn->c_proposed_version = RDS_PROTOCOL_VERSION; } EXPORT_SYMBOL_GPL(rds_connect_path_complete);