2013-11-07 06:21:06 +00:00
|
|
|
/* Copied from tbf.cpp
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012 Ivan Klyuchnikov
|
|
|
|
* Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
|
|
|
|
* Copyright (C) 2013 by Holger Hans Peter Freyther
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <bts.h>
|
|
|
|
|
2013-11-13 13:56:55 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
2013-11-07 06:21:06 +00:00
|
|
|
extern "C" {
|
|
|
|
#include <osmocom/core/msgb.h>
|
|
|
|
}
|
|
|
|
|
2020-03-11 13:04:52 +00:00
|
|
|
#include "pcu_utils.h"
|
|
|
|
|
2013-11-07 06:21:06 +00:00
|
|
|
/* reset LLC frame */
|
|
|
|
void gprs_llc::reset()
|
|
|
|
{
|
2013-11-13 16:14:42 +00:00
|
|
|
m_index = 0;
|
2013-11-13 15:56:15 +00:00
|
|
|
m_length = 0;
|
2013-11-26 15:39:47 +00:00
|
|
|
|
|
|
|
memset(frame, 0x42, sizeof(frame));
|
2013-11-07 06:21:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void gprs_llc::reset_frame_space()
|
|
|
|
{
|
2013-11-13 16:14:42 +00:00
|
|
|
m_index = 0;
|
2013-11-07 06:21:06 +00:00
|
|
|
}
|
|
|
|
|
2015-03-20 12:57:27 +00:00
|
|
|
/* Put an Unconfirmed Information (UI) Dummy command, see GSM 44.064, 6.4.2.2 */
|
|
|
|
void gprs_llc::put_dummy_frame(size_t req_len)
|
|
|
|
{
|
|
|
|
/* The shortest dummy command (the spec requests at least 6 octets) */
|
|
|
|
static const uint8_t llc_dummy_command[] = {
|
|
|
|
0x43, 0xc0, 0x01, 0x2b, 0x2b, 0x2b
|
|
|
|
};
|
2015-07-07 11:43:44 +00:00
|
|
|
static const size_t max_dummy_command_len = 79;
|
2015-03-20 12:57:27 +00:00
|
|
|
|
|
|
|
put_frame(llc_dummy_command, sizeof(llc_dummy_command));
|
|
|
|
|
|
|
|
if (req_len > max_dummy_command_len)
|
|
|
|
req_len = max_dummy_command_len;
|
|
|
|
|
|
|
|
/* Add further stuffing, if the requested length exceeds the minimum
|
|
|
|
* dummy command length */
|
|
|
|
while (m_length < req_len)
|
|
|
|
frame[m_length++] = 0x2b;
|
|
|
|
}
|
|
|
|
|
2013-11-07 06:21:06 +00:00
|
|
|
void gprs_llc::put_frame(const uint8_t *data, size_t len)
|
|
|
|
{
|
2013-11-13 13:56:55 +00:00
|
|
|
/* only put frames when we are empty */
|
2013-11-13 16:14:42 +00:00
|
|
|
OSMO_ASSERT(m_index == 0 && m_length == 0);
|
2013-11-13 15:56:15 +00:00
|
|
|
append_frame(data, len);
|
|
|
|
}
|
2013-11-13 13:56:55 +00:00
|
|
|
|
2013-11-13 15:56:15 +00:00
|
|
|
void gprs_llc::append_frame(const uint8_t *data, size_t len)
|
|
|
|
{
|
2013-11-13 13:56:55 +00:00
|
|
|
/* TODO: bounds check */
|
2013-11-21 20:30:23 +00:00
|
|
|
memcpy(frame + m_length, data, len);
|
2013-11-13 15:56:15 +00:00
|
|
|
m_length += len;
|
2013-11-07 06:21:06 +00:00
|
|
|
}
|
|
|
|
|
2015-05-29 08:37:09 +00:00
|
|
|
void gprs_llc::init()
|
2013-11-07 06:21:06 +00:00
|
|
|
{
|
2015-05-29 08:37:09 +00:00
|
|
|
reset();
|
|
|
|
}
|
2013-11-07 06:21:06 +00:00
|
|
|
|
2015-05-29 08:37:09 +00:00
|
|
|
bool gprs_llc::is_user_data_frame(uint8_t *data, size_t len)
|
|
|
|
{
|
|
|
|
if (len < 2)
|
|
|
|
return false;
|
2013-12-04 16:10:54 +00:00
|
|
|
|
2015-05-29 08:37:09 +00:00
|
|
|
if ((data[0] & 0x0f) == 1 /* GPRS_SAPI_GMM */)
|
|
|
|
return false;
|
|
|
|
|
2015-06-11 09:47:06 +00:00
|
|
|
if ((data[0] & 0xe0) != 0xc0 /* LLC UI */)
|
|
|
|
/* It is not an LLC UI frame, see TS 44.064, 6.3 */
|
2015-05-29 08:37:09 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
2013-11-07 06:21:06 +00:00
|
|
|
}
|
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
void llc_queue_init(struct gprs_llc_queue *q)
|
2013-11-07 06:21:06 +00:00
|
|
|
{
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
INIT_LLIST_HEAD(&q->m_queue);
|
|
|
|
q->m_queue_size = 0;
|
|
|
|
q->m_queue_octets = 0;
|
|
|
|
q->m_avg_queue_delay = 0;
|
2015-05-29 08:37:09 +00:00
|
|
|
}
|
|
|
|
|
2020-02-26 19:05:33 +00:00
|
|
|
|
2020-03-11 13:04:52 +00:00
|
|
|
void gprs_llc_queue::enqueue(struct msgb *llc_msg, const struct timespec *expire_time)
|
2015-05-29 08:37:09 +00:00
|
|
|
{
|
2015-06-15 12:32:33 +00:00
|
|
|
MetaInfo *meta_storage;
|
|
|
|
|
2020-02-26 19:05:33 +00:00
|
|
|
osmo_static_assert(sizeof(*meta_storage) <= sizeof(llc_msg->cb), info_does_not_fit);
|
2015-06-15 12:32:33 +00:00
|
|
|
|
2015-05-29 08:37:09 +00:00
|
|
|
m_queue_size += 1;
|
2015-06-15 12:32:33 +00:00
|
|
|
m_queue_octets += msgb_length(llc_msg);
|
|
|
|
|
|
|
|
meta_storage = (MetaInfo *)&llc_msg->cb[0];
|
2020-03-11 13:04:52 +00:00
|
|
|
osmo_clock_gettime(CLOCK_MONOTONIC, &meta_storage->recv_time);
|
2020-02-26 19:05:33 +00:00
|
|
|
meta_storage->expire_time = *expire_time;
|
2015-06-15 12:32:33 +00:00
|
|
|
|
2015-05-29 08:37:09 +00:00
|
|
|
msgb_enqueue(&m_queue, llc_msg);
|
|
|
|
}
|
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
void llc_queue_clear(struct gprs_llc_queue *q, struct BTS *bts)
|
2015-05-29 08:37:09 +00:00
|
|
|
{
|
|
|
|
struct msgb *msg;
|
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
while ((msg = msgb_dequeue(&q->m_queue))) {
|
2015-05-29 08:37:09 +00:00
|
|
|
if (bts)
|
2020-05-12 18:54:35 +00:00
|
|
|
bts->do_rate_ctr_inc(CTR_LLC_FRAME_DROPPED);
|
2015-05-29 08:37:09 +00:00
|
|
|
msgb_free(msg);
|
|
|
|
}
|
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
q->m_queue_size = 0;
|
|
|
|
q->m_queue_octets = 0;
|
2013-11-07 06:21:06 +00:00
|
|
|
}
|
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
void llc_queue_move_and_merge(struct gprs_llc_queue *q, struct gprs_llc_queue *o)
|
2015-08-21 16:07:47 +00:00
|
|
|
{
|
|
|
|
struct msgb *msg, *msg1 = NULL, *msg2 = NULL;
|
|
|
|
struct llist_head new_queue;
|
|
|
|
size_t queue_size = 0;
|
|
|
|
size_t queue_octets = 0;
|
|
|
|
INIT_LLIST_HEAD(&new_queue);
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
if (msg1 == NULL)
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
msg1 = msgb_dequeue(&q->m_queue);
|
2015-08-21 16:07:47 +00:00
|
|
|
|
|
|
|
if (msg2 == NULL)
|
|
|
|
msg2 = msgb_dequeue(&o->m_queue);
|
|
|
|
|
|
|
|
if (msg1 == NULL && msg2 == NULL)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (msg1 == NULL) {
|
|
|
|
msg = msg2;
|
|
|
|
msg2 = NULL;
|
|
|
|
} else if (msg2 == NULL) {
|
|
|
|
msg = msg1;
|
|
|
|
msg1 = NULL;
|
|
|
|
} else {
|
|
|
|
const MetaInfo *mi1 = (MetaInfo *)&msg1->cb[0];
|
|
|
|
const MetaInfo *mi2 = (MetaInfo *)&msg2->cb[0];
|
|
|
|
|
2020-03-11 13:04:52 +00:00
|
|
|
if (timespeccmp(&mi2->recv_time, &mi1->recv_time, >)) {
|
2015-08-21 16:07:47 +00:00
|
|
|
msg = msg1;
|
|
|
|
msg1 = NULL;
|
|
|
|
} else {
|
|
|
|
msg = msg2;
|
|
|
|
msg2 = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
msgb_enqueue(&new_queue, msg);
|
|
|
|
queue_size += 1;
|
|
|
|
queue_octets += msgb_length(msg);
|
|
|
|
}
|
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(llist_empty(&q->m_queue));
|
2015-08-21 16:07:47 +00:00
|
|
|
OSMO_ASSERT(llist_empty(&o->m_queue));
|
|
|
|
|
|
|
|
o->m_queue_size = 0;
|
|
|
|
o->m_queue_octets = 0;
|
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
llist_splice_init(&new_queue, &q->m_queue);
|
|
|
|
q->m_queue_size = queue_size;
|
|
|
|
q->m_queue_octets = queue_octets;
|
2015-08-21 16:07:47 +00:00
|
|
|
}
|
|
|
|
|
2013-12-04 17:11:47 +00:00
|
|
|
#define ALPHA 0.5f
|
|
|
|
|
2015-06-15 12:32:33 +00:00
|
|
|
struct msgb *gprs_llc_queue::dequeue(const MetaInfo **info)
|
2013-11-07 06:21:06 +00:00
|
|
|
{
|
2013-12-04 17:11:47 +00:00
|
|
|
struct msgb *msg;
|
2020-03-11 13:04:52 +00:00
|
|
|
struct timespec *tv, tv_now, tv_result;
|
2013-12-04 17:11:47 +00:00
|
|
|
uint32_t lifetime;
|
2015-06-15 12:32:33 +00:00
|
|
|
const MetaInfo *meta_storage;
|
2013-12-04 17:11:47 +00:00
|
|
|
|
2015-05-29 08:37:09 +00:00
|
|
|
msg = msgb_dequeue(&m_queue);
|
2013-12-04 17:11:47 +00:00
|
|
|
if (!msg)
|
|
|
|
return NULL;
|
|
|
|
|
2015-06-15 12:32:33 +00:00
|
|
|
meta_storage = (MetaInfo *)&msg->cb[0];
|
|
|
|
|
|
|
|
if (info)
|
|
|
|
*info = meta_storage;
|
|
|
|
|
2013-12-04 17:11:47 +00:00
|
|
|
m_queue_size -= 1;
|
2015-06-15 12:32:33 +00:00
|
|
|
m_queue_octets -= msgb_length(msg);
|
2013-12-04 17:11:47 +00:00
|
|
|
|
|
|
|
/* take the second time */
|
2020-03-11 13:04:52 +00:00
|
|
|
osmo_clock_gettime(CLOCK_MONOTONIC, &tv_now);
|
|
|
|
tv = (struct timespec *)&msg->data[sizeof(*tv)];
|
|
|
|
timespecsub(&tv_now, &meta_storage->recv_time, &tv_result);
|
2013-12-04 17:11:47 +00:00
|
|
|
|
2020-03-11 13:04:52 +00:00
|
|
|
lifetime = tv_result.tv_sec*1000 + tv_result.tv_nsec/1000000;
|
2013-12-04 17:11:47 +00:00
|
|
|
m_avg_queue_delay = m_avg_queue_delay * ALPHA + lifetime * (1-ALPHA);
|
|
|
|
|
|
|
|
return msg;
|
2013-11-07 06:21:06 +00:00
|
|
|
}
|
2013-11-13 14:17:12 +00:00
|
|
|
|
2020-03-11 13:04:52 +00:00
|
|
|
void gprs_llc_queue::calc_pdu_lifetime(BTS *bts, const uint16_t pdu_delay_csec, struct timespec *tv)
|
2013-11-13 14:17:12 +00:00
|
|
|
{
|
|
|
|
uint16_t delay_csec;
|
|
|
|
if (bts->bts_data()->force_llc_lifetime)
|
|
|
|
delay_csec = bts->bts_data()->force_llc_lifetime;
|
|
|
|
else
|
|
|
|
delay_csec = pdu_delay_csec;
|
|
|
|
|
2013-11-21 20:59:32 +00:00
|
|
|
/* keep timestamp at 0 for infinite delay */
|
2013-11-13 14:19:39 +00:00
|
|
|
if (delay_csec == 0xffff) {
|
|
|
|
memset(tv, 0, sizeof(*tv));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* calculate timestamp of timeout */
|
2020-03-11 13:04:52 +00:00
|
|
|
struct timespec now, csec;
|
|
|
|
osmo_clock_gettime(CLOCK_MONOTONIC, &now);
|
|
|
|
csecs_to_timespec(delay_csec, &csec);
|
2013-11-13 14:35:45 +00:00
|
|
|
|
2020-03-11 13:04:52 +00:00
|
|
|
timespecadd(&now, &csec, tv);
|
2013-11-13 14:17:12 +00:00
|
|
|
}
|
2013-11-13 16:15:26 +00:00
|
|
|
|
2020-03-11 13:04:52 +00:00
|
|
|
bool gprs_llc_queue::is_frame_expired(const struct timespec *tv_now,
|
|
|
|
const struct timespec *tv)
|
2013-11-13 16:15:26 +00:00
|
|
|
{
|
|
|
|
/* Timeout is infinite */
|
2020-03-11 13:04:52 +00:00
|
|
|
if (tv->tv_sec == 0 && tv->tv_nsec == 0)
|
2013-11-13 16:15:26 +00:00
|
|
|
return false;
|
|
|
|
|
2020-03-11 13:04:52 +00:00
|
|
|
return timespeccmp(tv_now, tv, >);
|
2013-11-13 16:15:26 +00:00
|
|
|
}
|