Skip to content

Commit a8a264f

Browse files
authored
amf-sim, gnb-cu-up, and ASN.1 CHOICE extensions (#186)
* amf-sim executable * GNB-CU-UP executable * Terminate pending requests when connection dies * Add connection retry * Add BearerContextSetupProcedure and BearerContextModificationRequest * Add StateStore * Supply cell ID on UeContextSetupRequest * Fill in Drbs to setup item * Allow use of XXAP choice extensions * Form CuToDuRrcInformation correctly * BearerContextModificationRequest and CellGroupConfig
1 parent bcb4f4e commit a8a264f

56 files changed

Lines changed: 3000 additions & 690 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
members = [
44
"asn1-per",
5+
"amf-sim",
56
"common",
67
"sctp",
78
"net",
@@ -12,6 +13,7 @@ members = [
1213
"rrc",
1314
"pdcp",
1415
"gnb-cu-cp",
16+
"gnb-cu-up",
1517
"connection-api",
1618
"coordination-api",
1719
"gnb-cu-cp-coordinator",

README.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,32 @@ The gNodeB is the component that manages the radio access of 5G User Equipment (
77
This project is currently a proof of concept and not yet a fully functional gNB-CU.
88

99
## Current support
10-
1110
- UE registration demo against free5GC.
1211
- Session setup (TS 23.502, figure 4.3.2.2.1-1).
1312
- UE state in Redis datastore.
1413
- ASN.1 libraries for NGAP, E1AP, F1AP and RRC.
1514
- Connection management stack
1615
- Scale-out of GNB-CU-CP workers using multiple TNLAs.
17-
- Procedures: NG Setup, RAN Configuration Update, F1 Setup, E1 Setup, Initial Access, Uplink NAS, Downlink NAS, Initial Context Setup, Pdu Session Resource Setup, AMF Status Indication, GNB CU Configuration Update, GNB DU Configuration Update, GNB CU CP Configuration Update.
1816
- [Triangular redirection](documentation/design/triangular-redirection.md)
1917
- Rust ASN.1 autogenerator (written in Python).
2018

21-
The gNB-CU-UP does not exist yet.
22-
19+
The gNB-CU-UP is currently a simple stub that replies to E1AP requests but does not process userplane packets.
2320
Generally only the success cases are covered, and there are a lot of 'To Dos'.
21+
### Procedure support
22+
- NG Setup
23+
- RAN Configuration Update
24+
- F1 Setup
25+
- E1 Setup
26+
- Initial Access
27+
- Uplink NAS
28+
- Downlink NAS
29+
- Initial Context Setup
30+
- Pdu Session Resource Setup (Bearer Context Setup)
31+
- AMF Status Indication
32+
- GNB CU Configuration Update
33+
- GNB DU Configuration Update
34+
- GNB CU CP Configuration Update.
35+
2436

2537
## What's different about Alsoran?
2638

alsoran.pcap

5.04 KB
Binary file not shown.

amf-sim/Cargo.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "amf-sim"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
mocks = { path = "../mocks" }
10+
slog = "2.7.0"
11+
anyhow = "1.0.52"
12+
async-std = { version = "1.10.0", features = ["attributes"] }
13+
common = { path = "../common" }
14+
hex = "0.4.3"

amf-sim/src/main.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// main - acts as an AMF for testing with O-RAN O-DU
2+
3+
use anyhow::Result;
4+
use mocks::MockAmf;
5+
use slog::info;
6+
7+
// The purpose of this code is to cause Alsoran GNB-CU to produce the same message sequence as the O-RAN-SC O-DU Cu Stub.
8+
// The required call flow is documented in full at `documentation/odu.md`.
9+
#[async_std::main]
10+
async fn main() -> Result<()> {
11+
let logger = common::logging::init();
12+
let mut amf = MockAmf::new(&logger).await;
13+
amf.disable_receive_timeouts();
14+
15+
// Wait for connection and do NG Setup.
16+
amf.add_endpoint("127.0.0.1").await?;
17+
amf.expect_connection_established().await;
18+
amf.handle_ng_setup().await?;
19+
20+
// Receive Ngap InitialUeMessage + Nas Registration Request
21+
let ue = amf.receive_initial_ue_message(1).await?;
22+
info!(&logger, ">> Registration request");
23+
24+
// Send Nas Authentication Request
25+
info!(&logger, "<< Nas Authentication request");
26+
let nas = hex::decode(
27+
"7e005602020000217ac1c891b8aba0b2646e9cad34f4a0192010037859caf5e58000d58e09fc227bbf19",
28+
)?;
29+
amf.send_downlink_nas_transport(&ue, nas).await?;
30+
31+
// Receive Nas Authentication Response
32+
let _nas = amf.receive_uplink_nas_transport(&ue).await?;
33+
info!(&logger, ">> Nas Authentication Response");
34+
35+
// Send Nas Security Mode Command
36+
info!(&logger, "<< Nas Security Mode Comamnd");
37+
let nas = hex::decode("7e03e8e277e4007e005d010204f070f070e1360102")?;
38+
amf.send_downlink_nas_transport(&ue, nas).await?;
39+
40+
// Receive Nas Security Mode Complete
41+
let _nas = amf.receive_uplink_nas_transport(&ue).await?;
42+
info!(&logger, ">> Nas Security Mode Complete");
43+
44+
// Send Ngap InitialContextSetupRequest + Nas Registration Accept
45+
let nas = hex::decode("7e00420101")?;
46+
amf.send_initial_context_setup_request(&ue, nas).await?;
47+
48+
// Receive Ngap InitialContextSetupResponse
49+
amf.receive_initial_context_setup_response(&ue).await?;
50+
51+
// Send Nas Registration Accept
52+
//info!(&logger, "<< Nas Registration Accept");
53+
//amf.send_downlink_nas_transport(&ue, nas).await?;
54+
55+
// Receive Nas Registration Complete
56+
let _nas = amf.receive_uplink_nas_transport(&ue).await?;
57+
info!(&logger, ">> Nas Registration complete");
58+
59+
amf.send_pdu_session_resource_setup(&ue).await?;
60+
amf.receive_pdu_session_resource_setup_response(&ue).await?;
61+
62+
amf.terminate().await;
63+
64+
Ok(())
65+
}

asn1-generator/asn1/f1ap/F1AP-PDU-Contents.asn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1999,7 +1999,7 @@ InitialULRRCMessageTransferIEs F1AP-PROTOCOL-IES ::= {
19991999
{ ID id-RRCContainer CRITICALITY reject TYPE RRCContainer PRESENCE mandatory } |
20002000
{ ID id-DUtoCURRCContainer CRITICALITY reject TYPE DUtoCURRCContainer PRESENCE optional } |
20012001
{ ID id-SULAccessIndication CRITICALITY ignore TYPE SULAccessIndication PRESENCE optional } |
2002-
-- To work around bug in O-RAN ODU, we have transaction ID is set to optional here when it is actually mandatory
2002+
-- To work with rel 15 peers such as O-RAN-SC O-DU, transaction ID is set to optional here when it is actually defined as mandatory
20032003
{ ID id-TransactionID CRITICALITY ignore TYPE TransactionID PRESENCE optional --mandatory-- } |
20042004
{ ID id-RANUEID CRITICALITY ignore TYPE RANUEID PRESENCE optional } |
20052005
{ ID id-RRCContainer-RRCSetupComplete CRITICALITY ignore TYPE RRCContainer-RRCSetupComplete PRESENCE optional } ,

asn1-generator/src/grammar.lark

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ _OID: /{[^}]+}/
1717
//_OBJECT_CLASS: /\w+/
1818
_IMPORTS: /[^;]+;/
1919
extension_marker: "..." [","]
20+
_size: "(" "SIZE" "(" _constraints ")" ")"
21+
_constraints: _range_options+
22+
_range_options: _range["|" _range] * [","]
23+
_range: extension_marker | (BOUND [".." BOUND])
24+
named_values: _nested_braces
25+
_nested_braces: "{" (_nested_braces|/[^\{\}]+/) * "}"
2026

2127
// For testability, we make the parts before and after the definitions optional
2228
// This means we can just run small fragments through the grammar.
@@ -26,8 +32,8 @@ _fragment: _definitions
2632
module_name: IDENTIFIER
2733
_begin: "DEFINITIONS AUTOMATIC TAGS ::=" "BEGIN"
2834

29-
_definitions: ( tuple_struct
30-
| struct
35+
_definitions: ( primitive_def
36+
| sequence_def
3137
| enum_def
3238
| choice_def
3339
| generic_choice_def
@@ -38,8 +44,8 @@ _definitions: ( tuple_struct
3844
| top_level_enum_def
3945
| class_instance)+
4046
?assign: IDENTIFIER "::="
41-
tuple_struct: assign _primitive
42-
struct: assign sequence
47+
primitive_def: assign _primitive
48+
sequence_def: assign sequence
4349
enum_def: assign enumerated
4450
choice_def: assign choice
4551
generic_choice_def: IDENTIFIER type_parameter "::=" choice
@@ -54,17 +60,19 @@ _bracketed_group{x}: ("[[" _comma_separated{x} "]]") | x
5460

5561
sequence_of: "SEQUENCE" [_size] "OF" (_field_type | single_ie_container)
5662
sequence: "SEQUENCE" _items{_sequence_item}
57-
_sequence_item: optional_field | field | extension_container | private_ie_container | ie_container | single_ie_container | (empty_sequence "OPTIONAL")
63+
_sequence_item: optional_field | field | extension_container_field | private_ie_container_field | protocol_ies_field | single_ie_container | (empty_sequence_field "OPTIONAL")
5864
optional_field.2: _identifier _field_type ("OPTIONAL" | "DEFAULT" _identifier)
5965
field.1: _identifier _field_type
6066

67+
_empty_sequence.3: "SEQUENCE" "{}"
68+
empty_sequence_field.1: _identifier _empty_sequence
69+
6170
enumerated.1: "ENUMERATED" _items{enum_field}
6271
enum_field: _identifier
6372

6473
choice: "CHOICE" _items{_choice_item}
65-
_choice_item: choice_field | choice_ie_container | choice_extension_container
74+
_choice_item: choice_field | choice_field_ie_container | choice_field_ie_extension | empty_sequence_field
6675
choice_field: _identifier _field_type
67-
empty_sequence.3: _identifier "SEQUENCE" "{}"
6876

6977
integer: "INTEGER" named_values? ["(" _constraints ")"]
7078
printable_string: "PrintableString" [_size]
@@ -92,26 +100,24 @@ _field_type: _primitive | enumerated | sequence | choice
92100
type_parameter: "{" _identifier "}"
93101
type_parameterized_identifier: _identifier type_parameter
94102

95-
ie_container.1: "protocolIEs" "ProtocolIE-Container" "{" "{" _identifier "}" "}"
96-
choice_ie_container: _identifier "ProtocolIE-Container" "{" "{" _identifier "}" "}"
103+
// XXAP IE and protocol containers
104+
_protocol_ie_container: "ProtocolIE-Container" "{" "{" _identifier "}" "}"
97105
single_ie_container.1: "ProtocolIE-SingleContainer" "{" "{" _identifier "}" "}"
106+
_private_ie_container: "PrivateIE-Container" "{" "{" _identifier "}" "}" "OPTIONAL"? ","?
107+
_extension_container: "ProtocolExtensionContainer" "{" "{" _identifier "}" "}" "OPTIONAL"? ","?
108+
109+
extension_container_field.0: _IDENTIFIER _extension_container
110+
choice_field_ie_extension: _identifier single_ie_container
111+
choice_field_ie_container: _identifier _protocol_ie_container
112+
private_ie_container_field.0: _identifier _private_ie_container
113+
protocol_ies_field.1: "protocolIEs" _protocol_ie_container
114+
98115
ies: "{" (ie | optional_ie)* [","] extension_marker? "}"
99116
_ie{p}: "{" "ID" _identifier "CRITICALITY" _identifier ("TYPE" | "EXTENSION") _field_type+ "PRESENCE" p "}" ["|" | ","]
100117
optional_ie: _ie{"optional"} | _ie{"conditional"}
101118
ie: _ie{"mandatory"}
102119

103-
extension_container.0: _IDENTIFIER "ProtocolExtensionContainer" "{" "{" _identifier "}" "}" "OPTIONAL"? ","?
104-
private_ie_container.0: _identifier "PrivateIE-Container" "{" "{" _identifier "}" "}" "OPTIONAL"? ","?
105-
choice_extension_container: _identifier single_ie_container | empty_sequence
106-
107-
_size: "(" "SIZE" "(" _constraints ")" ")"
108-
_constraints: _range_options+
109-
_range_options: _range["|" _range] * [","]
110-
_range: extension_marker | (BOUND [".." BOUND])
111-
112-
named_values: _nested_braces
113-
_nested_braces: "{" (_nested_braces|/[^\{\}]+/) * "}"
114-
120+
// XXAP procedures
115121
family: /\w*-ELEMENTARY-PROCEDURE/
116122
procedure_def.2: procedure_name family "::=" "{" initiating successful? unsuccessful? procedure_code criticality "}"
117123
procedure_name: IDENTIFIER

0 commit comments

Comments
 (0)