Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
O
OAI-RAN-5G-sheduler_MaxTBS
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
MAQ5G-PFC
OAI-RAN-5G-sheduler_MaxTBS
Commits
353334f6
Commit
353334f6
authored
8 years ago
by
fnabet
Browse files
Options
Downloads
Patches
Plain Diff
RLC AM Rx PDU Segment changes
parent
01530385
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c
+265
-154
265 additions, 154 deletions
openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c
with
265 additions
and
154 deletions
openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c
+
265
−
154
View file @
353334f6
...
...
@@ -35,34 +35,72 @@ boolean_t rlc_am_rx_check_vr_reassemble(
const
protocol_ctxt_t
*
const
ctxt_pP
,
const
rlc_am_entity_t
*
const
rlc_pP
)
{
mem_block_t
*
cursor_p
=
NULL
;
cursor_p
=
rlc_pP
->
receiver_buffer
.
head
;
mem_block_t
*
cursor_p
=
rlc_pP
->
receiver_buffer
.
head
;
rlc_am_rx_pdu_management_t
*
pdu_cursor_mgnt_p
=
NULL
;
sdu_size_t
next_waited_so
=
0
;
boolean_t
reassemble
=
FALSE
;
if
(
cursor_p
!=
NULL
)
{
rlc_am_pdu_info_t
*
pdu_info_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
rlc_usn_t
sn_ref
=
pdu_info_p
->
sn
;
if
(
sn_ref
!=
rlc_pP
->
vr_r
)
{
reassemble
=
TRUE
;
}
/* Case vrR has advanced from head : most likely case */
/* jump up to vrR */
while
((
RLC_AM_DIFF_SN
(
pdu_info_p
->
sn
,
sn_ref
)
<
RLC_AM_DIFF_SN
(
rlc_pP
->
vr_r
,
sn_ref
))
&&
(
cursor_p
!=
NULL
))
{
if
((
pdu_info_p
->
rf
)
&&
(((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
segment_reassembled
==
RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_NO
))
{
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
segment_reassembled
=
RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_PENDING
;
reassemble
=
TRUE
;
/* Handle first SN if it is made of PDU segments : set them all to be reassembled */
if
(
pdu_info_p
->
rf
)
{
pdu_cursor_mgnt_p
=
(
rlc_am_rx_pdu_management_t
*
)
(
cursor_p
->
data
);
next_waited_so
=
0
;
AssertFatal
(
pdu_cursor_mgnt_p
->
all_segments_received
>
0
,
"AM Rx Check Reassembly head SN=%d with PDU segments != vrR=%d should be fully received LCID=%d
\n
"
,
sn_ref
,
rlc_pP
->
vr_r
,
rlc_pP
->
channel_id
);
while
((
cursor_p
!=
NULL
)
&&
(
pdu_info_p
->
sn
==
sn_ref
)
&&
(
pdu_info_p
->
so
==
next_waited_so
))
{
if
(
pdu_cursor_mgnt_p
->
segment_reassembled
==
RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_NO
)
{
pdu_cursor_mgnt_p
->
segment_reassembled
=
RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_PENDING
;
}
next_waited_so
+=
pdu_info_p
->
payload_size
;
cursor_p
=
cursor_p
->
next
;
if
(
cursor_p
!=
NULL
)
{
pdu_cursor_mgnt_p
=
(
rlc_am_rx_pdu_management_t
*
)
(
cursor_p
->
data
);
pdu_info_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
}
}
}
cursor_p
=
cursor_p
->
next
;
if
(
cursor_p
!=
NULL
)
{
pdu_info_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
/* Now jump up to vrR */
while
((
RLC_AM_DIFF_SN
(
pdu_info_p
->
sn
,
sn_ref
)
<
RLC_AM_DIFF_SN
(
rlc_pP
->
vr_r
,
sn_ref
))
&&
(
cursor_p
!=
NULL
))
{
cursor_p
=
cursor_p
->
next
;
if
(
cursor_p
!=
NULL
)
{
pdu_info_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
}
}
}
if
((
cursor_p
!=
NULL
)
&&
(
pdu_info_p
->
sn
==
rlc_pP
->
vr_r
))
{
/* Handle vrR if it is made of incomplete PDU Segments */
if
((
cursor_p
!=
NULL
)
&&
(
pdu_info_p
->
sn
==
rlc_pP
->
vr_r
))
{
pdu_cursor_mgnt_p
=
(
rlc_am_rx_pdu_management_t
*
)
(
cursor_p
->
data
);
next_waited_so
=
0
;
AssertFatal
(
pdu_cursor_mgnt_p
->
all_segments_received
==
0
,
"AM Rx Check Reassembly vr=%d should be partly received SNHead=%d LCID=%d
\n
"
,
rlc_pP
->
vr_r
,
sn_ref
,
rlc_pP
->
channel_id
);
while
((
cursor_p
!=
NULL
)
&&
(
pdu_info_p
->
sn
==
rlc_pP
->
vr_r
)
&&
(
pdu_info_p
->
so
==
next_waited_so
))
{
if
(
pdu_cursor_mgnt_p
->
segment_reassembled
==
RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_NO
)
{
pdu_cursor_mgnt_p
->
segment_reassembled
=
RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_PENDING
;
}
next_waited_so
+=
pdu_info_p
->
payload_size
;
cursor_p
=
cursor_p
->
next
;
if
(
cursor_p
!=
NULL
)
{
pdu_cursor_mgnt_p
=
(
rlc_am_rx_pdu_management_t
*
)
(
cursor_p
->
data
);
pdu_info_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
}
}
}
}
/* end sn_ref != rlc_pP->vr_r */
else
{
/* case vrR = partially received */
rlc_am_rx_pdu_management_t
*
pdu_cursor_mgnt_p
=
(
rlc_am_rx_pdu_management_t
*
)
(
cursor_p
->
data
);
sdu_size_t
next_waited_so
=
0
;
AssertFatal
(
pdu_cursor_mgnt_p
->
all_segments_received
==
0
,
"AM Rx Check Reassembly vr=%d should be partly received LCID=%d
\n
"
,
pdu_cursor_mgnt_p
=
(
rlc_am_rx_pdu_management_t
*
)
(
cursor_p
->
data
);
next_waited_so
=
0
;
AssertFatal
(
pdu_cursor_mgnt_p
->
all_segments_received
==
0
,
"AM Rx Check Reassembly SNHead=vr=%d should be partly received LCID=%d
\n
"
,
rlc_pP
->
vr_r
,
rlc_pP
->
channel_id
);
while
((
cursor_p
!=
NULL
)
&&
(
pdu_info_p
->
sn
==
rlc_pP
->
vr_r
)
&&
(
pdu_info_p
->
so
==
next_waited_so
))
{
if
(
pdu_cursor_mgnt_p
->
segment_reassembled
==
RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_NO
)
{
...
...
@@ -76,8 +114,7 @@ boolean_t rlc_am_rx_check_vr_reassemble(
pdu_info_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
}
}
}
}
/*end sn_ref == rlc_pP->vr_r */
}
return
reassemble
;
}
...
...
@@ -287,9 +324,7 @@ rlc_am_rx_pdu_status_t rlc_am_rx_list_handle_pdu_segment(
mem_block_t
*
cursor_p
=
rlc_pP
->
receiver_buffer
.
head
;
mem_block_t
*
previous_cursor_p
=
NULL
;
mem_block_t
*
next_cursor_p
=
NULL
;
boolean_t
prev_segment_found
=
FALSE
;
boolean_t
next_segment_found
=
FALSE
;
uint16_t
so_start
=
0
;
uint16_t
so_start_min
=
0
;
uint16_t
so_end
=
0
;
uint16_t
so_start_segment
=
pdu_rx_info_p
->
so
;
uint16_t
so_end_segment
=
pdu_rx_info_p
->
so
+
pdu_rx_info_p
->
payload_size
-
1
;
...
...
@@ -334,120 +369,73 @@ rlc_am_rx_pdu_status_t rlc_am_rx_list_handle_pdu_segment(
return
RLC_AM_DATA_PDU_STATUS_OK
;
}
/********************************************/
/* Now handle case cursor->sn = received SN */
// Filter out SN duplicate
/********************************************/
rlc_am_rx_pdu_management_t
*
pdu_cursor_mgnt_p
=
(
rlc_am_rx_pdu_management_t
*
)
(
cursor_p
->
data
);
// Filter out SN duplicate
if
(
pdu_cursor_mgnt_p
->
all_segments_received
)
{
return
RLC_AM_DATA_PDU_STATUS_AM_SEGMENT_DUPLICATE
;
}
// Handle the remaining case : some PDU Segments already received for the same SN
// Try to insert the PDU according to its SO and SO+datalength of stored ones
// First find the segment just before the pdu to insert
while
((
cursor_p
!=
NULL
)
&&
(
pdu_info_cursor_p
->
sn
==
pdu_rx_info_p
->
sn
))
{
if
(
pdu_rx_info_p
->
so
<
pdu_info_cursor_p
->
so
)
{
prev_segment_found
=
TRUE
;
break
;
}
// Try to Handle the most likely cases first
if
(
pdu_info_cursor_p
->
so
==
0
)
{
/* Loop on stored segments and find the stored segment containing received SOStart */
previous_cursor_p
=
cursor_p
;
pdu_info_previous_cursor_p
=
pdu_info_cursor_p
;
cursor_p
=
cursor_p
->
next
;
if
(
cursor_p
!=
NULL
)
{
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
}
}
/* if not previously inserted, it will be put after the last segment if it was not LSF*/
if
(
!
prev_segment_found
)
{
if
(
pdu_info_previous_cursor_p
->
lsf
==
0
)
{
prev_segment_found
=
TRUE
;
next_segment_found
=
TRUE
;
// no more segment after the PDU
next_cursor_p
=
cursor_p
;
AssertFatal
(
previous_cursor_p
->
next
==
next_cursor_p
,
"AM Rx PDU Segment store at the end error, SN=%d
\n
"
,
pdu_rx_info_p
->
sn
);
}
else
{
// the segment is duplicate
return
RLC_AM_DATA_PDU_STATUS_AM_SEGMENT_DUPLICATE
;
while
((
cursor_p
!=
NULL
)
&&
(
pdu_info_cursor_p
->
sn
==
pdu_rx_info_p
->
sn
)
&&
((
pdu_info_cursor_p
->
so
+
pdu_info_cursor_p
->
payload_size
)
<=
so_start_segment
))
{
previous_cursor_p
=
cursor_p
;
pdu_info_previous_cursor_p
=
pdu_info_cursor_p
;
cursor_p
=
cursor_p
->
next
;
if
(
cursor_p
!=
NULL
)
{
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
}
}
}
// Most likely case : no duplicate, the segment is put after all stored segments which are contiguous
if
((
cursor_p
==
NULL
)
||
(
pdu_info_cursor_p
->
sn
!=
pdu_rx_info_p
->
sn
)
||
(
pdu_info_cursor_p
->
so
>
so_end_segment
))
{
LOG_D
(
RLC
,
PROTOCOL_RLC_AM_CTXT_FMT
"[PROCESS RX PDU SEGMENT SN=%d SOSTART=%d] PDU SEGMENT INSERTED AFTER PDU SEGMENT WITH SOEND=%d
\n
"
,
PROTOCOL_RLC_AM_CTXT_ARGS
(
ctxt_pP
,
rlc_pP
),
pdu_rx_info_p
->
sn
,
so_start_segment
,
pdu_info_previous_cursor_p
->
so
+
pdu_info_previous_cursor_p
->
payload_size
-
1
);
// Check that the Segment is not duplicate by scanning stored contiguous segments from previous_cursor_p
if
((
previous_cursor_p
!=
NULL
)
&&
(
pdu_info_previous_cursor_p
->
sn
==
pdu_rx_info_p
->
sn
))
{
so_start
=
pdu_info_previous_cursor_p
->
so
;
so_end
=
pdu_info_previous_cursor_p
->
so
+
pdu_info_previous_cursor_p
->
payload_size
-
1
;
list2_insert_after_element
(
tb_pP
,
previous_cursor_p
,
&
rlc_pP
->
receiver_buffer
);
return
RLC_AM_DATA_PDU_STATUS_OK
;
}
pdu_info_cursor_p
=
pdu_info_previous_cursor_p
;
// Duplicate case : Resume contiguous scan and update previous_cursor_p
so_start_min
=
pdu_info_previous_cursor_p
->
so
;
so_end
=
so_start_min
+
pdu_info_previous_cursor_p
->
payload_size
;
cursor_p
=
previous_cursor_p
->
next
;
rlc_am_pdu_info_t
*
pdu_info_cursor_next_p
=
NULL
;
if
(
cursor_p
!=
NULL
)
{
pdu_info_cursor_
next_
p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
}
while
((
cursor_p
!=
NULL
)
&&
(
pdu_info_cursor_
next_
p
->
s
n
==
pdu_rx_info_p
->
sn
)
&&
(
pdu_info_cursor_next_p
->
so
==
pdu_info_cursor_p
->
so
+
pdu_info_cursor_p
->
payload_size
))
{
so_end
+=
pdu_info_cursor_next_p
->
payload_size
;
pdu_info_cursor_p
=
pdu_info_cursor_
next_p
;
while
((
cursor_p
!=
NULL
)
&&
(
pdu_info_cursor_p
->
sn
==
pdu_rx_info_p
->
sn
)
&&
(
pdu_info_cursor_p
->
s
o
==
so_end
))
{
previous_cursor_p
=
cursor_p
;
pdu_info_previous_cursor_p
=
pdu_info_cursor_p
;
so_end
+
=
pdu_info_cursor_
p
->
payload_size
;
cursor_p
=
cursor_p
->
next
;
if
(
cursor_p
!=
NULL
)
{
pdu_info_cursor_
next_
p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
}
}
/* Now discard the PDU segment if it is within so_start so_end */
if
((
so_start
<=
so_start_segment
)
&&
(
so_end_segment
<
=
so_end
))
{
/* Now discard the PDU segment if it is within so_start
_min and
so_end */
if
((
so_start
_min
<=
so_start_segment
)
&&
(
so_end_segment
<
so_end
))
{
LOG_D
(
RLC
,
PROTOCOL_RLC_AM_CTXT_FMT
"[PROCESS RX PDU SEGMENT] DISCARD : DUPLICATE SEGMENT SN=%d
\n
"
,
PROTOCOL_RLC_AM_CTXT_ARGS
(
ctxt_pP
,
rlc_pP
),
pdu_rx_info_p
->
sn
);
return
RLC_AM_DATA_PDU_STATUS_AM_SEGMENT_DUPLICATE
;
}
}
// Now found the segment which will be right after the pdu to insert
if
(
!
next_segment_found
)
{
/* special case if SN=vrR and some segments have been previously reassembled and not yet discarded */
/* update previous_cursor_p up to the last reassembled Segment */
if
((
previous_cursor_p
!=
NULL
)
&&
(
pdu_rx_info_p
->
sn
==
rlc_pP
->
vr_r
))
{
if
(((
rlc_am_rx_pdu_management_t
*
)(
previous_cursor_p
->
data
))
->
segment_reassembled
==
RLC_AM_RX_PDU_SEGMENT_REASSEMBLED
)
{
pdu_info_previous_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
previous_cursor_p
->
data
))
->
pdu_info
;
so_end
=
pdu_info_previous_cursor_p
->
so
+
pdu_info_previous_cursor_p
->
payload_size
;
cursor_p
=
previous_cursor_p
->
next
;
if
(
cursor_p
!=
NULL
)
{
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
}
while
((
cursor_p
!=
NULL
)
&&
(
pdu_info_cursor_p
->
sn
==
pdu_rx_info_p
->
sn
)
&&
(((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
segment_reassembled
==
RLC_AM_RX_PDU_SEGMENT_REASSEMBLED
))
{
AssertFatal
(
pdu_info_cursor_p
->
so
==
so_end
,
"AM Rx PDU Segment store contiguous reassembled error, SN=%d
\n
"
,
pdu_rx_info_p
->
sn
);
so_end
+=
pdu_info_cursor_p
->
payload_size
;
previous_cursor_p
=
cursor_p
;
cursor_p
=
cursor_p
->
next
;
if
(
cursor_p
!=
NULL
)
{
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
}
}
}
}
if
(
previous_cursor_p
!=
NULL
)
{
cursor_p
=
previous_cursor_p
->
next
;
}
else
{
cursor_p
=
rlc_pP
->
receiver_buffer
.
head
;
}
// Discard potential embedded segments in the received PDU segment
// The first one is discontigous
next_cursor_p
=
cursor_p
;
if
(
next_cursor_p
!=
NULL
)
{
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
next_cursor_p
->
data
))
->
pdu_info
;
}
// Discard embedded segments in the received PDU segment
while
((
next_cursor_p
!=
NULL
)
&&
(
pdu_info_cursor_p
->
sn
==
pdu_rx_info_p
->
sn
)
&&
(
pdu_rx_info_p
->
so
+
pdu_rx_info_p
->
payload_size
>=
pdu_info_cursor_p
->
so
+
pdu_info_cursor_p
->
payload_size
))
{
(
so_end_segment
>=
pdu_info_cursor_p
->
so
+
pdu_info_cursor_p
->
payload_size
-
1
))
{
/* Discard the segment */
cursor_p
=
next_cursor_p
;
next_cursor_p
=
next_cursor_p
->
next
;
...
...
@@ -458,75 +446,196 @@ rlc_am_rx_pdu_status_t rlc_am_rx_list_handle_pdu_segment(
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
next_cursor_p
->
data
))
->
pdu_info
;
}
}
}
cursor_p
=
next_cursor_p
;
/
* Now r
emove duplicate
bytes */
// remove duplicate at the begining, only valid if the segment is to be inserted after a PDU segment of the same SN
if
(
previous_cursor_p
!=
NULL
)
{
pdu_info_previous_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
previous_cursor_p
->
data
))
->
pdu_info
;
if
((
pdu_info_previous_cursor_p
->
sn
==
pdu_rx_info_p
->
sn
)
&&
(
so_start_segment
<
pdu_info_previous_cursor_p
->
so
+
pdu_info_previous_cursor_p
->
payload_size
)
)
{
/
/R
emove duplicate
at the begining
if
(
so_start_segment
<
pdu_info_previous_cursor_p
->
so
)
{
so_start_segment
=
pdu_info_previous_cursor_p
->
so
+
pdu_info_previous_cursor_p
->
payload_size
;
}
else
if
(
so_start_segment
<
pdu_info_previous_cursor_p
->
so
+
pdu_info_previous_cursor_p
->
payload_size
){
so_start_segment
+=
(
pdu_info_previous_cursor_p
->
so
+
pdu_info_previous_cursor_p
->
payload_size
-
so_start_segment
);
}
}
// remove duplicate at the end
if
(
next_
cursor_p
!=
NULL
)
{
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
next_cursor_p
->
data
))
->
pdu_info
;
//
Now
remove duplicate at the end
, only valid if cursor_p SN has the same received SN
if
(
cursor_p
!=
NULL
)
{
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
next_cursor_p
->
data
))
->
pdu_info
;
if
((
pdu_info_cursor_p
->
sn
==
pdu_rx_info_p
->
sn
)
&&
(
so_end_segment
>=
pdu_info_cursor_p
->
so
))
{
so_end_segment
=
pdu_info_cursor_p
->
so
-
1
;
if
((
pdu_info_cursor_p
->
sn
==
pdu_rx_info_p
->
sn
)
&&
(
so_end_segment
>=
pdu_info_cursor_p
->
so
))
{
so_end_segment
=
pdu_info_cursor_p
->
so
-
1
;
}
}
}
AssertFatal
((
so_start_segment
<=
so_end_segment
)
&&
(
pdu_rx_info_p
->
so
<=
so_start_segment
)
&&
(
so_end_segment
<=
pdu_rx_info_p
->
so
+
pdu_rx_info_p
->
payload_size
-
1
),
" AM RX PDU Segment Duplicate elimination error OldSOStart=%d OldSOEnd=%d newSOStart=%d newSOEnd =%d SN=%d
\n
"
,
pdu_rx_info_p
->
so
,
pdu_rx_info_p
->
so
+
pdu_rx_info_p
->
payload_size
-
1
,
so_start_segment
,
so_end_segment
,
pdu_rx_info_p
->
sn
);
AssertFatal
((
so_start_segment
<=
so_end_segment
)
&&
(
pdu_rx_info_p
->
so
<=
so_start_segment
)
&&
(
so_end_segment
<=
pdu_rx_info_p
->
so
+
pdu_rx_info_p
->
payload_size
-
1
),
" AM RX PDU Segment Duplicate elimination error
FirstSO=0
OldSOStart=%d OldSOEnd=%d newSOStart=%d newSOEnd =%d SN=%d
\n
"
,
pdu_rx_info_p
->
so
,
pdu_rx_info_p
->
so
+
pdu_rx_info_p
->
payload_size
-
1
,
so_start_segment
,
so_end_segment
,
pdu_rx_info_p
->
sn
);
/* Last step : Insertion */
/* If some duplicate bytes had been removed, build a new PDU segment */
if
((
pdu_rx_info_p
->
so
!=
so_start_segment
)
||
(
so_end_segment
!=
pdu_rx_info_p
->
so
+
pdu_rx_info_p
->
payload_size
-
1
))
{
}
// end pdu_info_cursor_p->so == 0
else
{
// Handle most likely case : PDU Segment without duplicate is inserted before first stored PDU segment
if
(
so_end_segment
<
pdu_info_cursor_p
->
so
)
{
LOG_D
(
RLC
,
PROTOCOL_RLC_AM_CTXT_FMT
"[PROCESS RX PDU SEGMENT SN=%d SOSTART=%d SOEND=%d] PDU SEGMENT INSERTED BEFORE PDU SEGMENT WITH SOSTART=%d
\n
"
,
PROTOCOL_RLC_AM_CTXT_ARGS
(
ctxt_pP
,
rlc_pP
),
pdu_rx_info_p
->
sn
,
so_start_segment
,
so_end_segment
,
pdu_info_cursor_p
->
so
);
mem_block_t
*
trunc_segment
=
create_new_segment_from_pdu
(
tb_pP
,
so_start_segment
-
pdu_rx_info_p
->
so
,
so_end_segment
-
so_start_segment
+
1
);
if
(
trunc_segment
!=
NULL
)
{
LOG_I
(
RLC
,
PROTOCOL_RLC_AM_CTXT_FMT
"[PROCESS RX PDU SEGMENT] CREATE SEGMENT FROM SEGMENT OFFSET=%d DATA LENGTH=%d SN=%d
\n
"
,
PROTOCOL_RLC_AM_CTXT_ARGS
(
ctxt_pP
,
rlc_pP
),
so_start_segment
-
pdu_rx_info_p
->
so
,
so_end_segment
-
so_start_segment
+
1
,
pdu_rx_info_p
->
sn
);
list2_insert_before_element
(
tb_pP
,
cursor_p
,
&
rlc_pP
->
receiver_buffer
);
return
RLC_AM_DATA_PDU_STATUS_OK
;
}
if
(
previous_cursor_p
!=
NULL
)
{
list2_insert_after_element
(
trunc_segment
,
previous_cursor_p
,
&
rlc_pP
->
receiver_buffer
);
// Handle duplicate case
if
(
so_start_segment
<
pdu_info_cursor_p
->
so
)
{
// First Case : only duplicate at the end
// Scan for embedded segments to be discarded
next_cursor_p
=
cursor_p
;
while
((
next_cursor_p
!=
NULL
)
&&
(
pdu_info_cursor_p
->
sn
==
pdu_rx_info_p
->
sn
)
&&
(
so_end_segment
>=
pdu_info_cursor_p
->
so
+
pdu_info_cursor_p
->
payload_size
-
1
))
{
/* Discard the segment */
cursor_p
=
next_cursor_p
;
next_cursor_p
=
next_cursor_p
->
next
;
list2_remove_element
(
cursor_p
,
&
rlc_pP
->
receiver_buffer
);
free_mem_block
(
cursor_p
,
__func__
);
if
(
next_cursor_p
!=
NULL
)
{
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
next_cursor_p
->
data
))
->
pdu_info
;
}
}
else
{
list2_insert_before_element
(
trunc_segment
,
rlc_pP
->
receiver_buffer
.
head
,
&
rlc_pP
->
receiver_buffer
);
cursor_p
=
next_cursor_p
;
// Now remove duplicate at the end, only valid if cursor_p SN has the same received SN
if
(
cursor_p
!=
NULL
)
{
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
next_cursor_p
->
data
))
->
pdu_info
;
if
((
pdu_info_cursor_p
->
sn
==
pdu_rx_info_p
->
sn
)
&&
(
so_end_segment
>=
pdu_info_cursor_p
->
so
))
{
so_end_segment
=
pdu_info_cursor_p
->
so
-
1
;
}
}
/* Free original PDU Segment */
free_mem_block
(
tb_pP
,
__func__
);
AssertFatal
((
so_start_segment
<=
so_end_segment
)
&&
(
so_end_segment
<=
pdu_rx_info_p
->
so
+
pdu_rx_info_p
->
payload_size
-
1
),
" AM RX PDU Segment Duplicate elimination at the end error FirstSO!=0 SOStart=%d OldSOEnd=%d newSOEnd =%d SN=%d
\n
"
,
pdu_rx_info_p
->
so
,
pdu_rx_info_p
->
so
+
pdu_rx_info_p
->
payload_size
-
1
,
so_end_segment
,
pdu_rx_info_p
->
sn
);
return
RLC_AM_DATA_PDU_STATUS_OK
;
}
else
{
return
RLC_AM_DATA_PDU_STATUS_BUFFER_FULL
;
// Second Case: Duplicate at the begining and potentially at the end
/* Loop on stored segments and find the stored segment containing received SOStart */
previous_cursor_p
=
cursor_p
;
pdu_info_previous_cursor_p
=
pdu_info_cursor_p
;
while
((
cursor_p
!=
NULL
)
&&
(
pdu_info_cursor_p
->
sn
==
pdu_rx_info_p
->
sn
)
&&
((
pdu_info_cursor_p
->
so
+
pdu_info_cursor_p
->
payload_size
)
<=
so_start_segment
))
{
previous_cursor_p
=
cursor_p
;
pdu_info_previous_cursor_p
=
pdu_info_cursor_p
;
cursor_p
=
cursor_p
->
next
;
if
(
cursor_p
!=
NULL
)
{
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
}
}
// Most likely case : no duplicate, the segment is put after all stored segments which are contiguous
if
((
cursor_p
==
NULL
)
||
(
pdu_info_cursor_p
->
sn
!=
pdu_rx_info_p
->
sn
)
||
(
pdu_info_cursor_p
->
so
>
so_end_segment
))
{
LOG_D
(
RLC
,
PROTOCOL_RLC_AM_CTXT_FMT
"[PROCESS RX PDU SEGMENT SN=%d SOSTART=%d] PDU SEGMENT INSERTED AFTER PDU SEGMENT WITH SOEND=%d
\n
"
,
PROTOCOL_RLC_AM_CTXT_ARGS
(
ctxt_pP
,
rlc_pP
),
pdu_rx_info_p
->
sn
,
so_start_segment
,
pdu_info_previous_cursor_p
->
so
+
pdu_info_previous_cursor_p
->
payload_size
-
1
);
list2_insert_after_element
(
tb_pP
,
previous_cursor_p
,
&
rlc_pP
->
receiver_buffer
);
return
RLC_AM_DATA_PDU_STATUS_OK
;
}
// Now look for contiguous segments to check whether the received segment is not fully duplicate
so_start_min
=
pdu_info_previous_cursor_p
->
so
;
so_end
=
so_start_min
+
pdu_info_previous_cursor_p
->
payload_size
;
cursor_p
=
previous_cursor_p
->
next
;
if
(
cursor_p
!=
NULL
)
{
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
}
while
((
cursor_p
!=
NULL
)
&&
(
pdu_info_cursor_p
->
sn
==
pdu_rx_info_p
->
sn
)
&&
(
pdu_info_cursor_p
->
so
==
so_end
))
{
previous_cursor_p
=
cursor_p
;
pdu_info_previous_cursor_p
=
pdu_info_cursor_p
;
so_end
+=
pdu_info_cursor_p
->
payload_size
;
cursor_p
=
cursor_p
->
next
;
if
(
cursor_p
!=
NULL
)
{
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
;
}
}
/* Now discard the PDU segment if it is within so_start_min and so_end */
if
((
so_start_min
<=
so_start_segment
)
&&
(
so_end_segment
<
so_end
))
{
LOG_D
(
RLC
,
PROTOCOL_RLC_AM_CTXT_FMT
"[PROCESS RX PDU SEGMENT] DISCARD : DUPLICATE SEGMENT SN=%d
\n
"
,
PROTOCOL_RLC_AM_CTXT_ARGS
(
ctxt_pP
,
rlc_pP
),
pdu_rx_info_p
->
sn
);
return
RLC_AM_DATA_PDU_STATUS_AM_SEGMENT_DUPLICATE
;
}
//Remove duplicate at the begining
if
(
so_start_segment
<
pdu_info_previous_cursor_p
->
so
)
{
so_start_segment
=
pdu_info_previous_cursor_p
->
so
+
pdu_info_previous_cursor_p
->
payload_size
;
}
else
if
(
so_start_segment
<
pdu_info_previous_cursor_p
->
so
+
pdu_info_previous_cursor_p
->
payload_size
){
so_start_segment
+=
(
pdu_info_previous_cursor_p
->
so
+
pdu_info_previous_cursor_p
->
payload_size
-
so_start_segment
);
}
// Now Scan for embedded segments to be discarded
next_cursor_p
=
cursor_p
;
while
((
next_cursor_p
!=
NULL
)
&&
(
pdu_info_cursor_p
->
sn
==
pdu_rx_info_p
->
sn
)
&&
(
so_end_segment
>=
pdu_info_cursor_p
->
so
+
pdu_info_cursor_p
->
payload_size
-
1
))
{
/* Discard the segment */
cursor_p
=
next_cursor_p
;
next_cursor_p
=
next_cursor_p
->
next
;
list2_remove_element
(
cursor_p
,
&
rlc_pP
->
receiver_buffer
);
free_mem_block
(
cursor_p
,
__func__
);
if
(
next_cursor_p
!=
NULL
)
{
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
next_cursor_p
->
data
))
->
pdu_info
;
}
}
cursor_p
=
next_cursor_p
;
// Now remove duplicate at the end, only valid if cursor_p SN has the same received SN
if
(
cursor_p
!=
NULL
)
{
pdu_info_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
next_cursor_p
->
data
))
->
pdu_info
;
if
((
pdu_info_cursor_p
->
sn
==
pdu_rx_info_p
->
sn
)
&&
(
so_end_segment
>=
pdu_info_cursor_p
->
so
))
{
so_end_segment
=
pdu_info_cursor_p
->
so
-
1
;
}
}
AssertFatal
((
so_start_segment
<=
so_end_segment
)
&&
(
pdu_rx_info_p
->
so
<=
so_start_segment
)
&&
(
so_end_segment
<=
pdu_rx_info_p
->
so
+
pdu_rx_info_p
->
payload_size
-
1
),
" AM RX PDU Segment Duplicate elimination error FirstSO!=0 OldSOStart=%d OldSOEnd=%d newSOStart=%d newSOEnd =%d SN=%d
\n
"
,
pdu_rx_info_p
->
so
,
pdu_rx_info_p
->
so
+
pdu_rx_info_p
->
payload_size
-
1
,
so_start_segment
,
so_end_segment
,
pdu_rx_info_p
->
sn
);
}
}
else
{
}
// end pdu_info_cursor_p->so != 0
/* Last step : duplicate bytes had been removed, build a new PDU segment */
AssertFatal
((
pdu_rx_info_p
->
so
!=
so_start_segment
)
||
(
so_end_segment
!=
pdu_rx_info_p
->
so
+
pdu_rx_info_p
->
payload_size
-
1
),
" AM RX PDU Segment Duplicate elimination error FirstSO!=0 OldSOStart=%d OldSOEnd=%d newSOStart=%d newSOEnd =%d SN=%d
\n
"
,
pdu_rx_info_p
->
so
,
pdu_rx_info_p
->
so
+
pdu_rx_info_p
->
payload_size
-
1
,
so_start_segment
,
so_end_segment
,
pdu_rx_info_p
->
sn
);
mem_block_t
*
trunc_segment
=
create_new_segment_from_pdu
(
tb_pP
,
so_start_segment
-
pdu_rx_info_p
->
so
,
so_end_segment
-
so_start_segment
+
1
);
if
(
trunc_segment
!=
NULL
)
{
LOG_I
(
RLC
,
PROTOCOL_RLC_AM_CTXT_FMT
"[PROCESS RX PDU SEGMENT] CREATE SEGMENT FROM SEGMENT OFFSET=%d DATA LENGTH=%d SN=%d
\n
"
,
PROTOCOL_RLC_AM_CTXT_ARGS
(
ctxt_pP
,
rlc_pP
),
so_start_segment
-
pdu_rx_info_p
->
so
,
so_end_segment
-
so_start_segment
+
1
,
pdu_rx_info_p
->
sn
);
if
(
previous_cursor_p
!=
NULL
)
{
pdu_info_previous_cursor_p
=
&
((
rlc_am_rx_pdu_management_t
*
)(
previous_cursor_p
->
data
))
->
pdu_info
;
LOG_D
(
RLC
,
PROTOCOL_RLC_AM_CTXT_FMT
"[PROCESS RX PDU SEGMENT SN=%d NOT EMPTY] PDU SEGMENT INSERTED AFTER PDU SN=%d
\n
"
,
PROTOCOL_RLC_AM_CTXT_ARGS
(
ctxt_pP
,
rlc_pP
),
pdu_rx_info_p
->
sn
,
pdu_info_previous_cursor_p
->
sn
);
list2_insert_after_element
(
tb_pP
,
previous_cursor_p
,
&
rlc_pP
->
receiver_buffer
);
list2_insert_after_element
(
trunc_segment
,
previous_cursor_p
,
&
rlc_pP
->
receiver_buffer
);
}
else
{
LOG_D
(
RLC
,
PROTOCOL_RLC_AM_CTXT_FMT
"[PROCESS RX PDU SEGMENT SN=%d NOT EMPTY] PDU SEGMENT INSERTED BEFORE PDU SN=%d
\n
"
,
PROTOCOL_RLC_AM_CTXT_ARGS
(
ctxt_pP
,
rlc_pP
),
pdu_rx_info_p
->
sn
,
pdu_rx_info_p
->
sn
);
list2_insert_before_element
(
tb_pP
,
rlc_pP
->
receiver_buffer
.
head
,
&
rlc_pP
->
receiver_buffer
);
list2_insert_before_element
(
trunc_segment
,
rlc_pP
->
receiver_buffer
.
head
,
&
rlc_pP
->
receiver_buffer
);
}
/* Free original PDU Segment */
free_mem_block
(
tb_pP
,
__func__
);
return
RLC_AM_DATA_PDU_STATUS_OK
;
}
else
{
return
RLC_AM_DATA_PDU_STATUS_BUFFER_FULL
;
}
}
rlc_am_rx_pdu_status_t
rlc_am_rx_list_handle_pdu
(
...
...
@@ -1316,10 +1425,12 @@ rlc_am_rx_list_reassemble_rlc_sdus(
}
/* Reset Management pointers */
if
((
cursor_p
!=
NULL
)
&&
((((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
pdu_info
.
sn
==
RLC_AM_NEXT_SN
(
sn
))
||
(((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
))
->
segment_reassembled
==
RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_PENDING
)))
{
if
(
cursor_p
!=
NULL
)
{
rlc_am_rx_pdu_management_p
=
((
rlc_am_rx_pdu_management_t
*
)(
cursor_p
->
data
));
/* Next SN must be the same or SN+1 */
if
(
RLC_AM_DIFF_SN
(
rlc_am_rx_pdu_management_p
->
pdu_info
.
sn
,
sn
)
>
1
)
{
return
;
}
}
else
{
return
;
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment