Skip to content

Commit ef67891

Browse files
committed
prov/efa: Add packet entry flag tracking for double linked list management
Add flags EFA_RDM_PKE_IN_PEER_OUTSTANDING_TX_PKTS and EFA_RDM_PKE_IN_OPE_QUEUED_PKTS to track packet entry insertion status in outstanding_tx_pkts and queued_pkts lists. Update insertion/removal operations to set/clear these flags and modify efa_rdm_pke_release_tx() to safely remove packets from lists based on flag state. Add comprehensive unit test to verify flag tracking behavior. Signed-off-by: Shi Jin <[email protected]>
1 parent c68c24f commit ef67891

File tree

6 files changed

+117
-2
lines changed

6 files changed

+117
-2
lines changed

prov/efa/src/rdm/efa_rdm_ep_utils.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -409,9 +409,11 @@ void efa_rdm_ep_record_tx_op_submitted(struct efa_rdm_ep *ep, struct efa_rdm_pke
409409
* and the RMA is a local read toward the endpoint itself
410410
*/
411411
peer = ope->peer;
412-
if (peer)
412+
if (peer) {
413413
dlist_insert_tail(&pkt_entry->entry,
414414
&peer->outstanding_tx_pkts);
415+
pkt_entry->flags |= EFA_RDM_PKE_IN_PEER_OUTSTANDING_TX_PKTS;
416+
}
415417

416418
assert(pkt_entry->alloc_type == EFA_RDM_PKE_FROM_EFA_TX_POOL);
417419
ep->efa_outstanding_tx_ops++;
@@ -471,8 +473,10 @@ void efa_rdm_ep_record_tx_op_completed(struct efa_rdm_ep *ep, struct efa_rdm_pke
471473
* a new peer has the same GID+QPN was inserted to address, or because
472474
* application removed the peer from address vector.
473475
*/
474-
if (pkt_entry->peer)
476+
if (pkt_entry->peer) {
475477
dlist_remove(&pkt_entry->entry);
478+
pkt_entry->flags &= ~EFA_RDM_PKE_IN_PEER_OUTSTANDING_TX_PKTS;
479+
}
476480

477481
assert(pkt_entry->alloc_type == EFA_RDM_PKE_FROM_EFA_TX_POOL);
478482
ep->efa_outstanding_tx_ops--;
@@ -543,6 +547,7 @@ void efa_rdm_ep_queue_rnr_pkt(struct efa_rdm_ep *ep, struct efa_rdm_pke *pkt_ent
543547

544548
assert(ope);
545549
dlist_insert_tail(&pkt_entry->entry, &ope->queued_pkts);
550+
pkt_entry->flags |= EFA_RDM_PKE_IN_OPE_QUEUED_PKTS;
546551
ep->efa_rnr_queued_pkt_cnt += 1;
547552
assert(peer);
548553
if (!(ope->internal_flags & EFA_RDM_OPE_QUEUED_RNR)) {
@@ -783,6 +788,7 @@ ssize_t efa_rdm_ep_post_queued_pkts(struct efa_rdm_ep *ep,
783788
* be removed from the list before send.
784789
*/
785790
dlist_remove(&pkt_entry->entry);
791+
pkt_entry->flags &= ~EFA_RDM_PKE_IN_OPE_QUEUED_PKTS;
786792

787793
switch (efa_rdm_pkt_type_of(pkt_entry)) {
788794
case EFA_RDM_RMA_CONTEXT_PKT:
@@ -798,6 +804,7 @@ ssize_t efa_rdm_ep_post_queued_pkts(struct efa_rdm_ep *ep,
798804
if (ret == -FI_EAGAIN) {
799805
/* add the pkt back to pkts, so it can be resent again */
800806
dlist_insert_tail(&pkt_entry->entry, pkts);
807+
pkt_entry->flags |= EFA_RDM_PKE_IN_OPE_QUEUED_PKTS;
801808
}
802809

803810
return ret;

prov/efa/src/rdm/efa_rdm_pke.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,14 @@ void efa_rdm_pke_release_tx(struct efa_rdm_pke *pkt_entry)
118118
#if ENABLE_DEBUG
119119
dlist_remove(&pkt_entry->dbg_entry);
120120
#endif
121+
/*
122+
* Remove packet from double linked lists if it was inserted
123+
*/
124+
if (pkt_entry->flags & (EFA_RDM_PKE_IN_PEER_OUTSTANDING_TX_PKTS | EFA_RDM_PKE_IN_OPE_QUEUED_PKTS)) {
125+
dlist_remove(&pkt_entry->entry);
126+
pkt_entry->flags &= ~(EFA_RDM_PKE_IN_PEER_OUTSTANDING_TX_PKTS | EFA_RDM_PKE_IN_OPE_QUEUED_PKTS);
127+
}
128+
121129
/*
122130
* Decrement rnr_queued_pkts counter and reset backoff for this peer if
123131
* we get a send completion for a retransmitted packet.

prov/efa/src/rdm/efa_rdm_pke.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#define EFA_RDM_PKE_LOCAL_WRITE BIT_ULL(4) /**< this packet entry is used as context of an RDMA Write to self */
1717
#define EFA_RDM_PKE_SEND_TO_USER_RECV_QP BIT_ULL(5) /**< this packet entry is used for posting send to a dedicated QP that doesn't expect any pkt hdrs */
1818
#define EFA_RDM_PKE_HAS_NO_BASE_HDR BIT_ULL(6) /**< This packet entry's wiredata contains no base header */
19+
#define EFA_RDM_PKE_IN_PEER_OUTSTANDING_TX_PKTS BIT_ULL(7) /**< this packet entry is in peer->outstanding_tx_pkts list */
20+
#define EFA_RDM_PKE_IN_OPE_QUEUED_PKTS BIT_ULL(8) /**< this packet entry is in ope->queued_pkts list */
1921

2022
#define EFA_RDM_PKE_ALIGNMENT 128
2123

@@ -137,6 +139,8 @@ struct efa_rdm_pke {
137139
* @see #EFA_RDM_PKE_LOCAL_WRITE
138140
* @see #EFA_RDM_PKE_SEND_TO_USER_RECV_QP
139141
* @see #EFA_RDM_PKE_HAS_NO_BASE_HDR
142+
* @see #EFA_RDM_PKE_IN_PEER_OUTSTANDING_TX_PKTS
143+
* @see #EFA_RDM_PKE_IN_OPE_QUEUED_PKTS
140144
*/
141145
uint32_t flags;
142146

prov/efa/test/efa_unit_test_pke.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,96 @@ void test_efa_rdm_pke_get_unexp(struct efa_resource **state)
275275
assert_int_equal(efa_unit_test_get_dlist_length(&efa_rdm_ep->rx_pkt_list), 1);
276276
#endif
277277
}
278+
279+
/**
280+
* @brief Test packet entry flag tracking for double linked list insertion/removal
281+
*
282+
* This test verifies that packet entries correctly track their insertion status
283+
* in outstanding_tx_pkts and queued_pkts lists using internal flags, and that
284+
* the release function properly removes them from the appropriate lists.
285+
*
286+
* @param state
287+
*/
288+
void test_efa_rdm_pke_flag_tracking(struct efa_resource **state)
289+
{
290+
struct efa_resource *resource = *state;
291+
struct efa_rdm_ep *efa_rdm_ep;
292+
struct efa_rdm_pke *pkt_entry;
293+
struct efa_rdm_peer *peer;
294+
struct efa_rdm_ope *txe;
295+
struct fi_msg msg = {0};
296+
char buf[16];
297+
struct iovec iov = {
298+
.iov_base = buf,
299+
.iov_len = sizeof(buf)
300+
};
301+
struct efa_ep_addr raw_addr = {0};
302+
size_t raw_addr_len = sizeof(struct efa_ep_addr);
303+
fi_addr_t peer_addr;
304+
int err, numaddr;
305+
306+
efa_unit_test_resource_construct(resource, FI_EP_RDM, EFA_FABRIC_NAME);
307+
308+
efa_rdm_ep = container_of(resource->ep, struct efa_rdm_ep, base_ep.util_ep.ep_fid);
309+
310+
/* Create a fake peer */
311+
err = fi_getname(&resource->ep->fid, &raw_addr, &raw_addr_len);
312+
assert_int_equal(err, 0);
313+
raw_addr.qpn = 1;
314+
raw_addr.qkey = 0x1234;
315+
numaddr = fi_av_insert(resource->av, &raw_addr, 1, &peer_addr, 0, NULL);
316+
assert_int_equal(numaddr, 1);
317+
peer = efa_rdm_ep_get_peer(efa_rdm_ep, peer_addr);
318+
assert_non_null(peer);
319+
320+
/* Create a txe */
321+
msg.addr = peer_addr;
322+
msg.iov_count = 1;
323+
msg.msg_iov = &iov;
324+
msg.desc = NULL;
325+
txe = efa_rdm_ep_alloc_txe(efa_rdm_ep, peer, &msg, ofi_op_msg, 0, 0);
326+
assert_non_null(txe);
327+
328+
/* Allocate a packet entry */
329+
pkt_entry = efa_rdm_pke_alloc(efa_rdm_ep, efa_rdm_ep->efa_tx_pkt_pool, EFA_RDM_PKE_FROM_EFA_TX_POOL);
330+
assert_non_null(pkt_entry);
331+
pkt_entry->ope = txe;
332+
pkt_entry->peer = peer;
333+
334+
/* Initially, packet should not be in any list */
335+
assert_int_equal(pkt_entry->flags & EFA_RDM_PKE_IN_PEER_OUTSTANDING_TX_PKTS, 0);
336+
assert_int_equal(pkt_entry->flags & EFA_RDM_PKE_IN_OPE_QUEUED_PKTS, 0);
337+
assert_true(dlist_empty(&peer->outstanding_tx_pkts));
338+
assert_true(dlist_empty(&txe->queued_pkts));
339+
340+
/* Test insertion into outstanding_tx_pkts */
341+
efa_rdm_ep_record_tx_op_submitted(efa_rdm_ep, pkt_entry);
342+
assert_int_not_equal(pkt_entry->flags & EFA_RDM_PKE_IN_PEER_OUTSTANDING_TX_PKTS, 0);
343+
assert_int_equal(pkt_entry->flags & EFA_RDM_PKE_IN_OPE_QUEUED_PKTS, 0);
344+
assert_false(dlist_empty(&peer->outstanding_tx_pkts));
345+
assert_true(dlist_empty(&txe->queued_pkts));
346+
347+
/* Test removal from outstanding_tx_pkts */
348+
efa_rdm_ep_record_tx_op_completed(efa_rdm_ep, pkt_entry);
349+
assert_int_equal(pkt_entry->flags & EFA_RDM_PKE_IN_PEER_OUTSTANDING_TX_PKTS, 0);
350+
assert_int_equal(pkt_entry->flags & EFA_RDM_PKE_IN_OPE_QUEUED_PKTS, 0);
351+
assert_true(dlist_empty(&peer->outstanding_tx_pkts));
352+
assert_true(dlist_empty(&txe->queued_pkts));
353+
354+
/* Test insertion into queued_pkts */
355+
efa_rdm_ep_queue_rnr_pkt(efa_rdm_ep, pkt_entry);
356+
assert_int_equal(pkt_entry->flags & EFA_RDM_PKE_IN_PEER_OUTSTANDING_TX_PKTS, 0);
357+
assert_int_not_equal(pkt_entry->flags & EFA_RDM_PKE_IN_OPE_QUEUED_PKTS, 0);
358+
assert_true(dlist_empty(&peer->outstanding_tx_pkts));
359+
assert_false(dlist_empty(&txe->queued_pkts));
360+
361+
/* Test that release_tx removes from queued_pkts */
362+
efa_rdm_pke_release_tx(pkt_entry);
363+
assert_true(dlist_empty(&peer->outstanding_tx_pkts));
364+
assert_true(dlist_empty(&txe->queued_pkts));
365+
366+
/* Clean up */
367+
efa_rdm_txe_release(txe);
368+
}
369+
370+

prov/efa/test/efa_unit_tests.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,8 @@ int main(void)
322322
cmocka_unit_test_setup_teardown(test_efa_rdm_pke_alloc_rtw_rxe, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown),
323323
cmocka_unit_test_setup_teardown(test_efa_rdm_pke_alloc_rtr_rxe, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown),
324324
cmocka_unit_test_setup_teardown(test_efa_rdm_pke_get_unexp, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown),
325+
cmocka_unit_test_setup_teardown(test_efa_rdm_pke_flag_tracking, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown),
326+
cmocka_unit_test_setup_teardown(test_efa_rdm_pke_flag_tracking, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown),
325327
/* end of efa_unit_test_pke.c */
326328

327329
/* begin efa_unit_test_domain.c */

prov/efa/test/efa_unit_tests.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ void test_efa_rdm_pke_alloc_rta_rxe();
320320
void test_efa_rdm_pke_alloc_rtw_rxe();
321321
void test_efa_rdm_pke_alloc_rtr_rxe();
322322
void test_efa_rdm_pke_get_unexp();
323+
void test_efa_rdm_pke_flag_tracking();
323324
/* end of efa_unit_test_pke.c */
324325

325326
void test_efa_msg_fi_recv();

0 commit comments

Comments
 (0)