summaryrefslogtreecommitdiff
path: root/cesar/mac/sar/src/expiration.c
blob: abe5f5c2bbd496f98bb0881b8d905dad8a534a72 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/* Cesar project {{{
 *
 * Copyright (C) 2007 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    mac/sar/src/sar_expiration.c
 * \brief   the function for the sar expiration process.
 * \ingroup mac_sar
 *
 */
#include "common/std.h"
#include "mac/common/timings.h"
#include "mac/common/ntb.h"
#include "mac/common/mfs.h"

#include "mac/sar/inc/context.h"
#include "mac/sar/inc/expiration.h"
#include "mac/sar/inc/sar.h"
#include "mac/sar/inc/trace.h"

/**
 * Verify if the MFS had expired.
 * \param  mfs  the mfs to check.
 * \param  ntb  the current ntb date.
 * \return  true is expired, false otherwise.
 */
#define sar_expiration_mfs_expired(mfs, ntb) \
    lesseq_mod2p32 (mfs->common.expiration_ntb, ntb)

/**
 * Verify if the MFS head PB had expired.
 * \param  mfs  the mfs to check.
 * \param  ntb  the current ntb date.
 * \return  true is expired, false otherwise.
 */
#define sar_expiration_mfs_head_expired(mfs, ntb) \
    lesseq_mod2p32 (mfs->head->expiration_ntb, ntb)

void
sar_expiration_mfs_update_ntb (sar_t *ctx, mfs_t *mfs, u32 arrival_ntb)
{
    dbg_claim (ctx);
    dbg_claim (mfs);
    if (mfs->common.tx)
        mfs->common.expiration_ntb = arrival_ntb
            + MAC_MS_TO_TCK (MFS_TX_ACTIVITY_DELAY_MS);
    else
        mfs->common.expiration_ntb = arrival_ntb
            + MAC_MS_TO_TCK (MFS_RX_ACTIVITY_DELAY_MS);
}

void
sar_expiration_mfs_purge_tx (sar_t *ctx, mfs_tx_t *mfs, u32 phy_curr_ntb)
{
    bool mfs_empty;
    u32 old_first_ssn = SAR_SSN_INVALID;
    uint expired_nb;
    dbg_assert (ctx);
    dbg_assert (mfs);
    if (CONFIG_TRACE && mfs->head)
        old_first_ssn = mfs->head->header.ssn;
    /* Call the PBprocessing to expire the PBs (only on MFS tx). */
    mfs_empty = pbproc_mfs_expire (ctx->pbproc_ctx, (mfs_tx_t *) mfs,
                                   phy_curr_ntb, &expired_nb);
    if (expired_nb)
    {
        SAR_TRACE (PB_TX_RELEASE, old_first_ssn,
                   mfs->head ? mfs->head->header.ssn : SAR_SSN_INVALID, mfs);
#if CONFIG_STATS
        if (mfs->common.mme)
            ctx->stats.mfs_tx_mme_pb_expired_nb += expired_nb;
        else
            ctx->stats.mfs_tx_data_pb_expired_nb += expired_nb;
#endif /* !CONFIG_STATS */
    }
    /* If the whole MFS has expired i.e. it does not have PB's.
     * Broadcast MFS must not expire see #2357. */
    if (mfs_empty
        && sar_expiration_mfs_expired (mfs, phy_curr_ntb)
        && !mfs->common.bcast)
    {
        sar_mfs_remove (ctx, PARENT_OF (mfs_t, tx, mfs));
        SAR_TRACE (MFS_RELEASE, phy_curr_ntb, mfs);
    }
}

void
sar_expiration_mfs_purge_rx (sar_t *ctx, mfs_rx_t *mfs, u32 ntb)
{
    bool mfs_empty = false;
    u32 expired_pb_nb = 0;
    dbg_assert (ctx);
    dbg_assert (mfs);
    /* Expire all the PBs with the cache date lesser than the actual date. */
    while (mfs->head && sar_expiration_mfs_head_expired (mfs, ntb))
    {
        SAR_TRACE (PB_RX_RELEASE, mfs->head->header.ssn, mfs);
        mfs->head = sar_pb_release (mfs->head);
        expired_pb_nb++;
    }
#if CONFIG_STATS
    if (mfs->common.mme)
        ctx->stats.mfs_rx_mme_pb_expired_nb += expired_pb_nb;
    else
        ctx->stats.mfs_rx_data_pb_expired_nb += expired_pb_nb;
#endif /* !CONFIG_STATS */
    if (mfs->head == NULL)
        mfs_empty = true;
    /* If the whole MFS has expired i.e. it does not have PB's. */
    if (mfs_empty && sar_expiration_mfs_expired (mfs, ntb))
    {
        mfs->release = true;
        mfs->common.expiration_ntb = ntb
            + mfs->common.expiration_delay_tck;
    }
}

/**
 * Release a MFS TX.
 * \param  ctx  the module context.
 * \param  mfs  the MFS TX to process.
 */
static void
sar_expiration_mfs_tx (sar_t *ctx, mfs_tx_t *mfs)
{
    u32 now = mac_ntb ();
    /* Release Time OUT. */
    if (!mfs->beacon)
    {
        if (mfs->fsm_state == MFS_FSM_CMD_RELEASE
            && sar_expiration_mfs_expired (mfs, now))
            sar_mfs_free_tx (ctx, mfs);
        /* Expire the MFS only if the PBs and the MFS have completely
         * expired. */
        else
            sar_expiration_mfs_purge_tx (ctx, mfs, now);
    }
}

/**
 * Release a MFS RX.
 * \param  ctx  the module context.
 * \param  mfs  the MFS TX to process.
 */
static void
sar_expiration_mfs_rx (sar_t *ctx, mfs_rx_t *mfs)
{
    u32 now = mac_ntb ();
    /* Release Time OUT. */
    if (mfs->release
        && sar_expiration_mfs_expired (mfs, now))
        sar_mfs_free_rx (ctx, mfs);
    /* Expire the MFS only if the PBs and the MFS have completely
     * expired. */
    else
        sar_expiration_mfs_purge_rx (ctx, mfs, now);
}

/**
 * Clean a MFS.
 * \param  mac_store  the mac store.
 * \param  mfs  the MFS concerned.
 * \param  ctx  the callback context.
 */
static void
sar_expiration_mfs_found (mac_store_t *mac_store, mfs_t *mfs, void *ctx)
{
    arch_dsr_lock ();
    if (mfs->common.tx)
        sar_expiration_mfs_tx (ctx, &mfs->tx);
    else
        sar_expiration_mfs_rx (ctx, &mfs->rx);
    arch_dsr_unlock ();
}

void
sar_expiration_mfs (sar_t *ctx)
{
    dbg_assert (ctx);
    mac_store_mfs_travel (ctx->mac_store,
                          sar_expiration_mfs_found,
                          ctx);
}