Skip to content

Commit 9607a01

Browse files
Dag Moxnesjfvogel
authored andcommitted
rds: ib: need to flush neighbor cache for local peer connections on failover
On RDS connections to other hosts, the neighbor cache on the peer side normally will get flushed by means of GARP packets. For local connections (connections on the same host), GARP packets does not cause neighbor cache to be updated. To prevent RDS to use bad entries in the neighbor cache we need to flush the neighbor cache entries TO the IP-address when the IP-address is moved due to an ADDR_CHANGED event. Orabug: 30417190 Signed-off-by: Dag Moxnes <[email protected]> Reviewed-by: Ka-Cheong Poon <[email protected]> Signed-off-by: Somasundaram Krishnasamy <[email protected]> Orabug: 30820081 UEK5 => UEK6 (cherry picked from commit b63fbdb) cherry-pick-repo=UEK/production/linux-uek.git Signed-off-by: Gerd Rausch <[email protected]> Reviewed-by: Sharon Liu <[email protected]>
1 parent 179317f commit 9607a01

File tree

3 files changed

+47
-16
lines changed

3 files changed

+47
-16
lines changed

net/rds/ib.c

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -879,14 +879,8 @@ static unsigned int neigh_flush_interval = 750;
879879
/* Should be large enough to hold the flush message. */
880880
static unsigned int flush_buf_len = 48;
881881

