Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG-RAN
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
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
Michael Black
OpenXG-RAN
Commits
4fe3599a
Commit
4fe3599a
authored
Sep 14, 2022
by
Sakthivel Velumani
Committed by
laurent
Dec 14, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PDCP config as two functions
parent
ec21db63
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
106 additions
and
191 deletions
+106
-191
doc/SW_archi.md
doc/SW_archi.md
+2
-1
openair2/ENB_APP/enb_app.c
openair2/ENB_APP/enb_app.c
+0
-1
openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
+42
-76
openair2/MCE_APP/mce_app.c
openair2/MCE_APP/mce_app.c
+0
-1
openair2/RRC/NR/nr_rrc_proto.h
openair2/RRC/NR/nr_rrc_proto.h
+12
-12
openair2/RRC/NR/rrc_gNB.c
openair2/RRC/NR/rrc_gNB.c
+21
-51
openair2/RRC/NR/rrc_gNB_nsa.c
openair2/RRC/NR/rrc_gNB_nsa.c
+7
-13
openair2/RRC/NR_UE/rrc_UE.c
openair2/RRC/NR_UE/rrc_UE.c
+21
-34
openair2/SDAP/nr_sdap/nr_sdap.c
openair2/SDAP/nr_sdap/nr_sdap.c
+1
-1
openair3/MME_APP/mme_app.c
openair3/MME_APP/mme_app.c
+0
-1
No files found.
doc/SW_archi.md
View file @
4fe3599a
...
...
@@ -344,7 +344,8 @@ pdcp_config_set_security(): not yet developped
nr_DRB_preconfiguration(): the mac layer calls this for ???
nr_rrc_pdcp_config_asn1_req() adds a UE in pdcp, pdcp_remove_UE() removes it
nr_pdcp_add_srbs() adds UE SRBs in pdcp, pdcp_remove_UE() removes it
nr_pdcp_add_drbs() adds UE DRBs in pdcp, pdcp_remove_UE() removes it
# GTP
Gtp + UDP are two twin threads performing the data plane interface to the core network
...
...
openair2/ENB_APP/enb_app.c
View file @
4fe3599a
...
...
@@ -41,7 +41,6 @@
# include "intertask_interface.h"
# include "s1ap_eNB.h"
# include "sctp_eNB_task.h"
# include "gtpv1u_eNB_task.h"
# include "x2ap_eNB.h"
# include "x2ap_messages_types.h"
...
...
openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
View file @
4fe3599a
...
...
@@ -911,11 +911,11 @@ static void add_srb(int is_gnb, int rnti, struct NR_SRB_ToAddMod *s,
nr_pdcp_manager_unlock
(
nr_pdcp_ue_manager
);
}
static
void
add_drb_am
(
int
is_gnb
,
int
rnti
,
struct
NR_DRB_ToAddMod
*
s
,
int
ciphering_algorithm
,
int
integrity_algorithm
,
unsigned
char
*
ciphering_key
,
unsigned
char
*
integrity_key
)
void
add_drb_am
(
int
is_gnb
,
int
rnti
,
struct
NR_DRB_ToAddMod
*
s
,
int
ciphering_algorithm
,
int
integrity_algorithm
,
unsigned
char
*
ciphering_key
,
unsigned
char
*
integrity_key
)
{
nr_pdcp_entity_t
*
pdcp_drb
;
nr_pdcp_ue_t
*
ue
;
...
...
@@ -1038,72 +1038,45 @@ static void add_drb(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s,
LOG_I
(
PDCP
,
"%s:%s:%d: added DRB for UE RNTI %x
\n
"
,
__FILE__
,
__FUNCTION__
,
__LINE__
,
rnti
);
}
bool
nr_rrc_pdcp_config_asn1_req
(
const
protocol_ctxt_t
*
const
ctxt_pP
,
NR_SRB_ToAddModList_t
*
const
srb2add_list
,
NR_DRB_ToAddModList_t
*
const
drb2add_list
,
NR_DRB_ToReleaseList_t
*
const
drb2release_list
,
const
uint8_t
security_modeP
,
uint8_t
*
const
kRRCenc
,
uint8_t
*
const
kRRCint
,
uint8_t
*
const
kUPenc
,
uint8_t
*
const
kUPint
,
LTE_PMCH_InfoList_r9_t
*
pmch_InfoList_r9
,
rb_id_t
*
const
defaultDRB
,
struct
NR_CellGroupConfig__rlc_BearerToAddModList
*
rlc_bearer2add_list
)
{
int
rnti
=
ctxt_pP
->
rnti
;
int
i
;
if
(
//ctxt_pP->enb_flag != 1 ||
ctxt_pP
->
module_id
!=
0
||
ctxt_pP
->
instance
!=
0
||
ctxt_pP
->
eNB_index
!=
0
||
//ctxt_pP->configured != 2 ||
//srb2add_list == NULL ||
//drb2add_list != NULL ||
//drb2release_list != NULL ||
//security_modeP != 255 ||
//kRRCenc != NULL ||
//kRRCint != NULL ||
//kUPenc != NULL ||
pmch_InfoList_r9
!=
NULL
/*||
defaultDRB != NULL */
)
{
LOG_I
(
PDCP
,
"Releasing DRBs, oops
\n
"
);
TODO
;
}
void
nr_pdcp_add_srbs
(
eNB_flag_t
enb_flag
,
rnti_t
rnti
,
NR_SRB_ToAddModList_t
*
const
srb2add_list
,
const
uint8_t
security_modeP
,
uint8_t
*
const
kRRCenc
,
uint8_t
*
const
kRRCint
)
{
if
(
srb2add_list
!=
NULL
)
{
for
(
i
=
0
;
i
<
srb2add_list
->
list
.
count
;
i
++
)
{
add_srb
(
ctxt_pP
->
enb_flag
,
rnti
,
srb2add_list
->
list
.
array
[
i
],
for
(
i
nt
i
=
0
;
i
<
srb2add_list
->
list
.
count
;
i
++
)
{
add_srb
(
enb_flag
,
rnti
,
srb2add_list
->
list
.
array
[
i
],
security_modeP
&
0x0f
,
(
security_modeP
>>
4
)
&
0x0f
,
kRRCenc
,
kRRCint
);
}
}
}
else
LOG_W
(
PDCP
,
"nr_pdcp_add_srbs() with void list
\n
"
);
if
(
kRRCenc
)
free
(
kRRCenc
);
if
(
kRRCint
)
free
(
kRRCint
);
}
void
nr_pdcp_add_drbs
(
eNB_flag_t
enb_flag
,
rnti_t
rnti
,
NR_DRB_ToAddModList_t
*
const
drb2add_list
,
const
uint8_t
security_modeP
,
uint8_t
*
const
kUPenc
,
uint8_t
*
const
kUPint
,
struct
NR_CellGroupConfig__rlc_BearerToAddModList
*
rlc_bearer2add_list
)
{
if
(
drb2add_list
!=
NULL
)
{
for
(
i
=
0
;
i
<
drb2add_list
->
list
.
count
;
i
++
)
{
add_drb
(
ctxt_pP
->
enb_flag
,
rnti
,
drb2add_list
->
list
.
array
[
i
],
for
(
i
nt
i
=
0
;
i
<
drb2add_list
->
list
.
count
;
i
++
)
{
add_drb
(
enb_flag
,
rnti
,
drb2add_list
->
list
.
array
[
i
],
rlc_bearer2add_list
->
list
.
array
[
i
]
->
rlc_Config
,
security_modeP
&
0x0f
,
(
security_modeP
>>
4
)
&
0x0f
,
kUPenc
,
kUPint
);
}
}
/* update security */
if
(
kRRCint
!=
NULL
)
{
/* todo */
}
if
(
drb2release_list
!=
NULL
)
{
// TODO
}
free
(
kRRCenc
);
free
(
kRRCint
);
free
(
kUPenc
);
free
(
kUPint
);
return
0
;
}
else
LOG_W
(
PDCP
,
"nr_pdcp_add_drbs() with void list
\n
"
);
if
(
kUPenc
)
free
(
kUPenc
);
if
(
kUPint
)
free
(
kUPint
);
}
/* Dummy function due to dependency from LTE libraries */
...
...
@@ -1190,21 +1163,14 @@ void nr_DRB_preconfiguration(uint16_t crnti)
else
{
PROTOCOL_CTXT_SET_BY_MODULE_ID
(
&
ctxt
,
0
,
ENB_FLAG_NO
,
crnti
,
0
,
0
,
0
);
}
nr_rrc_pdcp_config_asn1_req
(
&
ctxt
,
(
NR_SRB_ToAddModList_t
*
)
NULL
,
rbconfig
->
drb_ToAddModList
,
rbconfig
->
drb_ToReleaseList
,
0
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
Rlc_Bearer_ToAdd_list
);
nr_pdcp_add_drbs
(
ctxt
.
enb_flag
,
ctxt
.
rnti
,
rbconfig
->
drb_ToAddModList
,
0
,
NULL
,
NULL
,
Rlc_Bearer_ToAdd_list
);
nr_rrc_rlc_config_asn1_req
(
&
ctxt
,
(
NR_SRB_ToAddModList_t
*
)
NULL
,
rbconfig
->
drb_ToAddModList
,
...
...
openair2/MCE_APP/mce_app.c
View file @
4fe3599a
...
...
@@ -41,7 +41,6 @@
# include "intertask_interface.h"
# include "s1ap_eNB.h"
# include "sctp_eNB_task.h"
# include "gtpv1u_eNB_task.h"
# include "x2ap_eNB.h"
# include "x2ap_messages_types.h"
...
...
openair2/RRC/NR/nr_rrc_proto.h
View file @
4fe3599a
...
...
@@ -210,17 +210,17 @@ rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt
const
LTE_PMCH_InfoList_r9_t
*
const
pmch_InfoList_r9_pP
,
struct
NR_CellGroupConfig__rlc_BearerToAddModList
*
rlc_bearer2add_list
);
bool
nr_rrc_pdcp_config_asn1_req
(
const
protocol_ctxt_t
*
const
ctxt_pP
,
NR_SRB_ToAddModList_t
*
const
srb2add_list
,
NR_DRB_ToAddModList_t
*
const
drb2add_list
,
NR_DRB_ToReleaseList_t
*
const
drb2release_list
,
const
uint8_t
security_modeP
,
uint8_t
*
const
kRRCenc
,
uint8_t
*
const
kRRCint
,
uint8_t
*
const
kUPenc
,
uint8_t
*
const
kUPint
,
LTE_PMCH_InfoList_r9_t
*
pmch_InfoList_r9
,
rb_id_t
*
const
defaultDRB
,
struct
NR_CellGroupConfig__rlc_BearerToAddModList
*
rlc_bearer2add_list
);
void
nr_pdcp_add_srbs
(
eNB_flag_t
enb_flag
,
rnti_t
rnti
,
NR_SRB_ToAddModList_t
*
const
srb2add_list
,
const
uint8_t
security_modeP
,
uint8_t
*
const
kRRCenc
,
uint8_t
*
const
kUPint
);
void
nr_pdcp_add_drbs
(
eNB_flag_t
enb_flag
,
rnti_t
rnti
,
NR_DRB_ToAddModList_t
*
const
drb2add_list
,
const
uint8_t
security_modeP
,
uint8_t
*
const
kUPenc
,
uint8_t
*
const
kUPint
,
struct
NR_CellGroupConfig__rlc_BearerToAddModList
*
rlc_bearer2add_list
);
#endif
openair2/RRC/NR/rrc_gNB.c
View file @
4fe3599a
...
...
@@ -312,23 +312,7 @@ void apply_macrlc_config(gNB_RRC_INST *rrc,
}
void
apply_pdcp_config
(
rrc_gNB_ue_context_t
*
const
ue_context_pP
,
const
protocol_ctxt_t
*
const
ctxt_pP
)
{
nr_rrc_pdcp_config_asn1_req
(
ctxt_pP
,
ue_context_pP
->
ue_context
.
SRB_configList
,
NULL
,
NULL
,
0
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
get_softmodem_params
()
->
sa
?
ue_context_pP
->
ue_context
.
masterCellGroup
->
rlc_BearerToAddModList
:
NULL
);
}
//-----------------------------------------------------------------------------
void
...
...
@@ -374,7 +358,12 @@ rrc_gNB_generate_RRCSetup(
ue_context_pP
->
ue_context
.
ue_release_timer_thres
=
1000
;
/* TODO: this should go through the E1 interface */
apply_pdcp_config
(
ue_context_pP
,
ctxt_pP
);
nr_pdcp_add_srbs
(
ctxt_pP
->
enb_flag
,
ctxt_pP
->
rnti
,
ue_context_pP
->
ue_context
.
SRB_configList
,
0
,
NULL
,
NULL
);
f1ap_dl_rrc_message_t
dl_rrc
=
{
.
old_gNB_DU_ue_id
=
0xFFFFFF
,
...
...
@@ -1324,19 +1313,21 @@ rrc_gNB_process_RRCReconfigurationComplete(
LOG_D
(
NR_RRC
,
"Configuring PDCP DRBs/SRBs for UE %x
\n
"
,
ue_context_pP
->
ue_context
.
rnti
);
nr_rrc_pdcp_config_asn1_req
(
ctxt_pP
,
SRB_configList
,
// NULL,
DRB_configList
,
DRB_Release_configList2
,
(
ue_context_pP
->
ue_context
.
integrity_algorithm
<<
4
)
|
ue_context_pP
->
ue_context
.
ciphering_algorithm
,
kRRCenc
,
kRRCint
,
kUPenc
,
kUPint
,
NULL
,
NULL
,
get_softmodem_params
()
->
sa
?
ue_context_pP
->
ue_context
.
masterCellGroup
->
rlc_BearerToAddModList
:
NULL
);
nr_pdcp_add_srbs
(
ctxt_pP
->
enb_flag
,
ctxt_pP
->
rnti
,
SRB_configList
,
(
ue_context_pP
->
ue_context
.
integrity_algorithm
<<
4
)
|
ue_context_pP
->
ue_context
.
ciphering_algorithm
,
kRRCenc
,
kRRCint
);
nr_pdcp_add_drbs
(
ctxt_pP
->
enb_flag
,
ctxt_pP
->
rnti
,
DRB_configList
,
(
ue_context_pP
->
ue_context
.
integrity_algorithm
<<
4
)
|
ue_context_pP
->
ue_context
.
ciphering_algorithm
,
kUPenc
,
kUPint
,
get_softmodem_params
()
->
sa
?
ue_context_pP
->
ue_context
.
masterCellGroup
->
rlc_BearerToAddModList
:
NULL
);
/* Refresh SRBs/DRBs */
if
(
!
NODE_IS_CU
(
RC
.
nrrrc
[
ctxt_pP
->
module_id
]
->
node_type
))
{
LOG_D
(
NR_RRC
,
"Configuring RLC DRBs/SRBs for UE %x
\n
"
,
ue_context_pP
->
ue_context
.
rnti
);
...
...
@@ -2180,27 +2171,6 @@ int nr_rrc_gNB_decode_ccch(protocol_ctxt_t *const ctxt_pP,
LOG_I
(
NR_RRC
,
PROTOCOL_NR_RRC_CTXT_UE_FMT
"CALLING RLC CONFIG SRB1 (rbid %d)
\n
"
,
PROTOCOL_NR_RRC_CTXT_UE_ARGS
(
ctxt_pP
),
Idx
);
// nr_rrc_pdcp_config_asn1_req(ctxt_pP,
// ue_context_p->ue_context.SRB_configList,
// NULL,
// NULL,
// 0xff,
// NULL,
// NULL,
// NULL,
// NULL,
// NULL,
// NULL,
// NULL);
// if (!NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) {
// nr_rrc_rlc_config_asn1_req(ctxt_pP,
// ue_context_p->ue_context.SRB_configList,
// NULL,
// NULL,
// NULL,
// NULL);
// }
}
break
;
...
...
openair2/RRC/NR/rrc_gNB_nsa.c
View file @
4fe3599a
...
...
@@ -383,21 +383,15 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
ctxt
.
subframe
,
ctxt
.
eNB_index
);
nr_rrc_pdcp_config_asn1_req
(
&
ctxt
,
get_softmodem_params
()
->
sa
?
ue_context_p
->
ue_context
.
rb_config
->
srb_ToAddModList
:
(
NR_SRB_ToAddModList_t
*
)
NULL
,
ue_context_p
->
ue_context
.
rb_config
->
drb_ToAddModList
,
ue_context_p
->
ue_context
.
rb_config
->
drb_ToReleaseList
,
(
ue_context_p
->
ue_context
.
integrity_algorithm
<<
4
)
|
ue_context_p
->
ue_context
.
ciphering_algorithm
,
NULL
,
/* kRRCenc - unused */
NULL
,
/* kRRCint - unused */
kUPenc
,
/* kUPenc */
kUPint
,
/* kUPint */
NULL
,
NULL
,
ue_context_p
->
ue_context
.
secondaryCellGroup
->
rlc_BearerToAddModList
);
nr_pdcp_add_drbs
(
ctxt
.
enb_flag
,
ctxt
.
rnti
,
ue_context_p
->
ue_context
.
rb_config
->
drb_ToAddModList
,
(
ue_context_p
->
ue_context
.
integrity_algorithm
<<
4
)
|
ue_context_p
->
ue_context
.
ciphering_algorithm
,
kUPenc
,
kUPint
,
ue_context_p
->
ue_context
.
secondaryCellGroup
->
rlc_BearerToAddModList
);
nr_rrc_rlc_config_asn1_req
(
&
ctxt
,
get_softmodem_params
()
->
sa
?
ue_context_p
->
ue_context
.
rb_config
->
srb_ToAddModList
:
(
NR_SRB_ToAddModList_t
*
)
NULL
,
get_softmodem_params
()
->
sa
?
ue_context_p
->
ue_context
.
rb_config
->
srb_ToAddModList
:
NULL
,
ue_context_p
->
ue_context
.
rb_config
->
drb_ToAddModList
,
ue_context_p
->
ue_context
.
rb_config
->
drb_ToReleaseList
,
(
LTE_PMCH_InfoList_r9_t
*
)
NULL
,
...
...
openair2/RRC/NR_UE/rrc_UE.c
View file @
4fe3599a
...
...
@@ -1970,19 +1970,12 @@ nr_rrc_ue_establish_srb2(
NR_UE_rrc_inst
[
ctxt_pP
->
module_id
].
kgnb
,
&
kRRCint
);
// Refresh SRBs
nr_rrc_pdcp_config_asn1_req
(
ctxt_pP
,
radioBearerConfig
->
srb_ToAddModList
,
NULL
,
NULL
,
NR_UE_rrc_inst
[
ctxt_pP
->
module_id
].
cipheringAlgorithm
|
(
NR_UE_rrc_inst
[
ctxt_pP
->
module_id
].
integrityProtAlgorithm
<<
4
),
kRRCenc
,
kRRCint
,
NULL
,
NULL
,
NULL
,
NULL
,
NR_UE_rrc_inst
[
ctxt_pP
->
module_id
].
cell_group_config
->
rlc_BearerToAddModList
);
nr_pdcp_add_srbs
(
ctxt_pP
->
enb_flag
,
ctxt_pP
->
rnti
,
radioBearerConfig
->
srb_ToAddModList
,
NR_UE_rrc_inst
[
ctxt_pP
->
module_id
].
cipheringAlgorithm
|
(
NR_UE_rrc_inst
[
ctxt_pP
->
module_id
].
integrityProtAlgorithm
<<
4
),
kRRCenc
,
kRRCint
);
// Refresh SRBs
nr_rrc_rlc_config_asn1_req
(
ctxt_pP
,
radioBearerConfig
->
srb_ToAddModList
,
...
...
@@ -2075,27 +2068,21 @@ nr_rrc_ue_establish_srb2(
NR_UE_rrc_inst
[
ctxt_pP
->
module_id
].
kgnb
,
&
kUPint
);
// Refresh DRBs
nr_rrc_pdcp_config_asn1_req
(
ctxt_pP
,
NULL
,
radioBearerConfig
->
drb_ToAddModList
,
NULL
,
NR_UE_rrc_inst
[
ctxt_pP
->
module_id
].
cipheringAlgorithm
|
(
NR_UE_rrc_inst
[
ctxt_pP
->
module_id
].
integrityProtAlgorithm
<<
4
),
NULL
,
NULL
,
kUPenc
,
kUPint
,
NULL
,
NR_UE_rrc_inst
[
ctxt_pP
->
module_id
].
defaultDRB
,
NR_UE_rrc_inst
[
ctxt_pP
->
module_id
].
cell_group_config
->
rlc_BearerToAddModList
);
// Refresh DRBs
nr_rrc_rlc_config_asn1_req
(
ctxt_pP
,
NULL
,
radioBearerConfig
->
drb_ToAddModList
,
NULL
,
NULL
,
NR_UE_rrc_inst
[
ctxt_pP
->
module_id
].
cell_group_config
->
rlc_BearerToAddModList
);
nr_pdcp_add_drbs
(
ctxt_pP
->
enb_flag
,
ctxt_pP
->
rnti
,
radioBearerConfig
->
drb_ToAddModList
,
NR_UE_rrc_inst
[
ctxt_pP
->
module_id
].
cipheringAlgorithm
|
(
NR_UE_rrc_inst
[
ctxt_pP
->
module_id
].
integrityProtAlgorithm
<<
4
),
kUPenc
,
kUPint
,
NR_UE_rrc_inst
[
ctxt_pP
->
module_id
].
cell_group_config
->
rlc_BearerToAddModList
);
// Refresh DRBs
nr_rrc_rlc_config_asn1_req
(
ctxt_pP
,
NULL
,
radioBearerConfig
->
drb_ToAddModList
,
NULL
,
NULL
,
NR_UE_rrc_inst
[
ctxt_pP
->
module_id
].
cell_group_config
->
rlc_BearerToAddModList
);
}
// drb_ToAddModList //
if
(
radioBearerConfig
->
drb_ToReleaseList
!=
NULL
)
{
...
...
openair2/SDAP/nr_sdap/nr_sdap.c
View file @
4fe3599a
...
...
@@ -74,7 +74,7 @@ void sdap_data_ind(rb_id_t pdcp_entity,
sdap_entity
=
nr_sdap_get_entity
(
ue_id
,
pdusession_id
);
if
(
sdap_entity
==
NULL
)
{
LOG_E
(
SDAP
,
"%s:%d:%s: Entity not found for ue rnti: %
x and pdusession id: %d
\n
"
,
__FILE__
,
__LINE__
,
__FUNCTION__
,
rnti
,
pdusession_id
);
LOG_E
(
SDAP
,
"%s:%d:%s: Entity not found for ue rnti: %
lu and pdusession id: %d
\n
"
,
__FILE__
,
__LINE__
,
__FUNCTION__
,
ue_id
,
pdusession_id
);
return
;
}
...
...
openair3/MME_APP/mme_app.c
View file @
4fe3599a
...
...
@@ -41,7 +41,6 @@
# include "intertask_interface.h"
# include "s1ap_eNB.h"
# include "sctp_eNB_task.h"
# include "gtpv1u_eNB_task.h"
# include "x2ap_eNB.h"
# include "x2ap_messages_types.h"
...
...
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