in ncrx/libncrx.c [468:529]
static int queue_oos_msg(struct ncrx_msg *tmsg, struct ncrx *ncrx)
{
struct ncrx_slot *slot;
struct ncrx_msg *msg, *nmsg, *first;
msg = copy_msg(tmsg);
if (!msg)
return -1;
msg_list_append(msg, &ncrx->oos_list);
/*
* Shifted left automatically on each new msg. Set oos and see if
* there have been too many oos among the last 32 messages.
*/
ncrx->oos_history |= 1;
if ((signed)hweight32(ncrx->oos_history) < ncrx->p.oos_thr) {
/* nope, handle oos overflow and handle */
if (ncrx->oos_list.nr > NCRX_OOS_MAX) {
msg = msg_list_pop(&ncrx->oos_list);
if (msg) {
msg->oos = 1;
msg_list_append(msg, &ncrx->retired_list);
}
}
return 0;
}
/*
* The current sequence stream seems no good. Let's reset by
* retiring all pending, picking the oos msg with the lowest seq,
* queueing it to reset the seq and then queueing all other oos
* msgs. If a msg is still oos after reset, just retire it.
*/
while (ncrx->tail != ncrx->head)
retire_tail(ncrx);
ncrx->head_seq = 0;
ncrx->acked_seq = UINT64_MAX;
first = node_to_msg(ncrx->oos_list.head.next);
msg_list_for_each(msg, nmsg, &ncrx->oos_list)
first = msg->seq < first->seq ? msg : first;
msg_list_del(first, &ncrx->oos_list);
slot = get_seq_slot(first, ncrx);
slot->msg = first;
slot_maybe_complete(slot);
while ((msg = msg_list_pop(&ncrx->oos_list))) {
slot = get_seq_slot(msg, ncrx);
if (slot) {
slot->msg = msg;
slot_maybe_complete(slot);
} else {
msg->oos = 1;
msg_list_append(msg, &ncrx->retired_list);
}
}
return 0;
}