Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
openairinterface5G
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
dyyu
openairinterface5G
Commits
353334f6
Commit
353334f6
authored
Mar 16, 2017
by
fnabet
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
RLC AM Rx PDU Segment changes
parent
01530385
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
265 additions
and
154 deletions
+265
-154
openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c
openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c
+265
-154
No files found.
openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c
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
->
sn
==
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
->
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_
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 remove 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
))
{
//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
);
}
}
// 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
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment