Skip to content

Commit

Permalink
amf-sim, gnb-cu-up, and ASN.1 CHOICE extensions (#186)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
nplrkn committed Apr 9, 2023
1 parent bcb4f4e commit a8a264f
Show file tree
Hide file tree
Showing 56 changed files with 3,000 additions and 690 deletions.
28 changes: 28 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

members = [
"asn1-per",
"amf-sim",
"common",
"sctp",
"net",
Expand All @@ -12,6 +13,7 @@ members = [
"rrc",
"pdcp",
"gnb-cu-cp",
"gnb-cu-up",
"connection-api",
"coordination-api",
"gnb-cu-cp-coordinator",
Expand Down
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,32 @@ The gNodeB is the component that manages the radio access of 5G User Equipment (
This project is currently a proof of concept and not yet a fully functional gNB-CU.

## Current support

- UE registration demo against free5GC.
- Session setup (TS 23.502, figure 4.3.2.2.1-1).
- UE state in Redis datastore.
- ASN.1 libraries for NGAP, E1AP, F1AP and RRC.
- Connection management stack
- Scale-out of GNB-CU-CP workers using multiple TNLAs.
- 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.
- [Triangular redirection](documentation/design/triangular-redirection.md)
- Rust ASN.1 autogenerator (written in Python).

The gNB-CU-UP does not exist yet.

The gNB-CU-UP is currently a simple stub that replies to E1AP requests but does not process userplane packets.
Generally only the success cases are covered, and there are a lot of 'To Dos'.
### Procedure support
- NG Setup
- RAN Configuration Update
- F1 Setup
- E1 Setup
- Initial Access
- Uplink NAS
- Downlink NAS
- Initial Context Setup
- Pdu Session Resource Setup (Bearer Context Setup)
- AMF Status Indication
- GNB CU Configuration Update
- GNB DU Configuration Update
- GNB CU CP Configuration Update.


## What's different about Alsoran?

Expand Down
Binary file added alsoran.pcap
Binary file not shown.
14 changes: 14 additions & 0 deletions amf-sim/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "amf-sim"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
mocks = { path = "../mocks" }
slog = "2.7.0"
anyhow = "1.0.52"
async-std = { version = "1.10.0", features = ["attributes"] }
common = { path = "../common" }
hex = "0.4.3"
65 changes: 65 additions & 0 deletions amf-sim/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// main - acts as an AMF for testing with O-RAN O-DU

use anyhow::Result;
use mocks::MockAmf;
use slog::info;

// 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.
// The required call flow is documented in full at `documentation/odu.md`.
#[async_std::main]
async fn main() -> Result<()> {
let logger = common::logging::init();
let mut amf = MockAmf::new(&logger).await;
amf.disable_receive_timeouts();

// Wait for connection and do NG Setup.
amf.add_endpoint("127.0.0.1").await?;
amf.expect_connection_established().await;
amf.handle_ng_setup().await?;

// Receive Ngap InitialUeMessage + Nas Registration Request
let ue = amf.receive_initial_ue_message(1).await?;
info!(&logger, ">> Registration request");

// Send Nas Authentication Request
info!(&logger, "<< Nas Authentication request");
let nas = hex::decode(
"7e005602020000217ac1c891b8aba0b2646e9cad34f4a0192010037859caf5e58000d58e09fc227bbf19",
)?;
amf.send_downlink_nas_transport(&ue, nas).await?;

// Receive Nas Authentication Response
let _nas = amf.receive_uplink_nas_transport(&ue).await?;
info!(&logger, ">> Nas Authentication Response");

// Send Nas Security Mode Command
info!(&logger, "<< Nas Security Mode Comamnd");
let nas = hex::decode("7e03e8e277e4007e005d010204f070f070e1360102")?;
amf.send_downlink_nas_transport(&ue, nas).await?;

// Receive Nas Security Mode Complete
let _nas = amf.receive_uplink_nas_transport(&ue).await?;
info!(&logger, ">> Nas Security Mode Complete");

// Send Ngap InitialContextSetupRequest + Nas Registration Accept
let nas = hex::decode("7e00420101")?;
amf.send_initial_context_setup_request(&ue, nas).await?;

// Receive Ngap InitialContextSetupResponse
amf.receive_initial_context_setup_response(&ue).await?;

// Send Nas Registration Accept
//info!(&logger, "<< Nas Registration Accept");
//amf.send_downlink_nas_transport(&ue, nas).await?;

// Receive Nas Registration Complete
let _nas = amf.receive_uplink_nas_transport(&ue).await?;
info!(&logger, ">> Nas Registration complete");

amf.send_pdu_session_resource_setup(&ue).await?;
amf.receive_pdu_session_resource_setup_response(&ue).await?;

amf.terminate().await;

Ok(())
}
2 changes: 1 addition & 1 deletion asn1-generator/asn1/f1ap/F1AP-PDU-Contents.asn
Original file line number Diff line number Diff line change
Expand Up @@ -1999,7 +1999,7 @@ InitialULRRCMessageTransferIEs F1AP-PROTOCOL-IES ::= {
{ ID id-RRCContainer CRITICALITY reject TYPE RRCContainer PRESENCE mandatory } |
{ ID id-DUtoCURRCContainer CRITICALITY reject TYPE DUtoCURRCContainer PRESENCE optional } |
{ ID id-SULAccessIndication CRITICALITY ignore TYPE SULAccessIndication PRESENCE optional } |
-- To work around bug in O-RAN ODU, we have transaction ID is set to optional here when it is actually mandatory
-- 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
{ ID id-TransactionID CRITICALITY ignore TYPE TransactionID PRESENCE optional --mandatory-- } |
{ ID id-RANUEID CRITICALITY ignore TYPE RANUEID PRESENCE optional } |
{ ID id-RRCContainer-RRCSetupComplete CRITICALITY ignore TYPE RRCContainer-RRCSetupComplete PRESENCE optional } ,
Expand Down
48 changes: 27 additions & 21 deletions asn1-generator/src/grammar.lark
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ _OID: /{[^}]+}/
//_OBJECT_CLASS: /\w+/
_IMPORTS: /[^;]+;/
extension_marker: "..." [","]
_size: "(" "SIZE" "(" _constraints ")" ")"
_constraints: _range_options+
_range_options: _range["|" _range] * [","]
_range: extension_marker | (BOUND [".." BOUND])
named_values: _nested_braces
_nested_braces: "{" (_nested_braces|/[^\{\}]+/) * "}"

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

_definitions: ( tuple_struct
| struct
_definitions: ( primitive_def
| sequence_def
| enum_def
| choice_def
| generic_choice_def
Expand All @@ -38,8 +44,8 @@ _definitions: ( tuple_struct
| top_level_enum_def
| class_instance)+
?assign: IDENTIFIER "::="
tuple_struct: assign _primitive
struct: assign sequence
primitive_def: assign _primitive
sequence_def: assign sequence
enum_def: assign enumerated
choice_def: assign choice
generic_choice_def: IDENTIFIER type_parameter "::=" choice
Expand All @@ -54,17 +60,19 @@ _bracketed_group{x}: ("[[" _comma_separated{x} "]]") | x

sequence_of: "SEQUENCE" [_size] "OF" (_field_type | single_ie_container)
sequence: "SEQUENCE" _items{_sequence_item}
_sequence_item: optional_field | field | extension_container | private_ie_container | ie_container | single_ie_container | (empty_sequence "OPTIONAL")
_sequence_item: optional_field | field | extension_container_field | private_ie_container_field | protocol_ies_field | single_ie_container | (empty_sequence_field "OPTIONAL")
optional_field.2: _identifier _field_type ("OPTIONAL" | "DEFAULT" _identifier)
field.1: _identifier _field_type

_empty_sequence.3: "SEQUENCE" "{}"
empty_sequence_field.1: _identifier _empty_sequence

enumerated.1: "ENUMERATED" _items{enum_field}
enum_field: _identifier

choice: "CHOICE" _items{_choice_item}
_choice_item: choice_field | choice_ie_container | choice_extension_container
_choice_item: choice_field | choice_field_ie_container | choice_field_ie_extension | empty_sequence_field
choice_field: _identifier _field_type
empty_sequence.3: _identifier "SEQUENCE" "{}"

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

ie_container.1: "protocolIEs" "ProtocolIE-Container" "{" "{" _identifier "}" "}"
choice_ie_container: _identifier "ProtocolIE-Container" "{" "{" _identifier "}" "}"
// XXAP IE and protocol containers
_protocol_ie_container: "ProtocolIE-Container" "{" "{" _identifier "}" "}"
single_ie_container.1: "ProtocolIE-SingleContainer" "{" "{" _identifier "}" "}"
_private_ie_container: "PrivateIE-Container" "{" "{" _identifier "}" "}" "OPTIONAL"? ","?
_extension_container: "ProtocolExtensionContainer" "{" "{" _identifier "}" "}" "OPTIONAL"? ","?

extension_container_field.0: _IDENTIFIER _extension_container
choice_field_ie_extension: _identifier single_ie_container
choice_field_ie_container: _identifier _protocol_ie_container
private_ie_container_field.0: _identifier _private_ie_container
protocol_ies_field.1: "protocolIEs" _protocol_ie_container

ies: "{" (ie | optional_ie)* [","] extension_marker? "}"
_ie{p}: "{" "ID" _identifier "CRITICALITY" _identifier ("TYPE" | "EXTENSION") _field_type+ "PRESENCE" p "}" ["|" | ","]
optional_ie: _ie{"optional"} | _ie{"conditional"}
ie: _ie{"mandatory"}

extension_container.0: _IDENTIFIER "ProtocolExtensionContainer" "{" "{" _identifier "}" "}" "OPTIONAL"? ","?
private_ie_container.0: _identifier "PrivateIE-Container" "{" "{" _identifier "}" "}" "OPTIONAL"? ","?
choice_extension_container: _identifier single_ie_container | empty_sequence

_size: "(" "SIZE" "(" _constraints ")" ")"
_constraints: _range_options+
_range_options: _range["|" _range] * [","]
_range: extension_marker | (BOUND [".." BOUND])

named_values: _nested_braces
_nested_braces: "{" (_nested_braces|/[^\{\}]+/) * "}"

// XXAP procedures
family: /\w*-ELEMENTARY-PROCEDURE/
procedure_def.2: procedure_name family "::=" "{" initiating successful? unsuccessful? procedure_code criticality "}"
procedure_name: IDENTIFIER
Expand Down
Loading

0 comments on commit a8a264f

Please sign in to comment.