laforge has uploaded this change for review.
octoi: slip frames if RIFO runs empty in IP->E1 direction
If the RIFO runs dry, it means somehow the E1 side is pulling frames
faster than the IP side delivers them, and we need to insert/invent
frames to re-gain sync and avoid a situation where we perpetually
substitute frames.
There is some danger in doing this as there are two situations where
this can arise:
1) clock drift as explained above
2) packet loss > RIFO depth _without loss of sync_. In this case
the clocks run at the same speed, but more 100ms of packets were
lost.
As we unconditionally assume '1', we damage our clock sync in '2'. This
probably needs some additional analysis, i.e. look at the current rate
of frames inserted into the FIFO to differentiate '1' from '2'.
Change-Id: Ic2a714fedb9a0698c17ef22447904a803c26ebfc
---
M src/octoi/e1oip.c
M src/octoi/e1oip.h
M src/octoi/frame_rifo.c
M src/octoi/octoi.c
4 files changed, 19 insertions(+), 4 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-e1d refs/changes/37/27837/1
diff --git a/src/octoi/e1oip.c b/src/octoi/e1oip.c
index 6a5a240..38a22b5 100644
--- a/src/octoi/e1oip.c
+++ b/src/octoi/e1oip.c
@@ -44,7 +44,8 @@
#include "e1oip.h"
static const struct rate_ctr_desc iline_ctr_description[] = {
- [LINE_CTR_E1oIP_UNDERRUN] = { "e1oip:underrun", "Frames missing/substituted in IP->E1 direction"},
+ [LINE_CTR_E1oIP_UNDERRUN] = { "e1oip:underrun", "Frames underrun / slipped in IP->E1 direction"},
+ [LINE_CTR_E1oIP_SUBSTITUTED] = { "e1oip:substituted", "Frames substituted in IP->E1 direction"},
[LINE_CTR_E1oIP_OVERFLOW] = { "e1oip:overflow", "Frames overflowed in IP->E1 direction"},
[LINE_CTR_E1oIP_RX_OUT_OF_ORDER] = { "e1oip:rx:pkt_out_of_order", "Packets out-of-order in IP->E1 direction"},
[LINE_CTR_E1oIP_RX_OUT_OF_WIN] = { "e1oip:rx:pkt_out_of_win", "Packets out-of-rx-window in IP->E1 direction"},
diff --git a/src/octoi/e1oip.h b/src/octoi/e1oip.h
index 1a184d2..c0d3ed3 100644
--- a/src/octoi/e1oip.h
+++ b/src/octoi/e1oip.h
@@ -15,6 +15,7 @@
enum e1oip_line_ctr {
LINE_CTR_E1oIP_UNDERRUN,
+ LINE_CTR_E1oIP_SUBSTITUTED,
LINE_CTR_E1oIP_OVERFLOW,
LINE_CTR_E1oIP_RX_OUT_OF_ORDER,
LINE_CTR_E1oIP_RX_OUT_OF_WIN,
diff --git a/src/octoi/frame_rifo.c b/src/octoi/frame_rifo.c
index 94758e9..effe78d 100644
--- a/src/octoi/frame_rifo.c
+++ b/src/octoi/frame_rifo.c
@@ -131,13 +131,22 @@
/*! pull one frames out of the RIFO.
* \param rifo The RIFO from which we want to pull frames
* \param out Caller-allocated output buffer
- * \returns 0 on success; -1 on error (no frame available) */
+ * \returns 0 on success; -1 if no frame available; -2 if RIFO depth == 0 */
int frame_rifo_out(struct frame_rifo *rifo, uint8_t *out)
{
uint32_t next_out_bucket = (rifo->next_out - rifo->buf) / BYTES_PER_FRAME;
bool bucket_bit = bucket_bit_get(rifo, next_out_bucket);
int rc = 0;
+ if (frame_rifo_depth(rifo) == 0) {
+ /* if we don't have any RIFO depth at all, our jitter buffer has
+ * run empty and most likely there is some fundamental clock sync problem
+ * somewhere. In order to prevent perpetual substitution of frames from
+ * now onwards, we slip/insert one frame here by _not_ advancing next_out
+ * or next_out_fn and telling the caller to insert a frame */
+ return -2;
+ }
+
if (!bucket_bit) {
/* caller is supposed to copy/duplicate previous frame */
rc = -1;
diff --git a/src/octoi/octoi.c b/src/octoi/octoi.c
index 8585f0d..5f4c2f9 100644
--- a/src/octoi/octoi.c
+++ b/src/octoi/octoi.c
@@ -127,10 +127,14 @@
for (int i = 0; i < fts; i++) {
uint8_t *cur = buf + BYTES_PER_FRAME*i;
rc = frame_rifo_out(&iline->e1t.rifo, cur);
- if (rc < 0) {
- iline_ctr_add(iline, LINE_CTR_E1oIP_UNDERRUN, 1);
+ if (rc == -1) {
+ iline_ctr_add(iline, LINE_CTR_E1oIP_SUBSTITUTED, 1);
/* substitute with last received frame */
memcpy(cur, iline->e1t.last_frame, BYTES_PER_FRAME);
+ } else if (rc == -2) {
+ iline_ctr_add(iline, LINE_CTR_E1oIP_UNDERRUN, 1);
+ /* substitute with all-FF frame */
+ memset(cur, 0xff, BYTES_PER_FRAME);
}
}
iline_stat_set(iline, LINE_STAT_E1oIP_E1T_FIFO, frame_rifo_depth(&iline->e1t.rifo));
To view, visit change 27837. To unsubscribe, or for help writing mail filters, visit settings.