882-
/* Given an rds_connection, flush the peer address' neighbor cache entry.
883-
* If the peer is not in the same network as us, nothing will be flushed.
884-
*
885-
* @net: the connection's namespace
886-
* @conn: pointer to the connection
887-
*/
888-
void rds_ib_flush_neigh(struct net *net,
889-
struct rds_connection *conn)
882+
static void __flush_neigh_conn(struct net *net,
883+
struct rds_connection *conn)
890884
{
891885
struct sockaddr_nl nlsa = { .nl_family = AF_NETLINK };
892886
u64 timenow = jiffies_to_msecs(get_jiffies_64());
@@ -982,4 +976,30 @@ void rds_ib_flush_neigh(struct net *net,
982976
kfree(sndbuf);
983977
}
984978

979+
/* Given an rds_connection, flush the peer address' neighbor cache entry.
980+
* If the peer is not in the same network as us, nothing will be flushed.
981+
*
982+
* @net: the connection's namespace
983+
* @conn: pointer to the connection
984+
* @flush_local_peer: Flush neighbor for the peer, if it is local, instead
985+
* of conn
986+
*/
987+
void rds_ib_flush_neigh(struct net *net,
988+
struct rds_connection *conn, bool flush_local_peer)
989+
{
990+
if (flush_local_peer && conn->c_loopback) {
991+
struct rds_connection *peer;
992+
993+
/* Note the swapped d/saddr */
994+
peer = rds_conn_find(rds_conn_net(conn),
995+
&conn->c_faddr, &conn->c_laddr,
996+
conn->c_trans, conn->c_tos,
997+
0);
998+
if (peer)
999+
__flush_neigh_conn(net, peer);
1000+
} else {
1001+
__flush_neigh_conn(net, conn);
1002+
}
1003+
}
1004+
9851005
MODULE_LICENSE("GPL");

net/rds/ib.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,9 @@ extern struct workqueue_struct *rds_aux_wq;
553553
extern struct rds_transport rds_ib_transport;
554554
extern void rds_ib_add_one(struct ib_device *device);
555555
extern void rds_ib_remove_one(struct ib_device *device, void *client_data);
556-
extern void rds_ib_flush_neigh(struct net *net, struct rds_connection *conn);
556+
extern void rds_ib_flush_neigh(struct net *net,
557+
struct rds_connection *conn,
558+
bool flush_local_peer);
557559
void rds_ib_srq_exit(struct rds_ib_device *rds_ibdev);
558560
int rds_ib_srq_init(struct rds_ib_device *rds_ibdev);
559561

net/rds/rdma_transport.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,15 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
9494
struct rds_connection *conn;
9595
struct rds_transport *trans = &rds_ib_transport;
9696
int ret = 0;
97+
/* ADDR_CHANGE event indicates that the local address has moved
98+
* to a different device, most likely due to failover/failback.
99+
* If this is a local connection (a connection to this host), we need
100+
* to flush the neighbor cache entry for the peer side of the
101+
* connection. In this case we do not need to flush this side of the
102+
* connection. If this is not a local connection, we still flush
103+
* the neighbor cache for the local side of the connection.
104+
*/
105+
bool flush_local_peer = event->event == RDMA_CM_EVENT_ADDR_CHANGE;
97106
int *err;
98107

99108
conn = rds_ib_get_conn(cm_id);
@@ -135,7 +144,7 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
135144
/* These events might indicate the IP being moved,
136145
* hence flush the address
137146
*/
138-
rds_ib_flush_neigh(&init_net, conn);
147+
rds_ib_flush_neigh(&init_net, conn, flush_local_peer);
139148
rds_rtd(RDS_RTD_CM, "Bailing, conn %p being shut down, ret: %d\n",
140149
conn, ret);
141150
goto out;
@@ -211,7 +220,7 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
211220

212221
case RDMA_CM_EVENT_ROUTE_ERROR:
213222
/* IP might have been moved so flush the ARP entry and retry */
214-
rds_ib_flush_neigh(&init_net, conn);
223+
rds_ib_flush_neigh(&init_net, conn, flush_local_peer);
215224

216225
rds_rtd_ptr(RDS_RTD_ERR,
217226
"ROUTE_ERROR: conn %p, calling rds_conn_drop <%pI6c,%pI6c,%d>\n",
@@ -227,7 +236,7 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
227236

228237
case RDMA_CM_EVENT_ADDR_ERROR:
229238
/* IP might have been moved so flush the ARP entry and retry */
230-
rds_ib_flush_neigh(&init_net, conn);
239+
rds_ib_flush_neigh(&init_net, conn, flush_local_peer);
231240

232241
rds_rtd_ptr(RDS_RTD_ERR,
233242
"ADDR_ERROR: conn %p, calling rds_conn_drop <%pI6c,%pI6c,%d>\n",
@@ -241,7 +250,7 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
241250
case RDMA_CM_EVENT_UNREACHABLE:
242251
case RDMA_CM_EVENT_DEVICE_REMOVAL:
243252
/* IP might have been moved so flush the ARP entry and retry */
244-
rds_ib_flush_neigh(&init_net, conn);
253+
rds_ib_flush_neigh(&init_net, conn, flush_local_peer);
245254

246255
rds_rtd_ptr(RDS_RTD_ERR,
247256
"CONN/UNREACHABLE/RMVAL ERR: conn %p, calling rds_conn_drop <%pI6c,%pI6c,%d>\n",
@@ -253,7 +262,7 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
253262

254263
case RDMA_CM_EVENT_REJECTED:
255264
/* May be due to ARP cache containing an incorrect dmac, hence flush it */
256-
rds_ib_flush_neigh(&init_net, conn);
265+
rds_ib_flush_neigh(&init_net, conn, flush_local_peer);
257266

258267
err = (int *)event->param.conn.private_data;
259268

@@ -299,7 +308,7 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
299308

300309
case RDMA_CM_EVENT_ADDR_CHANGE:
301310
/* IP might have been moved so flush the ARP entry and retry */
302-
rds_ib_flush_neigh(&init_net, conn);
311+
rds_ib_flush_neigh(&init_net, conn, flush_local_peer);
303312

304313
rds_rtd_ptr(RDS_RTD_CM_EXT,
305314
"ADDR_CHANGE event <%pI6c,%pI6c>\n",
@@ -314,7 +323,7 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
314323

315324
case RDMA_CM_EVENT_DISCONNECTED:
316325
/* IP might have been moved so flush the ARP entry and retry */
317-
rds_ib_flush_neigh(&init_net, conn);
326+
rds_ib_flush_neigh(&init_net, conn, flush_local_peer);
318327

319328
rds_rtd_ptr(RDS_RTD_CM,
320329
"DISCONNECT event - dropping conn %p <%pI6c,%pI6c,%d>\n",

0 commit comments

Comments
 (0)