summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cesar/lib/blk.h10
-rw-r--r--cesar/lib/src/blk.c7
-rw-r--r--cesar/lib/test/blk/src/test_blk.c4
-rw-r--r--cesar/mac/common/mfs.h10
-rw-r--r--cesar/mac/common/src/mfs.c34
-rw-r--r--cesar/mac/common/src/store.c87
-rw-r--r--cesar/mac/common/store.h31
-rw-r--r--cesar/mac/common/test/mfs/src/test_mfs.c43
-rw-r--r--cesar/mac/common/test/store/src/test_store.c17
-rw-r--r--cesar/mac/pbproc/pbproc.h4
-rw-r--r--cesar/mac/pbproc/src/fsm_handle_fc.c2
-rw-r--r--cesar/mac/pbproc/src/fsm_rx_sound.c2
-rw-r--r--cesar/mac/pbproc/test/mfs/src/test_mfs.c14
-rw-r--r--cesar/mac/sar/src/expiration.c36
-rw-r--r--cesar/mac/sar/src/tx.c4
-rw-r--r--cesar/mac/sar/test/utest/host/src/expiration.c35
-rw-r--r--cesar/mac/sar/test/utest/host/src/segmentation.c43
-rw-r--r--cleopatre/devkit/plcdrv/inc/qos.h11
18 files changed, 370 insertions, 24 deletions
diff --git a/cesar/lib/blk.h b/cesar/lib/blk.h
index 247ea12a58..428771580f 100644
--- a/cesar/lib/blk.h
+++ b/cesar/lib/blk.h
@@ -237,6 +237,16 @@ blk_print_memory (void);
uint
blk_slack (void);
+/**
+ * Query the total number of block usable for slack protected allocation.
+ * \return total number of block, minus the slack.
+ *
+ * Note: this is not precise as regular allocation is also consuming the same
+ * memory.
+ */
+uint
+blk_slack_total (void);
+
END_DECLS
#endif /* lib_blk_h */
diff --git a/cesar/lib/src/blk.c b/cesar/lib/src/blk.c
index 238fcbef67..a2ac8fa543 100644
--- a/cesar/lib/src/blk.c
+++ b/cesar/lib/src/blk.c
@@ -550,3 +550,10 @@ blk_slack (void)
else
return 0;
}
+
+uint
+blk_slack_total (void)
+{
+ return blk_global.total_nb - CONFIG_BLK_SLACK;
+}
+
diff --git a/cesar/lib/test/blk/src/test_blk.c b/cesar/lib/test/blk/src/test_blk.c
index 21bd5bef6d..debbee0542 100644
--- a/cesar/lib/test/blk/src/test_blk.c
+++ b/cesar/lib/test/blk/src/test_blk.c
@@ -369,12 +369,16 @@ blk_slack_test_case (test_t t)
{
blk_t *b[CONFIG_BLK_NB - CONFIG_BLK_SLACK];
uint i;
+ test_fail_unless (blk_slack_total () == CONFIG_BLK_NB
+ - CONFIG_BLK_SLACK);
for (i = 0; i < CONFIG_BLK_NB - CONFIG_BLK_SLACK; i++)
{
test_fail_unless (blk_slack ());
b[i] = blk_alloc ();
}
test_fail_unless (!blk_slack ());
+ test_fail_unless (blk_slack_total () == CONFIG_BLK_NB
+ - CONFIG_BLK_SLACK);
blk_release (b[CONFIG_BLK_NB - CONFIG_BLK_SLACK - 1]);
test_fail_unless (blk_slack ());
diff --git a/cesar/mac/common/mfs.h b/cesar/mac/common/mfs.h
index 01d5baf913..619000a482 100644
--- a/cesar/mac/common/mfs.h
+++ b/cesar/mac/common/mfs.h
@@ -237,6 +237,9 @@ BEGIN_DECLS
* it is included). */
extern const u16 mfs_window_size[MFS_WINDOW_SIZE_NB];
+/** Global TX MFS number of segment limit. */
+extern int mfs_tx_max_seg_nb;
+
/**
* Initialise a RX MFS, called from MAC store.
* \param mfs MFS to initialise
@@ -294,6 +297,13 @@ mfs_tx_init (mfs_tx_t *mfs, bool bcast, bool mme, uint lid, uint tei);
void
mfs_tx_init_unassociated (mfs_tx_t *mfs, bool bcast, bool mme, uint lid, uint tei);
+/**
+ * Update the MFS TX segment limit.
+ * \param active_nb number of active MFS
+ */
+void
+mfs_tx_max_seg_nb_update (int active_nb);
+
END_DECLS
#endif /* mac_common_mfs_h */
diff --git a/cesar/mac/common/src/mfs.c b/cesar/mac/common/src/mfs.c
index af269717cd..2d500507eb 100644
--- a/cesar/mac/common/src/mfs.c
+++ b/cesar/mac/common/src/mfs.c
@@ -16,6 +16,11 @@
#include "mac/common/defs.h"
#include "mac/common/timings.h"
+#include "common/module.h"
+#if MODULE_INCLUDED (mac_sar)
+#include "config/sar/pbpool/size.h"
+#endif
+
/** MFS MME window size (fixed). */
#define MFS_WINDOW_SIZE_MME MFS_WINDOW_SIZE_8
@@ -25,11 +30,20 @@
/** Default TX MFS DATA window size (actual value is fixed by the receiver). */
#define MFS_DEFAULT_WINDOW_SIZE_DATA_TX MFS_WINDOW_SIZE_16
+/** Default TX MFS segment limit. */
+#define MFS_TX_MAX_SEG_NB_DEFAULT 1200
+
+/** Minimum TX MFS segment limit. */
+#define MFS_TX_MAX_SEG_NB_MIN 42
+
/** Window size values table (values of the RxWSz field of the FCs in which
* it is included). */
const u16 mfs_window_size[MFS_WINDOW_SIZE_NB] = { 4, 8, 16, 24, 32, 48, 64, 80,
96, 112, 128, 144, 160, 192, 224, 256 };
+/** Global TX MFS number of segment limit. */
+int mfs_tx_max_seg_nb = MFS_TX_MAX_SEG_NB_DEFAULT;
+
static void
mfs_common_init (mfs_common_t *mfs_common, bool tx, bool bcast, bool mme, uint
lid, uint tei)
@@ -121,3 +135,23 @@ mfs_tx_init_unassociated (mfs_tx_t *mfs, bool bcast, bool mme, uint lid,
mfs->fsm_state = MFS_FSM_CMD_NOP;
}
+void
+mfs_tx_max_seg_nb_update (int active_nb)
+{
+ /* Try to have a good estimate of available memory. */
+ uint blk_nb = blk_slack_total ();
+#ifdef CONFIG_SAR_PBPOOL_SIZE
+ blk_nb -= CONFIG_SAR_PBPOOL_SIZE;
+#endif
+ /* Empiric margin. */
+ blk_nb = blk_nb * 15 / 16;
+ /* Now share all this memory between active MFS. */
+ int new_limit = blk_nb / (active_nb + 1);
+ if (new_limit > MFS_TX_MAX_SEG_NB_DEFAULT)
+ mfs_tx_max_seg_nb = MFS_TX_MAX_SEG_NB_DEFAULT;
+ else if (new_limit < MFS_TX_MAX_SEG_NB_MIN)
+ mfs_tx_max_seg_nb = MFS_TX_MAX_SEG_NB_MIN;
+ else
+ mfs_tx_max_seg_nb = new_limit;
+}
+
diff --git a/cesar/mac/common/src/store.c b/cesar/mac/common/src/store.c
index 3675434634..2c1a0a6ad4 100644
--- a/cesar/mac/common/src/store.c
+++ b/cesar/mac/common/src/store.c
@@ -500,6 +500,93 @@ mac_store_mfs_travel_by_tei (mac_store_t *ctx, uint tei,
}
}
+void
+mac_store_mfs_travel_locked (mac_store_t *ctx, mac_store_travel_t travel,
+ void *user)
+{
+ uint i;
+ dbg_assert (ctx);
+ dbg_assert (travel);
+ /* First travel local MFS. */
+ for (i = 0; i < MAC_PLID_NB; i++)
+ {
+ if (ctx->bcast_tx_plid[i])
+ travel (ctx, ctx->bcast_tx_plid[i], user);
+ }
+ if (ctx->bcast_tx_mme)
+ {
+ if (ctx->bcast_tx_mme)
+ travel (ctx, ctx->bcast_tx_mme, user);
+ }
+ for (i = MAC_LLID_MIN; i <= ctx->tx_llid_max; i++)
+ {
+ if (ctx->lglid[i])
+ travel (ctx, ctx->lglid[i], user);
+ }
+ for (i = MAC_GLID_MIN; i <= ctx->glid_max; i++)
+ {
+ if (ctx->lglid[i])
+ travel (ctx, ctx->lglid[i], user);
+ }
+ /* Then unassociated MFS. */
+ list_node_t *u, *uend, *unext;
+ uend = list_end (&ctx->unassociated);
+ for (u = list_begin (&ctx->unassociated); u != uend; u = unext)
+ {
+ unext = list_next (u);
+ travel (ctx, PARENT_OF (mfs_t, common.store_unassociated_link, u),
+ user);
+ }
+ /* Do not forget beacon MFS. */
+ if (ctx->lglid[MAC_LID_DISCOVER])
+ travel (ctx, ctx->lglid[MAC_LID_DISCOVER], user);
+ if (ctx->lglid[MAC_LID_SPC_CENTRAL])
+ travel (ctx, ctx->lglid[MAC_LID_SPC_CENTRAL], user);
+ /* Now travel by TEI. */
+ for (i = MAC_TEI_STA_MIN; i <= MAC_TEI_STA_MAX; i++)
+ if (ctx->sta[i])
+ mac_store_mfs_travel_by_tei_locked (ctx, i, travel, user);
+}
+
+void
+mac_store_mfs_travel_by_tei_locked (mac_store_t *ctx, uint tei,
+ mac_store_travel_t travel, void *user)
+{
+ uint i, j;
+ mac_store_sta_t *sta;
+ dbg_assert (ctx);
+ dbg_assert (MAC_TEI_IS_STA (tei));
+ dbg_assert (travel);
+ sta = ctx->sta[tei];
+ if (sta)
+ {
+ /* Travel MFS. */
+ for (i = 0; i < MAC_STORE_KIND_STA_NB; i++)
+ {
+ for (j = 0; j < MAC_PLID_NB; j++)
+ {
+ if (sta->plid[i][j])
+ travel (ctx, sta->plid[i][j], user);
+ }
+ if (sta->mme[i])
+ travel (ctx, sta->mme[i], user);
+ }
+ if (sta->rx_llid)
+ {
+ mfs_t **rx_llid;
+ rx_llid = sta->rx_llid;
+ if (rx_llid)
+ {
+ for (i = MAC_LLID_MIN; i <= sta->rx_llid_max; i++)
+ {
+ if (rx_llid[i])
+ travel (ctx, rx_llid[i], user);
+ }
+ }
+ }
+ }
+}
+
sta_t *
mac_store_sta_get_ (mac_store_t *ctx, uint tei __FL)
{
diff --git a/cesar/mac/common/store.h b/cesar/mac/common/store.h
index 446795d544..f9debc70cc 100644
--- a/cesar/mac/common/store.h
+++ b/cesar/mac/common/store.h
@@ -269,6 +269,37 @@ mac_store_mfs_travel_by_tei (mac_store_t *ctx, uint tei,
mac_store_travel_t travel, void *user);
/**
+ * Call the provided callback for all MFS, with DSR locked.
+ * \param ctx store context
+ * \param travel callback function
+ * \param user user data
+ * \context DSR
+ *
+ * \see mac_store_mfs_travel.
+ *
+ * DSR should be locked to call this function.
+ */
+void
+mac_store_mfs_travel_locked (mac_store_t *ctx, mac_store_travel_t travel,
+ void *user);
+
+/**
+ * Call the provided callback for all MFS connected to a STA, with DSR locked.
+ * \param ctx store context
+ * \param tei terminal equipment id of the STA
+ * \param travel callback function
+ * \param user user data
+ * \context DSR
+ *
+ * \see mac_store_mfs_travel_by_tei.
+ *
+ * DSR should be locked to call this function.
+ */
+void
+mac_store_mfs_travel_by_tei_locked (mac_store_t *ctx, uint tei,
+ mac_store_travel_t travel, void *user);
+
+/**
* Get a STA information structure pointer.
* \param ctx store context
* \param tei peer terminal equipment id
diff --git a/cesar/mac/common/test/mfs/src/test_mfs.c b/cesar/mac/common/test/mfs/src/test_mfs.c
index e6c2f20f54..60fc70dfd8 100644
--- a/cesar/mac/common/test/mfs/src/test_mfs.c
+++ b/cesar/mac/common/test/mfs/src/test_mfs.c
@@ -42,10 +42,53 @@ mfs_window_size_test_case (test_t t)
}
void
+mfs_tx_max_seg_nb_test_case (test_t t)
+{
+ /* Make an allocation to initialise the allocator. */
+ blk_release (blk_alloc ());
+ /* Now test. The test uses plain numbers as it do not have access to the
+ * macros defined in the code. This must be modified if macros are
+ * changed. Values also depend on blk configuration. */
+ test_case_begin (t, "mfs_tx_max_seg_nb");
+ test_begin (t, "default")
+ {
+ test_fail_unless (mfs_tx_max_seg_nb < 2000 && mfs_tx_max_seg_nb > 10);
+ } test_end;
+ int def = mfs_tx_max_seg_nb;
+ test_begin (t, "update low")
+ {
+ mfs_tx_max_seg_nb_update (0);
+ test_fail_unless (mfs_tx_max_seg_nb == def);
+ mfs_tx_max_seg_nb_update (1);
+ test_fail_unless (mfs_tx_max_seg_nb == def);
+ mfs_tx_max_seg_nb_update (2);
+ test_fail_unless (mfs_tx_max_seg_nb == def);
+ } test_end;
+ test_begin (t, "update high")
+ {
+ mfs_tx_max_seg_nb_update (1000);
+ test_fail_unless (mfs_tx_max_seg_nb > 10
+ && mfs_tx_max_seg_nb < def / 10);
+ } test_end;
+ test_begin (t, "update middle")
+ {
+ uint i;
+ int last = def;
+ for (i = 10; i < 20; i++)
+ {
+ mfs_tx_max_seg_nb_update (i);
+ test_fail_unless (mfs_tx_max_seg_nb < last);
+ last = mfs_tx_max_seg_nb;
+ }
+ } test_end;
+}
+
+void
mfs_test_suite (test_t t)
{
test_suite_begin (t, "mfs");
mfs_window_size_test_case (t);
+ mfs_tx_max_seg_nb_test_case (t);
}
int
diff --git a/cesar/mac/common/test/store/src/test_store.c b/cesar/mac/common/test/store/src/test_store.c
index e375710a39..ea1129f285 100644
--- a/cesar/mac/common/test/store/src/test_store.c
+++ b/cesar/mac/common/test/store/src/test_store.c
@@ -346,6 +346,9 @@ store_basic_test_case (test_t t)
} test_end;
test_begin (t, "travel")
{
+ ctx->travel_mfs_nb = 0;
+ ctx->travel_mfs_alias_nb = 0;
+ ctx->travel_mfs_unassoc_nb = 0;
mac_store_mfs_travel (ctx->store, travel_mfs, ctx);
uint mfs_alias = ctx->travel_mfs_alias_nb / 2;
test_fail_unless (ctx->travel_mfs_alias_nb % 2 == 0
@@ -355,6 +358,20 @@ store_basic_test_case (test_t t)
ctx->travel_mfs_nb - mfs_alias, mfs_alias,
ctx->travel_mfs_unassoc_nb);
} test_end;
+ test_begin (t, "travel locked")
+ {
+ ctx->travel_mfs_nb = 0;
+ ctx->travel_mfs_alias_nb = 0;
+ ctx->travel_mfs_unassoc_nb = 0;
+ mac_store_mfs_travel_locked (ctx->store, travel_mfs, ctx);
+ uint mfs_alias = ctx->travel_mfs_alias_nb / 2;
+ test_fail_unless (ctx->travel_mfs_alias_nb % 2 == 0
+ && (ctx->travel_mfs_nb - mfs_alias
+ == ctx->used_mfs_nb));
+ test_verbose_print ("mfs = %d, alias = %d, unassoc = %d",
+ ctx->travel_mfs_nb - mfs_alias, mfs_alias,
+ ctx->travel_mfs_unassoc_nb);
+ } test_end;
/* Clean up. */
test_begin (t, "cleanup")
{
diff --git a/cesar/mac/pbproc/pbproc.h b/cesar/mac/pbproc/pbproc.h
index 813108f99d..f001d4c0b0 100644
--- a/cesar/mac/pbproc/pbproc.h
+++ b/cesar/mac/pbproc/pbproc.h
@@ -54,8 +54,8 @@ struct pbproc_rx_params_t
bool sound;
/** Network encryption key select. */
u8 eks;
- /** Pending PB. */
- u8 pending_seg_nb;
+ /** Pending PB information. */
+ u8 pending_seg_info;
/** Bit loading estimate. */
u8 ble;
/** PB size (PHY_PB_SIZE_136 or PHY_PB_SIZE_520). */
diff --git a/cesar/mac/pbproc/src/fsm_handle_fc.c b/cesar/mac/pbproc/src/fsm_handle_fc.c
index a72d2479a6..f31346bfa5 100644
--- a/cesar/mac/pbproc/src/fsm_handle_fc.c
+++ b/cesar/mac/pbproc/src/fsm_handle_fc.c
@@ -184,7 +184,7 @@ pbproc_fhfc_parse_sof (pbproc_t *ctx, const pbproc_fc_t *fc_av)
rx_params->hp10df = BF_GET (PBPROC_FC_SOF_W1__HP10DF, sof_w1);
rx_params->hp11df = BF_GET (PBPROC_FC_SOF_W1__HP11DF, sof_w1);
rx_params->eks = BF_GET (PBPROC_FC_SOF_W1__EKS, sof_w1);
- rx_params->pending_seg_nb = BF_GET (PBPROC_FC_SOF_W1__PPB, sof_w1);
+ rx_params->pending_seg_info = BF_GET (PBPROC_FC_SOF_W1__PPB, sof_w1);
rx_params->ble = BF_GET (PBPROC_FC_SOF_W1__BLE, sof_w1);
rx_params->pb_size = BF_GET (PBPROC_FC_SOF_W1__PBSZ, sof_w1)
? PHY_PB_SIZE_136 : PHY_PB_SIZE_520;
diff --git a/cesar/mac/pbproc/src/fsm_rx_sound.c b/cesar/mac/pbproc/src/fsm_rx_sound.c
index 20448fbb3a..a24cdbd91c 100644
--- a/cesar/mac/pbproc/src/fsm_rx_sound.c
+++ b/cesar/mac/pbproc/src/fsm_rx_sound.c
@@ -118,7 +118,7 @@ pbproc_frso__handle (pbproc_t *ctx, u32 rx_date,
ctx->recv_mpdu.rx_params.multi_net_bcast = false;
ctx->recv_mpdu.rx_params.sound = true;
ctx->recv_mpdu.rx_params.eks = MAC_EKS_CLEAR;
- ctx->recv_mpdu.rx_params.pending_seg_nb = sound->ppb;
+ ctx->recv_mpdu.rx_params.pending_seg_info = sound->ppb;
ctx->recv_mpdu.rx_params.ble = 0;
ctx->recv_mpdu.rx_params.pb_size = pb_size;
ctx->recv_mpdu.rx_params.tmi_av = mod;
diff --git a/cesar/mac/pbproc/test/mfs/src/test_mfs.c b/cesar/mac/pbproc/test/mfs/src/test_mfs.c
index ea62602caf..8998d7f267 100644
--- a/cesar/mac/pbproc/test/mfs/src/test_mfs.c
+++ b/cesar/mac/pbproc/test/mfs/src/test_mfs.c
@@ -436,7 +436,7 @@ mfs_expire_test_case (test_t t)
mfs->next_ssn += 10;
mfs->holes_seg_nb += 10;
mfs_add_segments (mfs, 10, 0);
- /* Run expiration, remote everything! */
+ /* Run expiration, remove everything! */
empty = pbproc_mfs_expire (&pbproc, mfs, (u32) 1664, &expired_nb);
test_fail_unless (empty);
test_fail_unless (expired_nb == 20);
@@ -461,11 +461,11 @@ mfs_expire_test_case (test_t t)
mfs->next_ssn = 0;
mfs->fsm_state = MFS_FSM_CMD_IN_SYNC;
mfs_add_segments (mfs, 32, 0);
- /* Run expiration, do not remove all segment in window. */
+ /* Run expiration, do not remove all segments in window. */
empty = pbproc_mfs_expire (&pbproc, mfs, (u32) 4, &expired_nb);
test_fail_unless (expired_nb == 10);
test_fail_unless (mfs->fsm_state == MFS_FSM_CMD_IN_SYNC);
- /* Run expiration, do remove all segment in window. */
+ /* Run expiration, do remove all segments in window. */
empty = pbproc_mfs_expire (&pbproc, mfs, (u32) 42, &expired_nb);
test_fail_unless (expired_nb == 22);
test_fail_unless (mfs->fsm_state == MFS_FSM_CMD_RE_SYNC);
@@ -488,7 +488,7 @@ mfs_expire_test_case (test_t t)
mfs->next_ssn += 10;
mfs->holes_seg_nb += 10;
mfs_add_segments (mfs, 10, 0);
- /* Run expiration, do not remove all segment in window. */
+ /* Run expiration, do not remove all segments in window. */
empty = pbproc_mfs_expire (&pbproc, mfs, (u32) 4, &expired_nb);
test_fail_unless (expired_nb == 10);
test_fail_unless (mfs->fsm_state == MFS_FSM_CMD_IN_SYNC);
@@ -496,7 +496,7 @@ mfs_expire_test_case (test_t t)
mfs->next_ssn += 10;
mfs->holes_seg_nb += 10;
mfs_add_segments (mfs, 10, 0);
- /* Run expiration, do remove all segment in window. */
+ /* Run expiration, do remove all segments in window. */
empty = pbproc_mfs_expire (&pbproc, mfs, (u32) 1664, &expired_nb);
test_fail_unless (expired_nb == 20);
test_fail_unless (mfs->fsm_state == MFS_FSM_CMD_RE_SYNC);
@@ -516,11 +516,11 @@ mfs_expire_test_case (test_t t)
mfs->next_ssn = 0;
mfs->fsm_state = MFS_FSM_CMD_INIT;
mfs_add_segments (mfs, 32, 0);
- /* Run expiration, do not remove all segment in window. */
+ /* Run expiration, do not remove all segments in window. */
empty = pbproc_mfs_expire (&pbproc, mfs, (u32) 4, &expired_nb);
test_fail_unless (expired_nb == 10);
test_fail_unless (mfs->fsm_state == MFS_FSM_CMD_INIT);
- /* Run expiration, do remove all segment in window. */
+ /* Run expiration, do remove all segments in window. */
empty = pbproc_mfs_expire (&pbproc, mfs, (u32) 42, &expired_nb);
test_fail_unless (expired_nb == 22);
test_fail_unless (mfs->fsm_state == MFS_FSM_CMD_INIT);
diff --git a/cesar/mac/sar/src/expiration.c b/cesar/mac/sar/src/expiration.c
index abe5f5c2bb..c01a66f629 100644
--- a/cesar/mac/sar/src/expiration.c
+++ b/cesar/mac/sar/src/expiration.c
@@ -159,20 +159,39 @@ sar_expiration_mfs_rx (sar_t *ctx, mfs_rx_t *mfs)
sar_expiration_mfs_purge_rx (ctx, mfs, now);
}
+/** Context used for expiration MFS travel. */
+struct sar_expiration_mfs_t
+{
+ /** SAR context. */
+ sar_t *sar;
+ /** Number of active MFS. */
+ int active;
+};
+typedef struct sar_expiration_mfs_t sar_expiration_mfs_t;
+
/**
* Clean a MFS.
* \param mac_store the mac store.
* \param mfs the MFS concerned.
- * \param ctx the callback context.
+ * \param user the callback context.
*/
static void
-sar_expiration_mfs_found (mac_store_t *mac_store, mfs_t *mfs, void *ctx)
+sar_expiration_mfs_found (mac_store_t *mac_store, mfs_t *mfs, void *user)
{
+ sar_expiration_mfs_t *cbctx = user;
arch_dsr_lock ();
if (mfs->common.tx)
- sar_expiration_mfs_tx (ctx, &mfs->tx);
+ {
+ sar_expiration_mfs_tx (cbctx->sar, &mfs->tx);
+ if (mfs->tx.head && !mfs->tx.beacon)
+ cbctx->active++;
+ }
else
- sar_expiration_mfs_rx (ctx, &mfs->rx);
+ {
+ sar_expiration_mfs_rx (cbctx->sar, &mfs->rx);
+ if (mfs->rx.head)
+ cbctx->active++;
+ }
arch_dsr_unlock ();
}
@@ -180,7 +199,10 @@ void
sar_expiration_mfs (sar_t *ctx)
{
dbg_assert (ctx);
- mac_store_mfs_travel (ctx->mac_store,
- sar_expiration_mfs_found,
- ctx);
+ sar_expiration_mfs_t sar_expiration_mfs_ctx;
+ sar_expiration_mfs_ctx.sar = ctx;
+ sar_expiration_mfs_ctx.active = 0;
+ mac_store_mfs_travel (ctx->mac_store, sar_expiration_mfs_found,
+ &sar_expiration_mfs_ctx);
+ mfs_tx_max_seg_nb_update (sar_expiration_mfs_ctx.active);
}
diff --git a/cesar/mac/sar/src/tx.c b/cesar/mac/sar/src/tx.c
index 102022ecc3..00bb681552 100644
--- a/cesar/mac/sar/src/tx.c
+++ b/cesar/mac/sar/src/tx.c
@@ -317,8 +317,10 @@ sar_msdu_process (sar_t *ctx, u8 *buffer, u16 length, mfs_tx_t *mfs,
/* Check sequence. */
lib_seq_check_packet (&ctx->seq, buffer, length);
- /* Enough block available to send a frame and SAR is activated ? */
+ /* Enough block available to send a frame, enough room in MFS, and SAR is
+ * activated? */
if (ctx->activate
+ && mfs->seg_nb < mfs_tx_max_seg_nb
&& (blk_slack () || mfs->seg_nb <= MAC_SAR_EM_MAX_PB_ALLOWED))
{
if (mfs->fsm_state == MFS_FSM_CMD_RELEASE)
diff --git a/cesar/mac/sar/test/utest/host/src/expiration.c b/cesar/mac/sar/test/utest/host/src/expiration.c
index 7fd452e5e9..8711ddcf68 100644
--- a/cesar/mac/sar/test/utest/host/src/expiration.c
+++ b/cesar/mac/sar/test/utest/host/src/expiration.c
@@ -112,6 +112,41 @@ test_case_expiration (test_t test)
}
test_end;
sar_cleanup (t.sar);
+ /* Here constants in MFS limiting are unknown to this testing code.
+ * Behaviour will depend on MFS limit constants, code, and current blk
+ * allocator configuration. The test tries to mimic a typical behaviour
+ * but it might have to be changed if context is changed. */
+ test_begin (test, "MFS TX max seg nb update")
+ {
+ int limit, initial;
+ uint i;
+ mfs_tx_max_seg_nb_update (0);
+ initial = limit = mfs_tx_max_seg_nb;
+ phy_date = 0;
+ /* Expiration without MFS, limit should not change. */
+ sar_expiration_mfs (t.sar);
+ test_fail_unless (mfs_tx_max_seg_nb == initial);
+ /* Expiration with TX MFS, limit should be lower. */
+ for (i = 1; i <= COUNT (expiration_ntb); i++)
+ test_case_expiration__add (&t, i, 1, true, expiration_ntb[i - 1]);
+ sar_expiration_mfs (t.sar);
+ test_fail_unless (mfs_tx_max_seg_nb < limit);
+ limit = mfs_tx_max_seg_nb;
+ /* Expiration with RX MFS, limit should be even lower. */
+ for (i = 1; i <= COUNT (expiration_ntb); i++)
+ test_case_expiration__add (&t, i, 1, false, expiration_ntb[i - 1]);
+ sar_expiration_mfs (t.sar);
+ test_fail_unless (mfs_tx_max_seg_nb < limit);
+ /* Expire segments, empty MFS are not counted. */
+ phy_date = expiration_ntb[COUNT (expiration_ntb) - 1] + 10;
+ sar_expiration_mfs (t.sar);
+ test_fail_unless (mfs_tx_max_seg_nb == initial);
+ /* OK, cleanup, limit should return to initial value after
+ * expiration. */
+ sar_cleanup (t.sar);
+ sar_expiration_mfs (t.sar);
+ test_fail_unless (mfs_tx_max_seg_nb == initial);
+ } test_end;
sar_test_uninit (&t);
}
diff --git a/cesar/mac/sar/test/utest/host/src/segmentation.c b/cesar/mac/sar/test/utest/host/src/segmentation.c
index dfd0947f09..72f2b223c9 100644
--- a/cesar/mac/sar/test/utest/host/src/segmentation.c
+++ b/cesar/mac/sar/test/utest/host/src/segmentation.c
@@ -312,6 +312,48 @@ test_case_segmentation_em_max_pb_allowed (test_t test)
}
void
+test_case_segmentation_mfs_tx_max_seg_nb_test (test_t test, sar_test_t ctx,
+ mfs_tx_t *mfs)
+{
+ u8 *buffer = NULL;
+ test_within (test);
+ buffer = bufmgr_get (ctx.sar->bufmgr);
+ sar_msdu_process (ctx.sar, buffer, ETH_PACKET_MIN_SIZE_ALLOWED, mfs,
+ 0x0);
+ sar_bridge_dma_free_head (ctx.sar);
+ test_fail_unless (mfs->seg_nb == mfs_tx_max_seg_nb);
+ bufmgr_give_back (ctx.sar->bufmgr, buffer);
+}
+
+void
+test_case_segmentation_mfs_tx_max_seg_nb (test_t test)
+{
+ sar_test_t ctx;
+ bool added;
+ test_case_begin (test, "Test mfs_tx_max_seg_nb");
+ sar_test_init (&ctx, INVALID_PTR, INVALID_PTR);
+ mfs_tx_t *mfs = mac_store_mfs_add_tx (ctx.mac_store, false, false, 1,
+ 1, &added);
+ sar_activate (ctx.sar, true);
+ test_begin (test, "less than limit")
+ {
+ mfs->seg_nb = mfs_tx_max_seg_nb - 1;
+ test_case_segmentation_mfs_tx_max_seg_nb_test (test, ctx, mfs);
+ }
+ test_end;
+ test_begin (test, "more than limit")
+ {
+ mfs->seg_nb = mfs_tx_max_seg_nb;
+ test_case_segmentation_mfs_tx_max_seg_nb_test (test, ctx, mfs);
+ }
+ test_end;
+ sar_mfs_remove (ctx.sar, PARENT_OF (mfs_t, tx, mfs));
+ blk_release (mfs);
+ sar_sta_remove (ctx.sar, 1);
+ sar_test_uninit (&ctx);
+}
+
+void
test_suite_segmentation (test_t test)
{
test_suite_begin (test, "Segmentation");
@@ -320,6 +362,7 @@ test_suite_segmentation (test_t test)
test_case_segmentation (test);
test_case_segmentation_mfs_release (test);
test_case_segmentation_em_max_pb_allowed (test);
+ test_case_segmentation_mfs_tx_max_seg_nb (test);
test_begin (test, "Memory")
{
diff --git a/cleopatre/devkit/plcdrv/inc/qos.h b/cleopatre/devkit/plcdrv/inc/qos.h
index b896aa7fbd..96f57808a4 100644
--- a/cleopatre/devkit/plcdrv/inc/qos.h
+++ b/cleopatre/devkit/plcdrv/inc/qos.h
@@ -67,21 +67,22 @@ typedef struct
static inline unsigned int
qos_frame_prio_get (qos_t *qos, struct sk_buff *skb)
{
+ /* If MME, raise priority. */
+ const struct ethhdr *eth = (const struct ethhdr *) skb->data;
+ if (eth->h_proto == htons (ETH_P_HPAV))
+ return QOS_FRAME_PRIO_MME;
+ /* Else, look at service type. */
switch (qos->service_type)
{
case QOS_SERVICE_TYPE_NONE:
{
- /* Default service type, use frame VLAN prio and raise MME
- * priority. */
- const struct ethhdr *eth = (const struct ethhdr *) skb->data;
+ /* Default service type, use frame VLAN prio. */
if (eth->h_proto == htons (ETH_P_8021Q))
{
const struct vlan_ethhdr *veth
= (const struct vlan_ethhdr *) eth;
return VLAN_PRIO (ntohs (veth->h_vlan_TCI));
}
- else if (eth->h_proto == htons (ETH_P_HPAV))
- return QOS_FRAME_PRIO_MME;
return QOS_FRAME_PRIO_DEFAULT;
}
case QOS_SERVICE_TYPE_VID: