/* Cesar project {{{ * * Copyright (C) 2007 Spidcom * * <<>> * * }}} */ /** * \file mac/common/src/mfs.c * \brief MAC frame stream functions. * \ingroup mac_common */ #include "common/std.h" #include "mac/common/mfs.h" #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 /** RX MFS DATA window size (fixed). */ #define MFS_WINDOW_SIZE_DATA_RX MFS_WINDOW_SIZE_256 /** 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) { mfs_common->tx = tx; mfs_common->bcast = bcast; mfs_common->mme = mme; mfs_common->ats = false; mfs_common->lid = lid; mfs_common->tei = tei; mfs_common->lid_alias = MAC_LID_NONE; mfs_common->unassociated = false; list_init_node (&mfs_common->store_unassociated_link); /* mfs_common->expiration_ntb */ if (tx) mfs_common->expiration_delay_tck = MAC_MS_TO_TCK (MFS_PB_TX_DELAY_MS); else mfs_common->expiration_delay_tck = MAC_MS_TO_TCK (MFS_PB_RX_DELAY_MS); } void mfs_rx_init (mfs_rx_t *mfs, bool bcast, bool mme, uint lid, uint tei) { dbg_assert_ptr (mfs); dbg_assert ((mme && lid == MAC_LID_NONE) || (!mme && MAC_LID_IS_XLID (lid))); dbg_assert (tei != MAC_TEI_BCAST); mfs_common_init (&mfs->common, false, bcast, mme, lid, tei); mfs->head = NULL; mfs->ssn_min = 0; mfs->window_size_encoded = mme ? MFS_WINDOW_SIZE_MME : MFS_WINDOW_SIZE_DATA_RX; mfs->window_size = mfs_window_size[mfs->window_size_encoded]; mfs->release = false; link_stats_rx_reset (&mfs->stats); } void mfs_rx_init_unassociated (mfs_rx_t *mfs, bool bcast, bool mme, uint lid, uint tei) { mfs_rx_init (mfs, bcast, mme, lid, tei); mfs->common.unassociated = true; } void mfs_tx_init (mfs_tx_t *mfs, bool bcast, bool mme, uint lid, uint tei) { dbg_assert_ptr (mfs); dbg_assert ((mme && lid == MAC_LID_NONE) || (!mme && (MAC_LID_IS_XLID (lid) || MAC_LID_IS_BEACON (lid)))); dbg_assert ((bcast && tei == MAC_TEI_BCAST) || (!bcast && MAC_TEI_IS_STA (tei)) || (!bcast && mme && tei == MAC_TEI_UNASSOCIATED)); mfs_common_init (&mfs->common, true, bcast, mme, lid, tei); mfs->cfp = false; mfs->burst_count = 0; list_init_node (&mfs->ca_link); mfs->ca_state = CA_MFS_STATE_UNKNOWN; mfs->seg_nb = 0; mfs->pending_seg_nb = 0; mfs->fsm_state = bcast ? MFS_FSM_CMD_NOP : MFS_FSM_CMD_INIT; mfs->window_size = mme ? mfs_window_size[MFS_WINDOW_SIZE_MME] : mfs_window_size[MFS_DEFAULT_WINDOW_SIZE_DATA_TX]; mfs->holes_seg_nb = 0; mfs->delta_between_ssn_min = 0; if (mme) mfs->cap = 2; else mfs->cap = MAC_LID_IS_PLID (lid) ? lid : 0; mfs->head = NULL; dbg_invalid_ptr (mfs->tail); mfs->last_seg_offset = 0; mfs->next_ssn = 0; mfs->beacon = false; link_stats_tx_reset (&mfs->stats); } void mfs_tx_init_unassociated (mfs_tx_t *mfs, bool bcast, bool mme, uint lid, uint tei) { dbg_assert (mfs); mfs_tx_init (mfs, bcast, mme, lid, tei); mfs->common.unassociated = true; 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; }