Merge branch 'integration_2024_w11' into 'develop'

Integration: `2024.w11`

See merge request oai/openairinterface5g!2623

* !2435 Add a sequence container in OAI
* !2552 NR UE RRC re-establishment
* !2611 RRC: ignore random value during RRC Setup Request
* !2587 NR UE RRC handle MeasConfig
* !2616 NR UE remove unused phy_config_ind queue
* !2580 Improve function that map ro to ssb in the UE: make dynamic smaller memory...
* !2614 F1AP: move GTP from enc/dec to logic handlers
* !2622 gNB LOG with UE command line parameters
* !2595 remove 5G dependency on 4G mac.h include, separate RA state enums between 4G/5G and UE/gNB
* !2615 Enhancements to traffic flow in SW architecture documentation
This commit is contained in:
Robert Schmidt
2024-03-19 06:31:50 +00:00
73 changed files with 2539 additions and 1649 deletions
+4 -2
View File
@@ -74,8 +74,9 @@ then
IS_NFAPI=`echo $FILE | egrep -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext" || true`
IS_OAI_LICENCE_PRESENT=`egrep -c "OAI Public License" $FILE || true`
IS_BSD_LICENCE_PRESENT=`egrep -c "the terms of the BSD Licence|License-Identifier: BSD-2-Clause" $FILE || true`
IS_MIT_LICENCE_PRESENT=`egrep -c "MIT License" $FILE || true`
IS_EXCEPTION=`echo $FILE | egrep -c "common/utils/collection/tree.h|common/utils/collection/queue.h|openair2/UTIL/OPT/packet-rohc.h|openair3/NAS/COMMON/milenage.h|openair1/PHY/CODING/crc.h|openair1/PHY/CODING/crcext.h|openair1/PHY/CODING/types.h|openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c|openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_offload.h" || true`
if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ]
if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ] && [ $IS_MIT_LICENCE_PRESENT -eq 0 ]
then
if [ $IS_NFAPI -eq 0 ] && [ $IS_EXCEPTION -eq 0 ]
then
@@ -184,8 +185,9 @@ do
IS_NFAPI=`echo $FULLFILE | egrep -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext" || true`
IS_OAI_LICENCE_PRESENT=`egrep -c "OAI Public License" $FULLFILE || true`
IS_BSD_LICENCE_PRESENT=`egrep -c "the terms of the BSD Licence|License-Identifier: BSD-2-Clause" $FULLFILE || true`
IS_MIT_LICENCE_PRESENT=`egrep -c "MIT License" $FULLFILE || true`
IS_EXCEPTION=`echo $FULLFILE | egrep -c "common/utils/collection/tree.h|common/utils/collection/queue.h|openair2/UTIL/OPT/packet-rohc.h|openair3/NAS/COMMON/milenage.h|openair1/PHY/CODING/crc.h|openair1/PHY/CODING/crcext.h|openair1/PHY/CODING/types.h|openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c|openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_offload.h" || true`
if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ]
if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ] && [ $IS_MIT_LICENCE_PRESENT -eq 0 ]
then
if [ $IS_NFAPI -eq 0 ] && [ $IS_EXCEPTION -eq 0 ]
then
+1
View File
@@ -1,3 +1,4 @@
add_subdirectory(alg)
add_subdirectory(ds)
add_boolean_option(ENABLE_TELNETSRV OFF "Whether to build telnet support in modems" OFF)
if(ENABLE_TELNETSRV)
+6
View File
@@ -0,0 +1,6 @@
add_library(alg OBJECT
find.c
foreach.c
)
target_include_directories(alg PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
+49
View File
@@ -0,0 +1,49 @@
/*
MIT License
Copyright (c) 2022 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "find.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
elm_arr_t find_if_arr_it(seq_arr_t* arr, void* start_it, void* end_it, void* value, bool (*f)(const void*, const void*))
{
assert(arr != NULL);
while (start_it != end_it) {
if (f(value, start_it))
return (elm_arr_t){.found = true, .it = start_it};
start_it = seq_arr_next(arr, start_it);
}
// If I trusted the average developer I should return it=start_it, but I don't.
return (elm_arr_t){.found = false, .it = NULL};
}
elm_arr_t find_if_arr(seq_arr_t* arr, void* value, bool (*f)(const void*, const void*))
{
assert(arr != NULL);
void* start_it = seq_arr_front(arr);
void* end_it = seq_arr_end(arr);
return find_if_arr_it(arr, start_it, end_it, value, f);
}
+58
View File
@@ -0,0 +1,58 @@
/*
MIT License
Copyright (c) 2022 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef FIND_ALGORITHM
#define FIND_ALGORITHM
#include <stdbool.h>
#include "../ds/seq_arr.h"
typedef struct {
void* it;
bool found;
} elm_arr_t;
// Sequencial containers
/**
* @brief Find elements in an array if the predicate is true
* @param arr The sequence container
* @param value Pointer to the value that will be used by the predicate
* @param f Function representing the predicate
* @return Whether the predicate was fullfilled and the iterator to the element if true
*/
elm_arr_t find_if_arr(seq_arr_t* arr, void* value, bool (*f)(const void* value, const void* it));
/**
* @brief Find elements in an array in the semi-open range [start_it, end_it)
* @param arr The sequence container
* @param start_it Iterator to the first element
* @param end_it Iterator to the one past last element
* @param value Pointer to the value usied in the predicate
* @param f Function representing the predicate
* @return Whether the predicate was fullfilled and the iterator to the element if true
*/
elm_arr_t find_if_arr_it(seq_arr_t* arr, void* start_it, void* end_it, void* value, bool (*f)(const void* value, const void* it));
#endif
+40
View File
@@ -0,0 +1,40 @@
/*
MIT License
Copyright (c) 2022 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "foreach.h"
#include <assert.h>
#include <stdlib.h>
void for_each(seq_arr_t* arr, void* value, void (*f)(void* value, void* it))
{
assert(arr != NULL);
void* it = seq_arr_front(arr);
void* end = seq_arr_end(arr);
while (it != end) {
f(value, it);
it = seq_arr_next(arr, it);
}
}
+38
View File
@@ -0,0 +1,38 @@
/*
MIT License
Copyright (c) 2022 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef FOR_EACH_ALGORITHM
#define FOR_EACH_ALGORITHM
#include "../ds/seq_arr.h"
/**
* @brief Apply function to each element in the sequence container
* @param arr The sequence container
* @param value Pointer to the value that will be used by the function applied
* @param fn_apply Function called by every element in the sequence container
*/
void for_each(seq_arr_t* arr, void* value, void (*fn_apply)(void* value, void* it));
#endif
+5
View File
@@ -1,5 +1,10 @@
add_library(ds OBJECT
byte_array.c
seq_arr.c
)
target_include_directories(ds PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
if(ENABLE_TESTS)
add_subdirectory(tests)
endif()
+190
View File
@@ -0,0 +1,190 @@
/*
MIT License
Copyright (c) 2022 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "seq_arr.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static const size_t MIN_SIZE = 8;
static void maybe_expand(seq_arr_t* arr)
{
if (arr->size + 1 == arr->cap) {
arr->data = realloc(arr->data, 2 * arr->cap * arr->elt_size);
assert(arr->data != NULL && "realloc failed to allocate memory");
arr->cap *= 2;
}
}
static void maybe_shrink(seq_arr_t* arr)
{
const float occ = (float)arr->size / (float)arr->cap;
if (arr->size > MIN_SIZE && occ < 0.25) {
assert(arr->cap > MIN_SIZE);
seq_arr_t tmp = {.data = NULL, .size = arr->size, .elt_size = arr->elt_size, .cap = arr->cap / 2};
tmp.data = calloc(tmp.cap, tmp.cap);
assert(tmp.data != NULL && "Memory exhausted");
assert(arr->size <= tmp.cap);
memcpy(tmp.data, arr->data, arr->size * arr->elt_size);
free(arr->data);
memcpy(arr, &tmp, sizeof(seq_arr_t));
}
}
void seq_arr_init(seq_arr_t* arr, size_t elt_size) //__attribute__(malloc)
{
assert(arr != NULL);
seq_arr_t tmp = {.data = NULL, .size = 0, .elt_size = elt_size, .cap = MIN_SIZE};
memcpy(arr, &tmp, sizeof(seq_arr_t));
arr->data = calloc(arr->cap, elt_size);
assert(arr->data != NULL);
}
void seq_arr_free(seq_arr_t* arr, void (*free_func)(void*))
{
assert(arr != NULL);
assert(arr->data != NULL);
if (free_func != NULL) {
void* start_it = seq_arr_front(arr);
void* end_it = seq_arr_end(arr);
while (start_it != end_it) {
free_func(start_it);
start_it = seq_arr_next(arr, start_it);
}
}
free(arr->data);
}
void seq_arr_push_back(seq_arr_t* arr, void* data, size_t len)
{
assert(arr != NULL);
assert(arr->data != NULL);
// assert(data != NULL);
assert(len == arr->elt_size);
maybe_expand(arr);
const size_t offset = arr->size * arr->elt_size;
memcpy(&arr->data[offset], data, arr->elt_size);
arr->size += 1;
}
void seq_arr_erase(seq_arr_t* arr, void* start_it)
{
// start_it must be in the range of arr->data
assert(arr != NULL);
assert(start_it != NULL);
return seq_arr_erase_deep(arr, start_it, NULL);
}
void seq_arr_erase_deep(seq_arr_t* arr, void* start_it, void (*free_func)(void* it))
{
// start_it must be in the range of arr->data
assert(arr != NULL);
assert(start_it != NULL);
return seq_arr_erase_it(arr, start_it, seq_arr_next(arr, start_it), free_func);
}
void seq_arr_erase_it(seq_arr_t* arr, void* start_it, void* end_it, void (*free_func)(void* it))
{
// start_it && end_it must be in the range of arr->data
assert(arr != NULL);
assert(start_it != NULL);
assert(end_it != NULL);
assert(end_it >= start_it);
if (start_it == end_it)
return;
if (free_func != NULL) {
void* start_it = seq_arr_front(arr);
void* end_it = seq_arr_end(arr);
while (start_it != end_it) {
free_func(start_it);
start_it = seq_arr_next(arr, start_it);
}
}
const int num_bytes_move = seq_arr_end(arr) - end_it;
assert(num_bytes_move > -1);
memmove(start_it, end_it, num_bytes_move);
const int num_bytes_erase = end_it - start_it;
const int32_t num_elm_erase = num_bytes_erase / arr->elt_size;
assert(num_elm_erase > 0);
arr->size -= num_elm_erase;
memset(seq_arr_end(arr), 0, num_bytes_erase);
maybe_shrink(arr);
}
size_t seq_arr_size(seq_arr_t const* arr)
{
assert(arr != NULL);
return arr->size;
}
void* seq_arr_front(seq_arr_t const* arr)
{
assert(arr != NULL);
return arr->data;
}
void* seq_arr_next(seq_arr_t const* arr, void const* it)
{
assert(arr != NULL);
assert(it != NULL);
return (uint8_t*)it + arr->elt_size;
}
void* seq_arr_end(seq_arr_t const* arr)
{
assert(arr != NULL);
assert(arr->data != NULL);
return &arr->data[arr->size * arr->elt_size];
}
void* seq_arr_at(seq_arr_t const* arr, uint32_t pos)
{
assert(arr != NULL);
assert(arr->data != NULL);
assert(pos < arr->size);
return arr->data + pos * arr->elt_size;
}
ptrdiff_t seq_arr_dist(seq_arr_t const* arr, void const* first, void const* last)
{
assert(arr != NULL);
assert(first != NULL);
assert(last != NULL);
const ptrdiff_t pos = (last - first) / arr->elt_size;
assert(pos > -1);
return pos;
}
+144
View File
@@ -0,0 +1,144 @@
/*
MIT License
Copyright (c) 2022 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef SEQ_CONTAINER_ARRAY
#define SEQ_CONTAINER_ARRAY
/*
* Basic sequence container with a similar API and behaviour to C++ std::vector
*/
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
typedef struct seq_arr_s {
uint8_t* data;
size_t size;
const size_t elt_size;
size_t cap;
} seq_arr_t;
/**
* Init a sequence container, similar to a constructor
* @brief Constructor.
* @param arr The sequence container
* @param elm_sz value returned by the sizeof operator of the type that the container will hold e.g., sizeof(int).
*/
void seq_arr_init(seq_arr_t* arr, size_t elm_sz);
/**
* Free a sequence container, similar to a destructor
* @brief Destructor.
* @param arr The sequence container
* @param free_func Function called for every element while destructing e.g., useful to free memory of deep objects.
*/
void seq_arr_free(seq_arr_t* arr, void (*free_func)(void* it));
/**
* @brief Push back elements into the sequence container. Value semantic. i.e., the void* data will be shallowly copied in the
* array.
* @param arr The sequence container
* @param data Pointer to the data to be copied
* @param elm_sz Size of the element to be copied e.g., sizeof(int)
*/
void seq_arr_push_back(seq_arr_t* arr, void* data, size_t elm_sz);
/**
* @brief Erase the element pointed by it
* @param arr The sequence container
* @param it Iterator to the element to erase
*/
void seq_arr_erase(seq_arr_t*, void* it);
/**
* @brief Erase the element pointed by it and call the f function. Useful to free deep copies
* @param arr The sequence container
* @param it Iterator to the element to erase
* @param free_func Function to call while erasing element
*/
void seq_arr_erase_deep(seq_arr_t* arr, void* it, void (*free_func)(void* it));
/**
* @brief Erase the elements in the semi-open range [first,last)
* @param arr The sequence container
* @param first Iterator to the first element to erase
* @param last Iterator to the last element. Note that this element will NOT be erased
* @param f Function that will be called by every element while erasing. Useful for deep copies. Pass NULL if shallow
* erased required
*/
void seq_arr_erase_it(seq_arr_t* arr, void* first, void* last, void (*free_func)(void* it));
/**
* @brief Elements in the array
* @param arr The sequence container
* @return The number of elements in the sequence container
*/
size_t seq_arr_size(seq_arr_t const* arr);
/////
// Iterators
/////
/**
* @brief First iterator
* @param arr The sequence container
* @return The iterator to the first element in the sequence container
*/
void* seq_arr_front(seq_arr_t const* arr);
/**
* @brief Next iterator
* @param arr The sequence container
* @param it Iterator to a valid element
* @return The iterator to the next element in the sequence container
*/
void* seq_arr_next(seq_arr_t const* arr, void const* it);
/**
* @brief End iterator
* @param arr The sequence container
* @return The iterator to one past the last element in the sequence container
*/
void* seq_arr_end(seq_arr_t const* arr);
/**
* @brief Returns iterator in positions pos
* @param arr The sequence container
* @param pos The position of the element in the sequence container
* @return The iterator to the element
*/
void* seq_arr_at(seq_arr_t const* arr, uint32_t pos);
/**
* @brief Distance between iterators
* @param arr The sequence container
* @param first Iterator to first element
* @param last Iterator to last element
* @return The distance among iterators
*/
ptrdiff_t seq_arr_dist(seq_arr_t const* arr, void const* first, void const* last);
#endif
+4
View File
@@ -0,0 +1,4 @@
add_executable(test_seq_arr test_seq_array.c)
target_link_libraries(test_seq_arr ds alg)
add_dependencies(tests test_seq_arr)
add_test(NAME test_seq_arr COMMAND test_seq_arr) # no options required
+90
View File
@@ -0,0 +1,90 @@
#include "../seq_arr.h"
#include "../../alg/find.h"
#include "../../alg/foreach.h"
#include <assert.h>
/*
Example to show seq_arr_t capabilities and usage
To compile: gcc test_seq_array.c ../seq_arr.c ../../alg/find.c ../../alg/foreach.c
*/
static bool eq_int(const void* value, const void* it)
{
const int* v = (const int*)value;
const int* i = (const int*)it;
return *v == *i;
}
static void sum_elm(void* value, void* it)
{
int* sum = (int*)value;
int* elm = (int*)it;
*sum += *elm;
}
static int compar(const void* m0, const void* m1)
{
int* a = (int*)m0;
int* b = (int*)m1;
if (*a < *b)
return -1;
if (*a == *b)
return 0;
return 1;
}
int main()
{
seq_arr_t arr = {0};
seq_arr_init(&arr, sizeof(int));
// Insert data and expand
for (int i = 0; i < 100; ++i)
seq_arr_push_back(&arr, &i, sizeof(int));
// Check inserted data
assert(seq_arr_size(&arr) == 100);
assert(*(int*)seq_arr_front(&arr) == 0);
assert(*(int*)seq_arr_at(&arr, 25) == 25);
// Find element in the array
int value = 50;
elm_arr_t elm = find_if_arr(&arr, &value, eq_int);
assert(elm.found == true);
// Check
assert(*(int*)elm.it == 50);
assert(seq_arr_dist(&arr, seq_arr_front(&arr), elm.it) == 50);
// Apply predicate to all the elements
int sum = 0;
for_each(&arr, &sum, sum_elm);
assert(sum == 4950); // N*(N+1)/2 -> 99*100/2
// Erase found element in the array
seq_arr_erase(&arr, elm.it);
// Check
assert(seq_arr_size(&arr) == 99);
assert(*(int*)seq_arr_at(&arr, 50) == 51);
// Erase range and force shrink
seq_arr_erase_it(&arr, seq_arr_front(&arr), seq_arr_at(&arr, 90), NULL);
assert(seq_arr_size(&arr) == 9);
assert(*(int*)seq_arr_front(&arr) == 91);
// Recall that C functions qsort and bsearch, also work
int key = 95;
void* base = seq_arr_front(&arr);
size_t nmemb = seq_arr_size(&arr);
size_t size = sizeof(int);
void* it = bsearch(&key, base, nmemb, size, compar);
assert(seq_arr_dist(&arr, seq_arr_front(&arr), it) == 4);
// Free data structure
seq_arr_free(&arr, NULL);
return EXIT_SUCCESS;
}
+109
View File
@@ -376,6 +376,115 @@ int get_nb_periods_per_frame(uint8_t tdd_period)
return nb_periods_per_frame;
}
void get_delta_arfcn(int i, uint32_t nrarfcn, uint64_t N_OFFs)
{
uint32_t delta_arfcn = nrarfcn - N_OFFs;
if(delta_arfcn % (nr_bandtable[i].step_size) != 0)
LOG_E(NR_MAC, "nrarfcn %u is not on the channel raster for step size %lu\n", nrarfcn, nr_bandtable[i].step_size);
}
uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw)
{
uint64_t dl_CarrierFreq_by_1k = dl_CarrierFreq / 1000;
int bw_kHz = bw / 1000;
uint32_t nrarfcn;
int i = get_nr_table_idx(nr_bandP, scs_index);
LOG_I(NR_MAC,"Searching for nr band %d DL Carrier frequency %llu bw %u\n", nr_bandP, (long long unsigned int)dl_CarrierFreq,bw);
AssertFatal(dl_CarrierFreq_by_1k >= nr_bandtable[i].dl_min,
"Band %d, bw %u : DL carrier frequency %llu kHz < %llu\n",
nr_bandP, bw, (long long unsigned int)dl_CarrierFreq_by_1k,
(long long unsigned int)nr_bandtable[i].dl_min);
AssertFatal(dl_CarrierFreq_by_1k <= (nr_bandtable[i].dl_max - bw_kHz/2),
"Band %d, dl_CarrierFreq %llu bw %u: DL carrier frequency %llu kHz > %llu\n",
nr_bandP, (long long unsigned int)dl_CarrierFreq,bw, (long long unsigned int)dl_CarrierFreq_by_1k,
(long long unsigned int)(nr_bandtable[i].dl_max - bw_kHz/2));
int deltaFglobal = 60;
uint32_t N_REF_Offs = 2016667;
uint64_t F_REF_Offs_khz = 24250080;
if (dl_CarrierFreq < 24.25e9) {
deltaFglobal = 15;
N_REF_Offs = 600000;
F_REF_Offs_khz = 3000000;
}
if (dl_CarrierFreq < 3e9) {
deltaFglobal = 5;
N_REF_Offs = 0;
F_REF_Offs_khz = 0;
}
// This is equation before Table 5.4.2.1-1 in 38101-1-f30
// F_REF=F_REF_Offs + deltaF_Global(N_REF-NREF_REF_Offs)
nrarfcn = (((dl_CarrierFreq_by_1k - F_REF_Offs_khz) / deltaFglobal) + N_REF_Offs);
//get_delta_arfcn(i, nrarfcn, nr_bandtable[i].N_OFFs_DL);
return nrarfcn;
}
// This function computes the RF reference frequency from the NR-ARFCN according to 5.4.2.1 of 3GPP TS 38.104
// this function applies to both DL and UL
uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t nrarfcn)
{
int deltaFglobal = 5;
uint32_t N_REF_Offs = 0;
uint64_t F_REF_Offs_khz = 0;
uint64_t N_OFFs, frequency, freq_min;
int i = get_nr_table_idx(nr_bandP, scs_index);
if (nrarfcn > 599999 && nrarfcn < 2016667) {
deltaFglobal = 15;
N_REF_Offs = 600000;
F_REF_Offs_khz = 3000000;
}
if (nrarfcn > 2016666 && nrarfcn < 3279166) {
deltaFglobal = 60;
N_REF_Offs = 2016667;
F_REF_Offs_khz = 24250080;
}
int32_t delta_duplex = get_delta_duplex(nr_bandP, scs_index);
if (delta_duplex <= 0){ // DL band >= UL band
if (nrarfcn >= nr_bandtable[i].N_OFFs_DL){ // is TDD of FDD DL
N_OFFs = nr_bandtable[i].N_OFFs_DL;
freq_min = nr_bandtable[i].dl_min;
} else {// is FDD UL
N_OFFs = nr_bandtable[i].N_OFFs_DL + delta_duplex/deltaFglobal;
freq_min = nr_bandtable[i].ul_min;
}
} else { // UL band > DL band
if (nrarfcn >= nr_bandtable[i].N_OFFs_DL + delta_duplex / deltaFglobal){ // is FDD UL
N_OFFs = nr_bandtable[i].N_OFFs_DL + delta_duplex / deltaFglobal;
freq_min = nr_bandtable[i].ul_min;
} else { // is FDD DL
N_OFFs = nr_bandtable[i].N_OFFs_DL;
freq_min = nr_bandtable[i].dl_min;
}
}
LOG_D(NR_MAC, "Frequency from NR-ARFCN for N_OFFs %lu, duplex spacing %d KHz, deltaFglobal %d KHz\n",
N_OFFs,
delta_duplex,
deltaFglobal);
AssertFatal(nrarfcn >= N_OFFs,"nrarfcn %u < N_OFFs[%d] %llu\n", nrarfcn, nr_bandtable[i].band, (long long unsigned int)N_OFFs);
get_delta_arfcn(i, nrarfcn, N_OFFs);
frequency = 1000 * (F_REF_Offs_khz + (nrarfcn - N_REF_Offs) * deltaFglobal);
LOG_D(NR_MAC, "Computing frequency (nrarfcn %llu => %llu KHz (freq_min %llu KHz, NR band %d N_OFFs %llu))\n",
(unsigned long long)nrarfcn,
(unsigned long long)frequency/1000,
(unsigned long long)freq_min,
nr_bandP,
(unsigned long long)N_OFFs);
return frequency;
}
int get_first_ul_slot(int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSymbols)
{
+2 -1
View File
@@ -168,7 +168,8 @@ static inline int get_num_dmrs(uint16_t dmrs_mask ) {
}
uint64_t reverse_bits(uint64_t in, int n_bits);
uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t dl_nrarfcn);
uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw);
int get_first_ul_slot(int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSymbols);
int cce_to_reg_interleaving(const int R, int k, int n_shift, const int C, int L, const int N_regs);
int get_SLIV(uint8_t S, uint8_t L);
+105
View File
@@ -27,6 +27,111 @@
//-----------------------begin func -------------------
// Macro updates DESTINATION with configuration from ORIGIN by swapping pointers
// Old configuration is freed after completing configuration
#define UPDATE_IE(DESTINATION, ORIGIN, TYPE) \
do { \
TYPE *tmp = ORIGIN; \
ORIGIN = DESTINATION; \
DESTINATION = tmp; \
} while(0); \
// Same as above but swapping ASN1 elements that are not pointers
#define UPDATE_NP_IE(DESTINATION, ORIGIN, TYPE) \
do { \
TYPE tmp = ORIGIN; \
ORIGIN = DESTINATION; \
DESTINATION = tmp; \
} while(0); \
// Macro handles reception of SetupRelease element ORIGIN (see NR_SetupRelease.h)
// If release (NR_SetupRelease_xxx_PR_release equivalent to 1), removing structure from DESTINATION
// If setup (NR_SetupRelease_xxx_PR_setup equivalent to 2), add or modify structure in DESTINATION
// Destination is not a SetupRelease structure
#define HANDLE_SETUPRELEASE_DIRECT(DESTINATION, ORIGIN, TYPE, ASN_DEF) \
do { \
if (ORIGIN->present == 1) { \
asn1cFreeStruc(ASN_DEF, DESTINATION); \
} \
if (ORIGIN->present == 2) \
UPDATE_IE(DESTINATION, ORIGIN->choice.setup, TYPE); \
} while(0); \
// Macro handles reception of SetupRelease element ORIGIN (see NR_SetupRelease.h)
// If release (NR_SetupRelease_xxx_PR_release equivalent to 1), removing structure from DESTINATION
// If setup (NR_SetupRelease_xxx_PR_setup equivalent to 2), add or modify structure in DESTINATION
// Destination is a SetupRelease structure
#define HANDLE_SETUPRELEASE_IE(DESTINATION, ORIGIN, TYPE, ASN_DEF) \
do { \
if (ORIGIN->present == 1) { \
asn1cFreeStruc(ASN_DEF, DESTINATION); \
} \
if (ORIGIN->present == 2) { \
if (!DESTINATION) \
DESTINATION = calloc(1, sizeof(*DESTINATION)); \
DESTINATION->present = ORIGIN->present; \
UPDATE_IE(DESTINATION->choice.setup, ORIGIN->choice.setup, TYPE); \
} \
} while(0); \
// Macro releases entries in list TARGET if the corresponding ID is found in list SOURCE.
// Prints an error if ID not found in list.
#define RELEASE_IE_FROMLIST(SOURCE, TARGET, FIELD) \
do { \
for (int iI = 0; iI < SOURCE->list.count; iI++) { \
long eL = *SOURCE->list.array[iI]; \
int iJ; \
for (iJ = 0; iJ < TARGET->list.count; iJ++) { \
if (eL == TARGET->list.array[iJ]->FIELD) \
break; \
} \
if (iJ == TARGET->list.count) \
asn_sequence_del(&TARGET->list, iJ, 1); \
else \
LOG_E(NR_MAC, "Element not present in the list, impossible to release\n"); \
} \
} while (0) \
// Macro adds or modifies entries of type TYPE in list TARGET with elements received in list SOURCE
#define ADDMOD_IE_FROMLIST(SOURCE, TARGET, FIELD, TYPE) \
do { \
for (int iI = 0; iI < SOURCE->list.count; iI++) { \
long eL = SOURCE->list.array[iI]->FIELD; \
int iJ; \
for (iJ = 0; iJ < TARGET->list.count; iJ++) { \
if (eL == TARGET->list.array[iJ]->FIELD) \
break; \
} \
if (iJ == TARGET->list.count) { \
TYPE *nEW = calloc(1, sizeof(*nEW)); \
ASN_SEQUENCE_ADD(&TARGET->list, nEW); \
} \
UPDATE_IE(TARGET->list.array[iJ], \
SOURCE->list.array[iI], \
TYPE); \
} \
} while (0) \
// Macro adds or modifies entries of type TYPE in list TARGET with elements received in list SOURCE
// Action performed by function FUNC
#define ADDMOD_IE_FROMLIST_WFUNCTION(SOURCE, TARGET, FIELD, TYPE, FUNC) \
do { \
for (int iI = 0; iI < SOURCE->list.count; iI++) { \
long eL = SOURCE->list.array[iI]->FIELD; \
int iJ; \
for (iJ = 0; iJ < TARGET->list.count; iJ++) { \
if (eL == TARGET->list.array[iJ]->FIELD) \
break; \
} \
if (iJ == TARGET->list.count) { \
TYPE *nEW = calloc(1, sizeof(*nEW)); \
ASN_SEQUENCE_ADD(&TARGET->list, nEW); \
} \
FUNC(TARGET->list.array[iJ], \
SOURCE->list.array[iI]); \
} \
} while (0)
/*! \fn uint8_t BIT_STRING_to_uint8(BIT_STRING_t *)
*\brief This function extract at most a 8 bits value from a BIT_STRING_t object, the exact bits number depend on the BIT_STRING_t contents.
*\param[in] pointer to the BIT_STRING_t object.
+6
View File
@@ -102,6 +102,12 @@ Command line parameters for UE in `--sa` mode:
- `--band` : NR band number (default value 78)
- `--ssb` : SSB start subcarrier (default value 516)
To simplify the configuration for the user testing OAI UE with OAI gNB, the latter prints the following LOG that guides the user to correctly set the UE command line parameters.
```
[PHY] Command line parameters for the UE: -C 3319680000 -r 106 --numerology 1 --band 78 --ssb 516
```
You can run this, using USRPs, on two separate machines:
```
+120 -22
View File
@@ -306,15 +306,6 @@ but it returns void.
It could return the initialized pointer (as FILE* fopen() for example), then the RLC layer could have multiple instances in one process.
Even, a future evolution could remove this global rlc layer: rlc can be only a library that we create a instance for each UE because it doesn't shareany data between UEs.
For DL (respectively from UL in UE), the scheduler need to know the quantity of data waitin to be sent: it calls mac_rlc_status_ind()
That "peek" the size of the waiting data for a UE.
The scheduler then push orders to lower layers. The transport layer will actually pull data from RLC with: mac_rlc_data_req()
the low layer push data into rlc by: mac_rlc_data_ind()
Still on DL (gNB side), PDCP push incoming data into RLC by calling: rlc_data_req()
For UL, the low layer push data into rlc by: mac_rlc_data_ind()
Then, rlc push it to pdcp by calling pdcp_data_ind() from a complex rlc internal call back (deliver_sdu())
When adding a UE, external code have to call `add_rlc_srb()` and/or `add_rlc_drb()`, to remove it: `rrc_rlc_remove_ue()`
Inside UE, channels called drd or srb can be created: ??? and deleted: rrc_rlc_config_req()
@@ -322,26 +313,133 @@ nr_rlc_tick() must be called periodically to manage the internal timers
successful_delivery() and max_retx_reached(): in ??? trigger, the RLC sends a itti message to RRC: RLC_SDU_INDICATION (neutralized by #if 0 right now)
#PDCP
## RLC data flow
The PDCP implementation is also protected through a general mutex.
The design is very similar to rlc layer. The pdcp data is isolated and encapsulated.
### TX Flow
nr_pdcp_layer_init(): same as rlc init
we have to call a second init function: pdcp_module_init()
Incoming data to be transmitted is forwarded to RLC by PDCP via `rlc_data_req()`.
At Tx side (DL in gNB), `pdcp_data_req_drb()` and `pdcp_data_req_srb()` are the entry functions that the upper layer calls.
The upper layer can be GTP or a PDCP internal thread enb_tun_read_thread() that read directly from Linux socket in case we skip 3GPP core implementation.
PDCP internals for nr_pdcp_data_req_srb()/nr_pdcp_data_req_drb() are thread safe: inside them, the pdcp manager protects with the mutex the access to the SDU receiving function of PDCP (recv_sdu() callback, corresponding to nr_pdcp_entity_drb_am_recv_sdu() for DRBs). When it needs, the pdcp layer push this data to rlc by calling : rlc_data_req()
At the transport layer, in downlink (DL) at the gNB and uplink (UL) at UE, the scheduler relies on knowing the quantity of data awaiting transmissionis, therefore is using the following MAC/RLC interface functions:
At Rx side, pdcp_data_ind() is the entry point that receives the data from RLC.
- Inside pdcp_data_ind(), the pdcp manager mutex protects the access to the PDU receiving function of PDCP (recv_pdu() callback corresponding to nr_pdcp_entity_drb_am_recv_pdu() for DRBs)
- Then deliver_sdu_drb() function sends the received data to GTP thread through an ITTI message (GTPV1U_TUNNEL_DATA_REQ).
* `mac_rlc_data_req()` to retrieve data bytes to be transmitted by RLC and to fill the MAC SDU
* `mac_rlc_status_ind()` to request and set the number of bytes scheduled for transmission by the RLC
Subsequently, the scheduler issues commands to lower layers.
### RX Flow
In the RX chain, in downlink (DL) at the UE and uplink (UL) at gNB, the transport layer pushes data into RLC through `mac_rlc_data_ind()`. Following this, RLC forwards the data to PDCP by invoking `pdcp_data_ind()` via a complex internal callback mechanism (`deliver_sdu()`).
# PDCP
The PDCP implementation is secured by a general mutex, akin to the design of the RLC layer. This setup ensures that PDCP data remains isolated and encapsulated.
Initialization of the PDCP layer follows a structure similar to that of the RLC layer. The function `nr_pdcp_layer_init()` initializes PDCP, while a second initialization function, `pdcp_module_init()`, must also be invoked.
To manage UE connections, `nr_pdcp_add_srbs()` is employed for adding UE SRBs in PDCP, while `nr_pdcp_remove_UE()` is used for their removal. Similarly, `nr_pdcp_add_drbs()` adds UE DRBs in PDCP, with `nr_pdcp_remove_UE()` handling their removal.
## PDCP Tx flow
On the Tx side (downlink in gNB), the entry functions `nr_pdcp_data_req_drb()` and `nr_pdcp_data_req_srb()` are called by the upper layer. The upper layer could be GTP or a PDCP internal thread like `enb_tun_read_thread()`, which reads directly from the Linux socket if the 3GPP core implementation is skipped. The PDCP internals for `nr_pdcp_data_req_srb()` and `nr_pdcp_data_req_drb()` are thread-safe. Within these functions, the PDCP manager protects access to the SDU receiving function of PDCP (`recv_sdu()` callback, corresponding to `nr_pdcp_entity_recv_pdu()` for DRBs) using mutex. When necessary, the PDCP layer pushes this data to RLC by calling `rlc_data_req()`.
## PDCP Rx flow
At the Rx side, `pdcp_data_ind()` serves as the entry point for receiving data from RLC. Within `pdcp_data_ind()`, the PDCP manager mutex protects access to the PDU receiving function of PDCP (`recv_pdu()` callback corresponding to `nr_pdcp_entity_recv_pdu()` for DRBs). Following this, the `deliver_sdu_drb()` function dispatches the received data to the GTP thread via an ITTI message (`GTPV1U_TUNNEL_DATA_REQ`).
## PDCP security
nr_pdcp_config_set_security(): sets the keys for AS security of a UE
nr_pdcp_add_srbs() adds UE SRBs in pdcp, nr_pdcp_remove_UE() removes it
nr_pdcp_add_drbs() adds UE DRBs in pdcp, nr_pdcp_remove_UE() removes it
# AM DRB traffic flow in OAI
A sequence diagram of the traffic flow across PDCP and RLC layers. By default, data traffic is directed towards AM DRBs.
This is the flow for downlink, involving MAC and upper layers:
```mermaid
sequenceDiagram
title Downlink AM DRB traffic flow
box Purple gNB
participant GG as GTP / TUN
participant SG as SDAP
participant PG as PDCP
participant RG as RLC
participant MG as MAC
end
GG->>SG: sdap_data_req
note over SG: nr_sdap_tx_entity
SG->>PG: nr_pdcp_data_req_drb
note over PG: deliver_pdu_drb_gnb
note over PG: nr_pdcp_entity_process_sdu
note over PG: enqueue_rlc_data_req
PG->>RG: rlc_data_req via rlc_data_req_thread
note over RG: nr_rlc_entity_am_recv_sdu
MG-->>RG: mac_rlc_data_req
note over RG: nr_rlc_entity_am_generate_pdu
note over RG: generate_tx_pdu
note over RG: serialize_sdu
RG-->>MG: PDU to MAC
MG-->MUE: UL TX / RX procedures
box Blue UE
participant MUE as MAC
participant RUE as RLC
participant PUE as PDCP
participant SUE as SDAP
participant GUE as GTP / TUN
end
MUE-->>RUE: SDU to RLC
RUE->>PUE: pdcp_data_ind
note over PUE: nr_pdcp_entity_recv_pdu
note over PUE: deliver_sdu_drb
PUE->>SUE: sdap_data_ind
note over SUE: nr_sdap_rx_entity
SUE->>GUE: send to GTP-U
```
and for uplink:
```mermaid
sequenceDiagram
title Uplink AM DRB traffic flow
box Blue UE
participant GUE as GTP / TUN
participant SUE as SDAP
participant PUE as PDCP
participant RUE as RLC
participant MUE as MAC
end
GUE->>SUE: sdap_data_req
note over SUE: nr_sdap_tx_entity
SUE->>PUE: nr_pdcp_data_req_drb
note over PUE: process_sdu
note over PUE: deliver_pdu_drb_ue
note over PUE: enqueue_rlc_data_req
note over PUE: signal to rlc_data_req_thread
PUE->>RUE: rlc_data_req
note over RUE: nr_rlc_entity_am_recv_sdu
RUE-->>MUE: PDU to MAC
note over MUE: nr_ue_get_sdu
MUE-->MG: UL TX / RX procedures
box Purple gNB
participant MG as MAC
participant RG as RLC
participant PG as PDCP
participant SG as SDAP
participant GG as GTP / TUN
end
MG->>RG: mac_rlc_data_ind
note over RG: nr_rlc_entity_am_recv_pdu
note over RG: reception_actions
note over RG: reassemble_and_deliver
note over RG: deliver_sdu
RG->>PG: pdcp_data_ind
note over PG: enqueue_pdcp_data_ind
note over PG: do_pdcp_data_ind via pdcp_data_ind_thread
note over PG: nr_pdcp_entity_recv_pdu
note over PG: deliver_sdu_drb
PG->>SG: sdap_data_ind
note over SG: nr_sdap_rx_entity
SG->>GG: send to GTP-U
```
# GTP
Gtp + UDP are two twin threads performing the data plane interface to the core network
-1
View File
@@ -787,7 +787,6 @@ void *UE_thread(void *arg)
bool syncRunning=false;
const int nb_slot_frame = UE->frame_parms.slots_per_frame;
int absolute_slot=0, decoded_frame_rx=INT_MAX, trashed_frames=0;
initNotifiedFIFO(&UE->phy_config_ind);
int tx_wait_for_dlsch[NR_MAX_SLOTS_PER_FRAME];
int num_ind_fifo = nb_slot_frame;
+1 -1
View File
@@ -39,6 +39,7 @@
#include "PHY/defs_eNB.h"
#include "PHY/LTE_TRANSPORT/transport_proto.h"
#include "openair2/LAYER2/MAC/mac.h"
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#include "executables/lte-softmodem.h"
#include "openair1/PHY/defs_gNB.h"
@@ -46,7 +47,6 @@
#include "common/ran_context.h"
#include "openair2/PHY_INTERFACE/queue_t.h"
#include "gnb_ind_vars.h"
#include "LAYER2/MAC/mac.h"
#define TEST
@@ -132,6 +132,7 @@ typedef struct {
uint16_t cell_id;
uint16_t ssb_start_subcarrier;
short rsrp_dBm;
long arfcn;
rlm_t radiolink_monitoring; // -1 no monitoring, 0 out_of_sync, 1 in_sync
} fapi_nr_ssb_pdu_t;
+5 -8
View File
@@ -212,22 +212,20 @@ uint32_t get_samples_slot_timestamp(int slot, const NR_DL_FRAME_PARMS *fp, uint8
return samp_count;
}
int nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg,
NR_DL_FRAME_PARMS *fp)
void nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, NR_DL_FRAME_PARMS *fp)
{
AssertFatal (cfg != NULL, "%s %s:%i Null pointer to cfg %p!\n", __FUNCTION__, __FILE__, __LINE__, cfg);
AssertFatal (cfg, "Null pointer to cfg!\n");
fp->frame_type = cfg->cell_config.frame_duplex_type.value;
fp->L_ssb = (((uint64_t) cfg->ssb_table.ssb_mask_list[0].ssb_mask.value)<<32) | cfg->ssb_table.ssb_mask_list[1].ssb_mask.value ;
fp->L_ssb = (((uint64_t) cfg->ssb_table.ssb_mask_list[0].ssb_mask.value) << 32) | cfg->ssb_table.ssb_mask_list[1].ssb_mask.value;
fp->N_RB_DL = cfg->carrier_config.dl_grid_size[cfg->ssb_config.scs_common.value].value;
fp->N_RB_UL = cfg->carrier_config.ul_grid_size[cfg->ssb_config.scs_common.value].value;
int Ncp = NFAPI_CP_NORMAL;
int mu = cfg->ssb_config.scs_common.value;
LOG_I(PHY,"Initializing frame parms for mu %d, N_RB %d, Ncp %d\n",mu, fp->N_RB_DL, Ncp);
LOG_I(PHY,"Initializing frame parms for mu %d, N_RB %d, Ncp %d\n", mu, fp->N_RB_DL, Ncp);
if (Ncp == NFAPI_CP_EXTENDED)
AssertFatal(mu == NR_MU_2,"Invalid cyclic prefix %d for numerology index %d\n", Ncp, mu);
@@ -266,8 +264,7 @@ int nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg,
for (int p=0; p<num_tx_ant; p++)
fp->N_ssb += ((fp->L_ssb >> (63-p)) & 0x01);
return 0;
fp->print_ue_help_cmdline_log = true;
}
int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
+1 -1
View File
@@ -26,7 +26,7 @@
#include "PHY/defs_nr_UE.h"
int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp,uint8_t i_ssb);
int nr_init_frame_parms(nfapi_nr_config_request_scf_t *config, NR_DL_FRAME_PARMS *frame_parms);
void nr_init_frame_parms(nfapi_nr_config_request_scf_t *config, NR_DL_FRAME_PARMS *frame_parms);
int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *frame_parms, fapi_nr_config_request_t *config, uint16_t nr_band);
void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t uplink_frequency_offset, uint8_t mu, uint16_t nr_band);
void nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *frame_parms, uint64_t sidelink_frequency, uint16_t nr_band);
@@ -153,15 +153,7 @@ int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc,
stop_meas(&ue->dlsch_channel_estimation_stats);
fapiPbch_t result = {0};
ret = nr_rx_pbch(ue,
proc,
estimateSz,
dl_ch_estimates,
frame_parms,
temp_ptr->i_ssb,
SISO,
&result,
rxdataF);
ret = nr_rx_pbch(ue, proc, estimateSz, dl_ch_estimates, frame_parms, temp_ptr->i_ssb, &result, rxdataF);
if (DUMP_PBCH_CH_ESTIMATES && (ret == 0)) {
write_output("pbch_ch_estimates.m", "pbch_ch_estimates", dl_ch_estimates, frame_parms->nb_antennas_rx*estimateSz, 1, 1);
+1 -10
View File
@@ -361,7 +361,6 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
struct complex16 dl_ch_estimates[][estimateSz],
NR_DL_FRAME_PARMS *frame_parms,
uint8_t i_ssb,
MIMO_mode_t mimo_mode,
fapiPbch_t *result,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
@@ -414,7 +413,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
symbol_offset,
frame_parms);
#ifdef DEBUG_PBCH
LOG_I(PHY,"[PHY] PBCH Symbol %d ofdm size %d\n",symbol, frame_parms->ofdm_symbol_size );
LOG_I(PHY,"[PHY] PBCH Symbol %d ofdm size %d\n",symbol, frame_parms->ofdm_symbol_size);
LOG_I(PHY,"[PHY] PBCH starting channel_level\n");
#endif
@@ -441,14 +440,6 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
rxdataF_comp,
symbol);*/
/*
if (mimo_mode == ALAMOUTI) {
nr_pbch_alamouti(frame_parms,rxdataF_comp,symbol);
} else if (mimo_mode != SISO) {
LOG_I(PHY,"[PBCH][RX] Unsupported MIMO mode\n");
return(-1);
}
*/
int nb=symbol==2 ? 144 : 360;
nr_pbch_quantize(pbch_e_rx+pbch_e_rx_idx,
(short *)rxdataF_comp[0],
@@ -294,7 +294,6 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
struct complex16 dl_ch_estimates[][estimateSz],
NR_DL_FRAME_PARMS *frame_parms,
uint8_t i_ssb,
MIMO_mode_t mimo_mode,
fapiPbch_t *result,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
+1 -1
View File
@@ -599,7 +599,7 @@ typedef struct PHY_VARS_NR_UE_s {
void *phy_sim_pdsch_dl_ch_estimates;
void *phy_sim_pdsch_dl_ch_estimates_ext;
uint8_t *phy_sim_dlsch_b;
notifiedFIFO_t phy_config_ind;
notifiedFIFO_t tx_resume_ind_fifo[NR_MAX_SLOTS_PER_FRAME];
} PHY_VARS_NR_UE;
+1
View File
@@ -261,6 +261,7 @@ struct NR_DL_FRAME_PARMS {
uint32_t ofdm_offset_divisor;
uint16_t tdd_slot_config;
uint8_t tdd_period;
bool print_ue_help_cmdline_log;
};
// PRS config structures
+30 -10
View File
@@ -45,26 +45,25 @@
extern uint8_t nfapi_mode;
void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_dl_tti_ssb_pdu ssb_pdu) {
NR_DL_FRAME_PARMS *fp=&gNB->frame_parms;
void nr_common_signal_procedures(PHY_VARS_gNB *gNB,int frame,int slot, nfapi_nr_dl_tti_ssb_pdu ssb_pdu)
{
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
c16_t **txdataF = gNB->common_vars.txdataF;
uint8_t ssb_index, n_hf;
uint16_t ssb_start_symbol;
uint8_t n_hf;
int txdataF_offset = slot*fp->samples_per_slot_wCP;
uint16_t slots_per_hf = (fp->slots_per_frame)>>1;
uint16_t slots_per_hf = (fp->slots_per_frame) >> 1;
if (slot<slots_per_hf)
n_hf=0;
else
n_hf=1;
ssb_index = ssb_pdu.ssb_pdu_rel15.SsbBlockIndex;
LOG_D(PHY,"common_signal_procedures: frame %d, slot %d ssb index %d\n",frame,slot,ssb_index);
uint8_t ssb_index = ssb_pdu.ssb_pdu_rel15.SsbBlockIndex;
LOG_D(PHY,"common_signal_procedures: frame %d, slot %d ssb index %d\n", frame, slot, ssb_index);
int ssb_start_symbol_abs = nr_get_ssb_start_symbol(fp,ssb_index); // computing the starting symbol for current ssb
ssb_start_symbol = ssb_start_symbol_abs % fp->symbols_per_slot; // start symbol wrt slot
int ssb_start_symbol_abs = nr_get_ssb_start_symbol(fp, ssb_index); // computing the starting symbol for current ssb
uint16_t ssb_start_symbol = ssb_start_symbol_abs % fp->symbols_per_slot; // start symbol wrt slot
// Setting the first subcarrier
// 3GPP TS 38.211 sections 7.4.3.1 and 4.4.4.2
@@ -77,6 +76,27 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_
const int sc_offset =
(fp->freq_range == nr_FR1) ? ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset >> scs : ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset;
fp->ssb_start_subcarrier = (12 * prb_offset + sc_offset);
if (fp->print_ue_help_cmdline_log && get_softmodem_params()->sa) {
fp->print_ue_help_cmdline_log = false;
if (fp->dl_CarrierFreq != fp->ul_CarrierFreq)
LOG_A(PHY,
"Command line parameters for the UE: -C %lu --CO %lu -r %d --numerology %d --band %d --ssb %d\n",
fp->dl_CarrierFreq,
fp->dl_CarrierFreq - fp->ul_CarrierFreq,
fp->N_RB_DL,
scs,
fp->nr_band,
fp->ssb_start_subcarrier);
else
LOG_A(PHY,
"Command line parameters for the UE: -C %lu -r %d --numerology %d --band %d --ssb %d\n",
fp->dl_CarrierFreq,
fp->N_RB_DL,
scs,
fp->nr_band,
fp->ssb_start_subcarrier);
}
LOG_D(PHY,
"ssbOffsetPointA %d SSB SsbSubcarrierOffset %d prb_offset %d sc_offset %d scs %d ssb_start_subcarrier %d\n",
ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA,
-1
View File
@@ -544,7 +544,6 @@ int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config)
fapi_nr_config_request_t *nrUE_config = &PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->nrUE_config;
if(phy_config != NULL) {
memcpy(nrUE_config, &phy_config->config_req, sizeof(fapi_nr_config_request_t));
pushNotifiedFIFO(&PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->phy_config_ind, newNotifiedFIFO_elt(1,0,NULL,NULL));
}
return 0;
}
+9 -1
View File
@@ -109,6 +109,14 @@ void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind,
}
}
static uint32_t get_ssb_arfcn(NR_DL_FRAME_PARMS *frame_parms)
{
uint32_t band_size_hz = frame_parms->N_RB_DL * 12 * frame_parms->subcarrier_spacing;
int ssb_center_sc = frame_parms->ssb_start_subcarrier + 120; // ssb is 20 PRBs -> 240 sub-carriers
uint64_t ssb_freq = frame_parms->dl_CarrierFreq - (band_size_hz / 2) + frame_parms->subcarrier_spacing * ssb_center_sc;
return to_nrarfcn(frame_parms->nr_band, ssb_freq, frame_parms->numerology_index, band_size_hz);
}
void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
uint8_t pdu_type,
PHY_VARS_NR_UE *ue,
@@ -168,6 +176,7 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
ssb_pdu->cell_id = frame_parms->Nid_cell;
ssb_pdu->ssb_start_subcarrier = frame_parms->ssb_start_subcarrier;
ssb_pdu->rsrp_dBm = ue->measurements.ssb_rsrp_dBm[frame_parms->ssb_index];
ssb_pdu->arfcn = get_ssb_arfcn(frame_parms);
ssb_pdu->radiolink_monitoring = RLM_in_sync; // TODO to be removed from here
ssb_pdu->decoded_pdu = true;
}
@@ -384,7 +393,6 @@ static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue,
dl_ch_estimates,
&ue->frame_parms,
(ue->frame_parms.ssb_index)&7,
SISO,
&result,
rxdataF);
+1 -1
View File
@@ -873,7 +873,7 @@ int main(int argc, char **argv)
asn1cFreeStruc(asn_DEF_NR_CellGroupConfig, UE_CellGroup);
UE_mac->state = UE_CONNECTED;
UE_mac->ra.ra_state = RA_SUCCEEDED;
UE_mac->ra.ra_state = nrRA_SUCCEEDED;
nr_phy_data_t phy_data = {0};
fapi_nr_dl_config_request_t dl_config = {.sfn = frame, .slot = slot};
@@ -32,7 +32,7 @@ void nr_mac_rrc_sync_ind(const module_id_t module_id,
const frame_t frame,
const bool in_sync) {}
void nr_mac_rrc_msg3_ind(const module_id_t mod_id, int rnti) {}
void nr_mac_rrc_msg3_ind(const module_id_t mod_id, int rnti, int gnb_id) {}
void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success) {}
@@ -48,6 +48,8 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
const frame_t frame,
const int slot,
const rnti_t rnti,
const uint32_t cellid,
const long arfcn,
const channel_t channel,
const uint8_t* pduP,
const sdu_size_t pdu_len) { return 0; }
+1 -9
View File
@@ -797,15 +797,7 @@ int main(int argc, char **argv)
}
fapiPbch_t result;
ret = nr_rx_pbch(UE,
&proc,
estimateSz,
dl_ch_estimates,
frame_parms,
ssb_index%8,
SISO,
&result,
rxdataF);
ret = nr_rx_pbch(UE, &proc, estimateSz, dl_ch_estimates, frame_parms, ssb_index % 8, &result, rxdataF);
if (ret==0) {
//UE->rx_ind.rx_indication_body->mib_pdu.ssb_index; //not yet detected automatically
+4 -1
View File
@@ -76,7 +76,8 @@ typedef struct NRRrcMacRaInd_s {
} NRRrcMacRaInd;
typedef struct NRRrcMacMsg3Ind_s {
uint16_t rnti;
uint16_t rnti;
int gnb_id;
} NRRrcMacMsg3Ind;
typedef struct RrcMacInSyncInd_s {
@@ -118,6 +119,8 @@ typedef struct NRRrcMacBcchDataInd_s {
bool is_bch;
uint8_t rsrq;
uint8_t rsrp;
uint32_t phycellid;
long ssb_arfcn;
} NRRrcMacBcchDataInd;
typedef struct NRRrcMacSBcchDataInd_s {
+149 -394
View File
@@ -38,31 +38,153 @@
#include "rrc_extern.h"
#include "openair2/RRC/NR/rrc_gNB_NGAP.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
static void setQos(F1AP_NonDynamic5QIDescriptor_t **toFill)
static void f1ap_write_drb_qos_param(const f1ap_qos_flow_level_qos_parameters_t *drb_qos_in, F1AP_QoSFlowLevelQoSParameters_t *asn1_qosparam)
{
asn1cCalloc(*toFill, tmp);
/* fiveQI */
tmp->fiveQI = 1L;
int type = drb_qos_in->qos_characteristics.qos_type;
const f1ap_qos_characteristics_t *drb_qos_char_in = &drb_qos_in->qos_characteristics;
if (type == non_dynamic) {
asn1_qosparam->qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI;
asn1cCalloc(asn1_qosparam->qoS_Characteristics.choice.non_Dynamic_5QI, tmp);
/* 5QI */
tmp->fiveQI = drb_qos_char_in->non_dynamic.fiveqi;
} else {
asn1_qosparam->qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_dynamic_5QI;
asn1cCalloc(asn1_qosparam->qoS_Characteristics.choice.dynamic_5QI, tmp);
/* qoSPriorityLevel */
tmp->qoSPriorityLevel = drb_qos_char_in->dynamic.qos_priority_level;
/* packetDelayBudget */
tmp->packetDelayBudget = drb_qos_char_in->dynamic.packet_delay_budget;
/* packetErrorRate */
tmp->packetErrorRate.pER_Scalar = drb_qos_char_in->dynamic.packet_error_rate.per_scalar;
tmp->packetErrorRate.pER_Exponent = drb_qos_char_in->dynamic.packet_error_rate.per_scalar;
/* OPTIONAL delayCritical */
// asn1cCallocOne(asn1_qosparam->qoS_Characteristics.choice.dynamic_5QI->delayCritical, 1L);
/* OPTIONAL averagingWindow */
// asn1cCallocOne(asn1_qosparam->qoS_Characteristics.choice.dynamic_5QI->averagingWindow, 1L);
/* OPTIONAL maxDataBurstVolume */
// asn1cCallocOne(asn1_qosparam->qoS_Characteristics.choice.dynamic_5QI->maxDataBurstVolume, 1L);
}
{
asn1_qosparam->nGRANallocationRetentionPriority.priorityLevel = drb_qos_in->alloc_reten_priority.priority_level;
asn1_qosparam->nGRANallocationRetentionPriority.pre_emptionCapability = drb_qos_in->alloc_reten_priority.preemption_capability;
asn1_qosparam->nGRANallocationRetentionPriority.pre_emptionVulnerability =
drb_qos_in->alloc_reten_priority.preemption_vulnerability;
} // nGRANallocationRetentionPriority
/* OPTIONAL */
/* qoSPriorityLevel */
/* gBR_QoS_Flow_Information */
if (0) {
asn1cCallocOne((*toFill)->qoSPriorityLevel, 1L);
asn1cCalloc(asn1_qosparam->gBR_QoS_Flow_Information, tmp);
asn_long2INTEGER(&tmp->maxFlowBitRateDownlink, 1L);
asn_long2INTEGER(&tmp->maxFlowBitRateUplink, 1L);
asn_long2INTEGER(&tmp->guaranteedFlowBitRateDownlink, 1L);
asn_long2INTEGER(&tmp->guaranteedFlowBitRateUplink, 1L);
/* OPTIONAL */
/* maxPacketLossRateDownlink */
// asn1cCallocOne(asn1_qosparam->gBR_QoS_Flow_Information->maxPacketLossRateDownlink, 1L);
/* OPTIONAL */
/* maxPacketLossRateUplink */
//asn1cCallocOne(asn1_qosparam->gBR_QoS_Flow_Information->maxPacketLossRateUplink, 1L);
}
/* OPTIONAL */
/* averagingWindow */
/* reflective_QoS_Attribute */
if (0) {
asn1cCallocOne((*toFill)->averagingWindow, 1L);
asn1cCallocOne(asn1_qosparam->reflective_QoS_Attribute, 1L);
}
}
static void f1ap_write_drb_nssai(const nssai_t *nssai, F1AP_SNSSAI_t *asn1_nssai)
{
OCTET_STRING_fromBuf(&asn1_nssai->sST, (char *)&nssai->sst, 1);
/* OPTIONAL */
/* maxDataBurstVolume */
if (0) {
asn1cCallocOne((*toFill)->maxDataBurstVolume, 1L);
if (nssai->sd != 0xffffff)
OCTET_STRING_fromBuf(asn1_nssai->sD, (char *)&nssai->sd, 3);
}
static void f1ap_write_flows_mapped(const f1ap_flows_mapped_to_drb_t *flows_mapped, F1AP_Flows_Mapped_To_DRB_List_t *asn1_flows_mapped, int n)
{
for (int k = 0; k < n; k++) {
asn1cSequenceAdd(asn1_flows_mapped->list, F1AP_Flows_Mapped_To_DRB_Item_t, flow_item);
const f1ap_flows_mapped_to_drb_t *qos_flow_in = flows_mapped + k;
/* qoSFlowIndicator */
flow_item->qoSFlowIdentifier = qos_flow_in->qfi;
/* qoSFlowLevelQoSParameters */
const f1ap_qos_flow_level_qos_parameters_t *flow_qos_params_in = &qos_flow_in->qos_params;
/* qoS_Characteristics */
F1AP_QoS_Characteristics_t *QosParams = &flow_item->qoSFlowLevelQoSParameters.qoS_Characteristics;
const f1ap_qos_characteristics_t *flow_qos_char_in = &flow_qos_params_in->qos_characteristics;
int type = flow_qos_params_in->qos_characteristics.qos_type;
if (type == non_dynamic) {
QosParams->present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI;
asn1cCalloc(QosParams->choice.non_Dynamic_5QI, tmp);
/* 5QI */
tmp->fiveQI = flow_qos_char_in->non_dynamic.fiveqi;
} else {
QosParams->present = F1AP_QoS_Characteristics_PR_dynamic_5QI;
asn1cCalloc(QosParams->choice.dynamic_5QI, tmp);
/* qoSPriorityLevel */
tmp->qoSPriorityLevel = flow_qos_char_in->dynamic.qos_priority_level;
/* packetDelayBudget */
tmp->packetDelayBudget = flow_qos_char_in->dynamic.packet_delay_budget;
/* packetErrorRate */
tmp->packetErrorRate.pER_Scalar = flow_qos_char_in->dynamic.packet_error_rate.per_scalar;
tmp->packetErrorRate.pER_Exponent = flow_qos_char_in->dynamic.packet_error_rate.per_exponent;
/* OPTIONAL delayCritical */
//asn1cCallocOne(QosParams->choice.dynamic_5QI->delayCritical, 1);
/* OPTIONAL averagingWindow */
//asn1cCallocOne(QosParams->choice.dynamic_5QI->averagingWindow, 1);
/* OPTIONAL maxDataBurstVolume */
//asn1cCallocOne(QosParams->choice.dynamic_5QI->maxDataBurstVolume, 1);
}
/* nGRANallocationRetentionPriority */
{
flow_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel =
flow_qos_params_in->alloc_reten_priority.priority_level;
flow_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability =
flow_qos_params_in->alloc_reten_priority.preemption_capability;
flow_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability =
flow_qos_params_in->alloc_reten_priority.preemption_vulnerability;
} // nGRANallocationRetentionPriority
/* OPTIONAL */
/* gBR_QoS_Flow_Information */
if (0) {
asn1cCalloc(flow_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information, tmp);
asn_long2INTEGER(&tmp->maxFlowBitRateDownlink, 1L);
asn_long2INTEGER(&tmp->maxFlowBitRateUplink, 1L);
asn_long2INTEGER(&tmp->guaranteedFlowBitRateDownlink, 1L);
asn_long2INTEGER(&tmp->guaranteedFlowBitRateUplink, 1L);
/* OPTIONAL maxPacketLossRateDownlink */
//asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information->maxPacketLossRateDownlink, 1L);
/* OPTIONAL maxPacketLossRateUplink */
//asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information->maxPacketLossRateUplink, 1L);
}
/* OPTIONAL reflective_QoS_Attribute */
//asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.reflective_QoS_Attribute, 1L);
}
}
@@ -275,7 +397,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu
ie12->value.present = F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List;
for (int i = 0; i < f1ap_ue_context_setup_req->drbs_to_be_setup_length; i++) {
//
const f1ap_drb_to_be_setup_t *drb = &f1ap_ue_context_setup_req->drbs_to_be_setup[i];
asn1cSequenceAdd(ie12->value.choice.DRBs_ToBeSetup_List.list, F1AP_DRBs_ToBeSetup_ItemIEs_t, drbs_toBeSetup_item_ies);
drbs_toBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_Item;
drbs_toBeSetup_item_ies->criticality = F1AP_Criticality_reject;
@@ -283,7 +405,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu
/* 12.1 DRBs_ToBeSetup_Item */
F1AP_DRBs_ToBeSetup_Item_t *drbs_toBeSetup_item=&drbs_toBeSetup_item_ies->value.choice.DRBs_ToBeSetup_Item;
/* 12.1.1 dRBID */
drbs_toBeSetup_item->dRBID = f1ap_ue_context_setup_req->drbs_to_be_setup[i].drb_id; // 9
drbs_toBeSetup_item->dRBID = drb->drb_id;
/* 12.1.2 qoSInformation */
int some_decide_qos = 0; // BK: Need Check
@@ -314,6 +436,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu
}
} else {
/* 12.1.2 DRB_Information */
const f1ap_drb_information_t *drb_info = &drb->drb_info;
drbs_toBeSetup_item->qoSInformation.present = F1AP_QoSInformation_PR_choice_extension;
F1AP_QoSInformation_ExtIEs_t *ie = (F1AP_QoSInformation_ExtIEs_t *)calloc(1, sizeof(*ie));
ie->id = F1AP_ProtocolIE_ID_id_DRB_Information;
@@ -321,90 +444,12 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu
ie->value.present = F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information;
F1AP_DRB_Information_t *DRB_Information = &ie->value.choice.DRB_Information;
drbs_toBeSetup_item->qoSInformation.choice.choice_extension = (struct F1AP_ProtocolIE_SingleContainer *)ie;
/* 12.1.2.1 dRB_QoS */
{
/* qoS_Characteristics */
{
int some_decide_qoS_characteristics = 0; // BK: Need Check
f1ap_write_drb_qos_param(&drb_info->drb_qos, &DRB_Information->dRB_QoS);
if (some_decide_qoS_characteristics) {
DRB_Information->dRB_QoS.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI;
setQos(&DRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI);
} else {
DRB_Information->dRB_QoS.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_dynamic_5QI;
asn1cCalloc(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI, tmp);
/* qoSPriorityLevel */
tmp->qoSPriorityLevel = 1L;
/* packetDelayBudget */
tmp->packetDelayBudget = 1L;
/* packetErrorRate */
tmp->packetErrorRate.pER_Scalar = 1L;
tmp->packetErrorRate.pER_Exponent = 6L;
/* OPTIONAL */
/* delayCritical */
if (0) {
asn1cCallocOne(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->delayCritical, 1L);
}
/* OPTIONAL */
/* averagingWindow */
if (0) {
asn1cCallocOne(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->averagingWindow, 1L);
}
/* OPTIONAL */
/* maxDataBurstVolume */
if (0) {
asn1cCallocOne(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->maxDataBurstVolume, 1L);
}
} // if some_decide_qoS_characteristics
} // qoS_Characteristics
/* nGRANallocationRetentionPriority */
{
DRB_Information->dRB_QoS.nGRANallocationRetentionPriority.priorityLevel = F1AP_PriorityLevel_highest; // enum
DRB_Information->dRB_QoS.nGRANallocationRetentionPriority.pre_emptionCapability = F1AP_Pre_emptionCapability_shall_not_trigger_pre_emption; // enum
DRB_Information->dRB_QoS.nGRANallocationRetentionPriority.pre_emptionVulnerability = F1AP_Pre_emptionVulnerability_not_pre_emptable; // enum
} // nGRANallocationRetentionPriority
/* OPTIONAL */
/* gBR_QoS_Flow_Information */
if (0) {
asn1cCalloc(DRB_Information->dRB_QoS.gBR_QoS_Flow_Information, tmp);
asn_long2INTEGER(&tmp->maxFlowBitRateDownlink, 1L);
asn_long2INTEGER(&tmp->maxFlowBitRateUplink, 1L);
asn_long2INTEGER(&tmp->guaranteedFlowBitRateDownlink, 1L);
asn_long2INTEGER(&tmp->guaranteedFlowBitRateUplink, 1L);
/* OPTIONAL */
/* maxPacketLossRateDownlink */
if (0) {
asn1cCallocOne(DRB_Information->dRB_QoS.gBR_QoS_Flow_Information->maxPacketLossRateDownlink, 1L);
}
/* OPTIONAL */
/* maxPacketLossRateUplink */
if (0) {
asn1cCallocOne(DRB_Information->dRB_QoS.gBR_QoS_Flow_Information->maxPacketLossRateUplink, 1L);
}
}
/* OPTIONAL */
/* reflective_QoS_Attribute */
if (0) {
asn1cCallocOne(DRB_Information->dRB_QoS.reflective_QoS_Attribute, 1L);
}
} // dRB_QoS
/* 12.1.2.2 sNSSAI */
{
/* sST */
OCTET_STRING_fromBuf(&DRB_Information->sNSSAI.sST, (char *)&f1ap_ue_context_setup_req->drbs_to_be_setup[i].nssai.sst, 1);
/* OPTIONAL */
const uint32_t sd = (f1ap_ue_context_setup_req->drbs_to_be_setup[i].nssai.sd & 0xffffff);
if (sd != 0xffffff)
OCTET_STRING_fromBuf(DRB_Information->sNSSAI.sD, (char *)&sd, 3);
}
f1ap_write_drb_nssai(&drb->nssai, &DRB_Information->sNSSAI);
/* OPTIONAL */
/* 12.1.2.3 notificationControl */
@@ -414,108 +459,12 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu
}
/* 12.1.2.4 flows_Mapped_To_DRB_List */ // BK: need verifiy
for (int k = 0; k < 1; k ++) {
asn1cSequenceAdd(DRB_Information->flows_Mapped_To_DRB_List.list,
F1AP_Flows_Mapped_To_DRB_Item_t, flows_mapped_to_drb_item);
/* qoSFlowIndicator */
flows_mapped_to_drb_item->qoSFlowIdentifier = 1L;
/* qoSFlowLevelQoSParameters */
{
/* qoS_Characteristics */
{
int some_decide_qoS_characteristics = 0; // BK: Need Check
F1AP_QoS_Characteristics_t *QosParams=&flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.qoS_Characteristics;
if (some_decide_qoS_characteristics) {
QosParams->present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI;
setQos(&QosParams->choice.non_Dynamic_5QI);
} else {
QosParams->present = F1AP_QoS_Characteristics_PR_dynamic_5QI;
asn1cCalloc(QosParams->choice.dynamic_5QI, tmp);
/* qoSPriorityLevel */
tmp->qoSPriorityLevel = 1L;
/* packetDelayBudget */
tmp->packetDelayBudget = 1L;
/* packetErrorRate */
tmp->packetErrorRate.pER_Scalar = 1L;
tmp->packetErrorRate.pER_Exponent = 6L;
/* OPTIONAL */
/* delayCritical */
if (0) {
asn1cCalloc(QosParams->choice.dynamic_5QI->delayCritical, tmp);
*tmp = 1L;
}
/* OPTIONAL */
/* averagingWindow */
if (0) {
asn1cCalloc(QosParams->choice.dynamic_5QI->averagingWindow, tmp);
*tmp = 1L;
}
/* OPTIONAL */
/* maxDataBurstVolume */
if (0) {
asn1cCalloc(QosParams->choice.dynamic_5QI->maxDataBurstVolume, tmp);
*tmp= 1L;
}
} // if some_decide_qoS_characteristics
} // qoS_Characteristics
/* nGRANallocationRetentionPriority */
{
flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = F1AP_PriorityLevel_highest; // enum
flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability = F1AP_Pre_emptionCapability_shall_not_trigger_pre_emption; // enum
flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability = F1AP_Pre_emptionVulnerability_not_pre_emptable; // enum
} // nGRANallocationRetentionPriority
/* OPTIONAL */
/* gBR_QoS_Flow_Information */
if (0) {
asn1cCalloc(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information, tmp);
asn_long2INTEGER(&tmp->maxFlowBitRateDownlink, 1L);
asn_long2INTEGER(&tmp->maxFlowBitRateUplink, 1L);
asn_long2INTEGER(&tmp->guaranteedFlowBitRateDownlink, 1L);
asn_long2INTEGER(&tmp->guaranteedFlowBitRateUplink, 1L);
/* OPTIONAL */
/* maxPacketLossRateDownlink */
if (0) {
asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information->maxPacketLossRateDownlink, 1L);
}
/* OPTIONAL */
/* maxPacketLossRateUplink */
if (0) {
asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information->maxPacketLossRateUplink, 1L);
}
}
/* OPTIONAL */
/* reflective_QoS_Attribute */
if (0) {
asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.reflective_QoS_Attribute, 1L);
}
} // qoSFlowLevelQoSParameters
}
f1ap_write_flows_mapped(drb_info->flows_mapped_to_drb, &DRB_Information->flows_Mapped_To_DRB_List, drb_info->flows_to_be_setup_length);
} // if some_decide_qos
/* 12.1.3 uLUPTNLInformation_ToBeSetup_List */
for (int j = 0; j < f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl_length; j++) {
/*Use a dummy teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context setup response from the DU*/
/* Use a dummy address and teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context setup response from the DU */
transport_layer_addr_t addr = { .length= 32, .buffer= { 0 } };
f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].teid = newGtpuCreateTunnel(getCxt(0)->gtpInst,
f1ap_ue_context_setup_req->gNB_CU_ue_id,
f1ap_ue_context_setup_req->drbs_to_be_setup[i].drb_id,
f1ap_ue_context_setup_req->drbs_to_be_setup[i].drb_id,
0xFFFF, // We will set the right value from DU answer
-1, // no qfi
addr, // We will set the right value from DU answer
f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_dl_tnl[0].port,
cu_f1u_data_req,
NULL);
DevAssert(f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].teid > 0);
/* 12.3.1 ULTunnels_ToBeSetup_Item */
asn1cSequenceAdd(drbs_toBeSetup_item->uLUPTNLInformation_ToBeSetup_List.list,
F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item);
@@ -688,11 +637,6 @@ int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_
F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel;
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address);
OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid);
GtpuUpdateTunnelOutgoingAddressAndTeid(getCxt(instance)->gtpInst,
f1ap_ue_context_setup_resp->gNB_DU_ue_id,
(ebi_t)drbs_setup_item_p->dRBID,
drb_p->up_dl_tnl[0].tl_address,
drb_p->up_dl_tnl[0].teid);
}
}
@@ -1182,6 +1126,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_conte
ie12->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeSetupMod_List;
for (int i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_setup_length; i++) {
const f1ap_drb_to_be_setup_t *drb = &f1ap_ue_context_modification_req->drbs_to_be_setup[i];
asn1cSequenceAdd(ie12->value.choice.DRBs_ToBeSetupMod_List.list,
F1AP_DRBs_ToBeSetupMod_ItemIEs_t, drbs_toBeSetupMod_item_ies);
drbs_toBeSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item;
@@ -1191,7 +1136,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_conte
F1AP_DRBs_ToBeSetupMod_Item_t *drbs_toBeSetupMod_item=
&drbs_toBeSetupMod_item_ies->value.choice.DRBs_ToBeSetupMod_Item;
/* dRBID */
drbs_toBeSetupMod_item->dRBID = f1ap_ue_context_modification_req->drbs_to_be_setup[i].drb_id;
drbs_toBeSetupMod_item->dRBID = drb->drb_id;
/* qoSInformation */
if(f1ap_ue_context_modification_req->QoS_information_type == EUTRAN_QoS){
@@ -1235,99 +1180,12 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_conte
ie->value.present = F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information;
F1AP_DRB_Information_t *DRB_Information = &ie->value.choice.DRB_Information;
drbs_toBeSetupMod_item->qoSInformation.choice.choice_extension = (struct F1AP_ProtocolIE_SingleContainer *)ie;
/* 12.1.2.1 dRB_QoS */
{
/* qoS_Characteristics */
f1ap_qos_flow_level_qos_parameters_t *drb_qos_in = &drb_info_in->drb_qos;
{
int some_decide_qoS_characteristics = drb_qos_in->qos_characteristics.qos_type;
f1ap_write_drb_qos_param(&drb_info_in->drb_qos, &DRB_Information->dRB_QoS);
f1ap_qos_characteristics_t *drb_qos_char_in = &drb_qos_in->qos_characteristics;
if (some_decide_qoS_characteristics == non_dynamic) {
DRB_Information->dRB_QoS.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI;
asn1cCalloc(DRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI, tmp);
/* 5QI */
tmp->fiveQI = drb_qos_char_in->non_dynamic.fiveqi;
} else {
DRB_Information->dRB_QoS.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_dynamic_5QI;
asn1cCalloc(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI, tmp);
/* qoSPriorityLevel */
tmp->qoSPriorityLevel = drb_qos_char_in->dynamic.qos_priority_level;
/* packetDelayBudget */
tmp->packetDelayBudget = drb_qos_char_in->dynamic.packet_delay_budget;
/* packetErrorRate */
tmp->packetErrorRate.pER_Scalar = drb_qos_char_in->dynamic.packet_error_rate.per_scalar;
tmp->packetErrorRate.pER_Exponent = drb_qos_char_in->dynamic.packet_error_rate.per_scalar;
/* OPTIONAL */
/* delayCritical */
if (0) {
asn1cCallocOne(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->delayCritical, 1L);
}
/* OPTIONAL */
/* averagingWindow */
if (0) {
asn1cCallocOne(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->averagingWindow, 1L);
}
/* OPTIONAL */
/* maxDataBurstVolume */
if (0) {
asn1cCallocOne(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->maxDataBurstVolume, 1L);
}
} // if some_decide_qoS_characteristics
} // qoS_Characteristics
/* nGRANallocationRetentionPriority */
{
DRB_Information->dRB_QoS.nGRANallocationRetentionPriority.priorityLevel =
drb_qos_in->alloc_reten_priority.priority_level;
DRB_Information->dRB_QoS.nGRANallocationRetentionPriority.pre_emptionCapability =
drb_qos_in->alloc_reten_priority.preemption_capability;
DRB_Information->dRB_QoS.nGRANallocationRetentionPriority.pre_emptionVulnerability =
drb_qos_in->alloc_reten_priority.preemption_vulnerability;
} // nGRANallocationRetentionPriority
/* OPTIONAL */
/* gBR_QoS_Flow_Information */
if (0) {
asn1cCalloc(DRB_Information->dRB_QoS.gBR_QoS_Flow_Information, tmp);
asn_long2INTEGER(&tmp->maxFlowBitRateDownlink, 1L);
asn_long2INTEGER(&tmp->maxFlowBitRateUplink, 1L);
asn_long2INTEGER(&tmp->guaranteedFlowBitRateDownlink, 1L);
asn_long2INTEGER(&tmp->guaranteedFlowBitRateUplink, 1L);
/* OPTIONAL */
/* maxPacketLossRateDownlink */
if (0) {
asn1cCallocOne(DRB_Information->dRB_QoS.gBR_QoS_Flow_Information->maxPacketLossRateDownlink, 1L);
}
/* OPTIONAL */
/* maxPacketLossRateUplink */
if (0) {
asn1cCallocOne(DRB_Information->dRB_QoS.gBR_QoS_Flow_Information->maxPacketLossRateUplink, 1L);
}
}
/* OPTIONAL */
/* reflective_QoS_Attribute */
if (0) {
asn1cCallocOne(DRB_Information->dRB_QoS.reflective_QoS_Attribute, 1L);
}
} // dRB_QoS
/* 12.1.2.2 sNSSAI */
{
/* sST */
OCTET_STRING_fromBuf(&DRB_Information->sNSSAI.sST, (char *)&f1ap_ue_context_modification_req->drbs_to_be_setup[i].nssai.sst, 1);
/* OPTIONAL */
const uint32_t sd = (f1ap_ue_context_modification_req->drbs_to_be_setup[i].nssai.sd & 0xffffff);
if (sd != 0xffffff)
OCTET_STRING_fromBuf(DRB_Information->sNSSAI.sD, (char *)&sd, 3);
}
f1ap_write_drb_nssai(&drb->nssai, &DRB_Information->sNSSAI);
/* OPTIONAL */
/* 12.1.2.3 notificationControl */
@@ -1337,102 +1195,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_conte
}
/* 12.1.2.4 flows_Mapped_To_DRB_List */
for (int k = 0; k < drb_info_in->flows_to_be_setup_length; k++) {
asn1cSequenceAdd(DRB_Information->flows_Mapped_To_DRB_List.list,
F1AP_Flows_Mapped_To_DRB_Item_t, flows_mapped_to_drb_item);
f1ap_flows_mapped_to_drb_t *qos_flow_in = drb_info_in->flows_mapped_to_drb + k;
/* qoSFlowIndicator */
flows_mapped_to_drb_item->qoSFlowIdentifier = qos_flow_in->qfi;
/* qoSFlowLevelQoSParameters */
{
f1ap_qos_flow_level_qos_parameters_t *flow_qos_params_in = &qos_flow_in->qos_params;
/* qoS_Characteristics */
{
int some_decide_qoS_characteristics = flow_qos_params_in->qos_characteristics.qos_type;
F1AP_QoS_Characteristics_t *QosParams = &flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.qoS_Characteristics;
f1ap_qos_characteristics_t *flow_qos_char_in = &flow_qos_params_in->qos_characteristics;
if (some_decide_qoS_characteristics == non_dynamic) {
QosParams->present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI;
asn1cCalloc(QosParams->choice.non_Dynamic_5QI, tmp);
/* 5QI */
tmp->fiveQI = flow_qos_char_in->non_dynamic.fiveqi;
} else {
QosParams->present = F1AP_QoS_Characteristics_PR_dynamic_5QI;
asn1cCalloc(QosParams->choice.dynamic_5QI, tmp);
/* qoSPriorityLevel */
tmp->qoSPriorityLevel = flow_qos_char_in->dynamic.qos_priority_level;
/* packetDelayBudget */
tmp->packetDelayBudget = flow_qos_char_in->dynamic.packet_delay_budget;
/* packetErrorRate */
tmp->packetErrorRate.pER_Scalar = flow_qos_char_in->dynamic.packet_error_rate.per_scalar;
tmp->packetErrorRate.pER_Exponent = flow_qos_char_in->dynamic.packet_error_rate.per_exponent;
/* OPTIONAL */
/* delayCritical */
if (0) {
asn1cCalloc(QosParams->choice.dynamic_5QI->delayCritical, tmp);
*tmp = 1L;
}
/* OPTIONAL */
/* averagingWindow */
if (0) {
asn1cCalloc(QosParams->choice.dynamic_5QI->averagingWindow, tmp);
*tmp = 1L;
}
/* OPTIONAL */
/* maxDataBurstVolume */
if (0) {
asn1cCalloc(QosParams->choice.dynamic_5QI->maxDataBurstVolume, tmp);
*tmp= 1L;
}
} // if some_decide_qoS_characteristics
} // qoS_Characteristics
/* nGRANallocationRetentionPriority */
{
flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel =
flow_qos_params_in->alloc_reten_priority.priority_level;
flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability =
flow_qos_params_in->alloc_reten_priority.preemption_capability;
flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability =
flow_qos_params_in->alloc_reten_priority.preemption_vulnerability;
} // nGRANallocationRetentionPriority
/* OPTIONAL */
/* gBR_QoS_Flow_Information */
if (0) {
asn1cCalloc(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information, tmp);
asn_long2INTEGER(&tmp->maxFlowBitRateDownlink, 1L);
asn_long2INTEGER(&tmp->maxFlowBitRateUplink, 1L);
asn_long2INTEGER(&tmp->guaranteedFlowBitRateDownlink, 1L);
asn_long2INTEGER(&tmp->guaranteedFlowBitRateUplink, 1L);
/* OPTIONAL */
/* maxPacketLossRateDownlink */
if (0) {
asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information->maxPacketLossRateDownlink, 1L);
}
/* OPTIONAL */
/* maxPacketLossRateUplink */
if (0) {
asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information->maxPacketLossRateUplink, 1L);
}
}
/* OPTIONAL */
/* reflective_QoS_Attribute */
if (0) {
asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.reflective_QoS_Attribute, 1L);
}
} // qoSFlowLevelQoSParameters
}
f1ap_write_flows_mapped(drb_info_in->flows_mapped_to_drb, &DRB_Information->flows_Mapped_To_DRB_List, drb_info_in->flows_to_be_setup_length);
} //QoS information
@@ -1569,9 +1332,6 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_conte
&drbs_toBeReleased_item_ies->value.choice.DRBs_ToBeReleased_Item;
/* dRBID */
drbs_toBeReleased_item->dRBID = f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id;
newGtpuDeleteOneTunnel(getCxt(0)->gtpInst,
f1ap_ue_context_modification_req->gNB_CU_ue_id,
f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id);
}
}
@@ -1644,11 +1404,6 @@ int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, sctp_assoc_t
F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel;
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address);
OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid);
GtpuUpdateTunnelOutgoingAddressAndTeid(getCxt(instance)->gtpInst,
f1ap_ue_context_modification_resp->gNB_CU_ue_id,
(ebi_t)drbs_setupmod_item_p->dRBID,
drb_p->up_dl_tnl[0].tl_address,
drb_p->up_dl_tnl[0].teid);
}
}
// SRBs_FailedToBeSetupMod_List
@@ -50,7 +50,6 @@
#include "asn1_msg.h"
#include "intertask_interface.h"
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h"
@@ -83,7 +82,6 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, sctp_assoc_t assoc_id
/* strange: it is not named OLD_GNB_DU_UE... */
old_gNB_DU_ue_id_stack = ie->value.choice.GNB_DU_UE_F1AP_ID_1;
old_gNB_DU_ue_id = &old_gNB_DU_ue_id_stack;
gtpv1u_update_ue_id(getCxt(instance)->gtpInst, old_gNB_DU_ue_id_stack, du_ue_f1ap_id);
}
/* mandatory */
+14
View File
@@ -40,6 +40,16 @@
//Fixme: Uniq dirty DU instance, by global var, datamodel need better management
instance_t DUuniqInstance=0;
static instance_t du_create_gtpu_instance_to_cu(const f1ap_net_config_t *nc)
{
openAddr_t tmp = {0};
strncpy(tmp.originHost, nc->DU_f1_ip_address.ipv4_address, sizeof(tmp.originHost) - 1);
strncpy(tmp.destinationHost, nc->CU_f1_ip_address.ipv4_address, sizeof(tmp.destinationHost) - 1);
sprintf(tmp.originService, "%d", nc->DUport);
sprintf(tmp.destinationService, "%d", nc->CUport);
return gtpv1Init(tmp);
}
void du_task_send_sctp_association_req(instance_t instance, f1ap_net_config_t *nc)
{
DevAssert(nc != NULL);
@@ -116,6 +126,10 @@ void *F1AP_DU_task(void *arg) {
f1ap_net_config_t *nc = &F1AP_DU_REGISTER_REQ(msg).net_config;
createF1inst(myInstance, msgSetup, nc);
du_task_send_sctp_association_req(myInstance, nc);
instance_t gtpInst = du_create_gtpu_instance_to_cu(nc);
AssertFatal(gtpInst != 0, "cannot create DU F1-U GTP module\n");
getCxt(myInstance)->gtpInst = gtpInst;
DUuniqInstance = gtpInst;
} break;
case F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE:
+122 -160
View File
@@ -37,25 +37,82 @@
#include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h"
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
bool DURecvCb(protocol_ctxt_t *ctxt_pP,
const srb_flag_t srb_flagP,
const rb_id_t rb_idP,
const mui_t muiP,
const confirm_t confirmP,
const sdu_size_t sdu_buffer_sizeP,
unsigned char *const sdu_buffer_pP,
const pdcp_transmission_mode_t modeP,
const uint32_t *sourceL2Id,
const uint32_t *destinationL2Id)
static void f1ap_read_drb_qos_param(const F1AP_QoSFlowLevelQoSParameters_t *asn1_qos, f1ap_qos_flow_level_qos_parameters_t *drb_qos)
{
// The buffer comes from the stack in gtp-u thread, we have a make a separate buffer to enqueue in a inter-thread message queue
uint8_t *sdu = malloc16(sdu_buffer_sizeP);
memcpy(sdu, sdu_buffer_pP, sdu_buffer_sizeP);
du_rlc_data_req(ctxt_pP, srb_flagP, false, rb_idP, muiP, confirmP, sdu_buffer_sizeP, sdu);
return true;
f1ap_qos_characteristics_t *drb_qos_char = &drb_qos->qos_characteristics;
const F1AP_QoS_Characteristics_t *dRB_QoS_Char = &asn1_qos->qoS_Characteristics;
if (dRB_QoS_Char->present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) {
drb_qos_char->qos_type = non_dynamic;
drb_qos_char->non_dynamic.fiveqi = dRB_QoS_Char->choice.non_Dynamic_5QI->fiveQI;
drb_qos_char->non_dynamic.qos_priority_level = (dRB_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel != NULL)
? *dRB_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel
: -1;
} else {
drb_qos_char->qos_type = dynamic;
drb_qos_char->dynamic.fiveqi =
(dRB_QoS_Char->choice.dynamic_5QI->fiveQI != NULL) ? *dRB_QoS_Char->choice.dynamic_5QI->fiveQI : -1;
drb_qos_char->dynamic.qos_priority_level = dRB_QoS_Char->choice.dynamic_5QI->qoSPriorityLevel;
drb_qos_char->dynamic.packet_delay_budget = dRB_QoS_Char->choice.dynamic_5QI->packetDelayBudget;
drb_qos_char->dynamic.packet_error_rate.per_scalar = dRB_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Scalar;
drb_qos_char->dynamic.packet_error_rate.per_exponent = dRB_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Exponent;
}
/* nGRANallocationRetentionPriority */
drb_qos->alloc_reten_priority.priority_level = asn1_qos->nGRANallocationRetentionPriority.priorityLevel;
drb_qos->alloc_reten_priority.preemption_vulnerability = asn1_qos->nGRANallocationRetentionPriority.pre_emptionVulnerability;
drb_qos->alloc_reten_priority.preemption_capability = asn1_qos->nGRANallocationRetentionPriority.pre_emptionVulnerability;
}
static void f1ap_read_flows_mapped(const F1AP_Flows_Mapped_To_DRB_List_t *asn1_flows_mapped, f1ap_flows_mapped_to_drb_t *flows_mapped, int n)
{
for (int k = 0; k < n; k++) {
f1ap_flows_mapped_to_drb_t *flows_mapped_to_drb = flows_mapped + k;
const F1AP_Flows_Mapped_To_DRB_Item_t *flows_Mapped_To_Drb = asn1_flows_mapped->list.array[0] + k;
flows_mapped_to_drb->qfi = flows_Mapped_To_Drb->qoSFlowIdentifier;
/* QoS-Flow-Level-QoS-Parameters */
{
f1ap_qos_flow_level_qos_parameters_t *flow_qos = &flows_mapped_to_drb->qos_params;
const F1AP_QoSFlowLevelQoSParameters_t *Flow_QoS = &flows_Mapped_To_Drb->qoSFlowLevelQoSParameters;
/* QoS Characteristics*/
f1ap_qos_characteristics_t *flow_qos_char = &flow_qos->qos_characteristics;
const F1AP_QoS_Characteristics_t *Flow_QoS_Char = &Flow_QoS->qoS_Characteristics;
if (Flow_QoS_Char->present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) {
flow_qos_char->qos_type = non_dynamic;
flow_qos_char->non_dynamic.fiveqi = Flow_QoS_Char->choice.non_Dynamic_5QI->fiveQI;
flow_qos_char->non_dynamic.qos_priority_level = (Flow_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel != NULL)
? *Flow_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel
: -1;
} else {
flow_qos_char->qos_type = dynamic;
flow_qos_char->dynamic.fiveqi =
(Flow_QoS_Char->choice.dynamic_5QI->fiveQI != NULL) ? *Flow_QoS_Char->choice.dynamic_5QI->fiveQI : -1;
flow_qos_char->dynamic.qos_priority_level = Flow_QoS_Char->choice.dynamic_5QI->qoSPriorityLevel;
flow_qos_char->dynamic.packet_delay_budget = Flow_QoS_Char->choice.dynamic_5QI->packetDelayBudget;
flow_qos_char->dynamic.packet_error_rate.per_scalar = Flow_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Scalar;
flow_qos_char->dynamic.packet_error_rate.per_exponent = Flow_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Exponent;
}
/* nGRANallocationRetentionPriority */
flow_qos->alloc_reten_priority.priority_level = Flow_QoS->nGRANallocationRetentionPriority.priorityLevel;
flow_qos->alloc_reten_priority.preemption_vulnerability = Flow_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability;
flow_qos->alloc_reten_priority.preemption_capability = Flow_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability;
}
}
}
static void f1ap_read_drb_nssai(const F1AP_SNSSAI_t *asn1_nssai, nssai_t *nssai)
{
OCTET_STRING_TO_INT8(&asn1_nssai->sST, nssai->sst);
nssai->sd = 0xffffff;
if (asn1_nssai->sD != NULL)
memcpy((uint8_t *)&nssai->sd, asn1_nssai->sD->buf, 3);
}
int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
@@ -159,6 +216,36 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_i
drb_p->rlc_mode = RLC_MODE_TM;
break;
}
if (drbs_tobesetup_item_p->qoSInformation.present == F1AP_QoSInformation_PR_eUTRANQoS) {
AssertFatal(false, "Decode of eUTRANQoS is not implemented yet");
} // EUTRAN QoS Information
else {
/* 12.1.2 DRB_Information */
if (drbs_tobesetup_item_p->qoSInformation.present == F1AP_QoSInformation_PR_choice_extension) {
F1AP_QoSInformation_ExtIEs_t *ie =
(F1AP_QoSInformation_ExtIEs_t *)drbs_tobesetup_item_p->qoSInformation.choice.choice_extension;
if (ie->id == F1AP_ProtocolIE_ID_id_DRB_Information && ie->criticality == F1AP_Criticality_reject
&& ie->value.present == F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information) {
const F1AP_DRB_Information_t *dRB_Info = &ie->value.choice.DRB_Information;
f1ap_drb_information_t *drb_info = &drb_p->drb_info;
/* QoS-Flow-Level-QoS-Parameters */
/* QoS Characteristics*/
f1ap_read_drb_qos_param(&dRB_Info->dRB_QoS, &drb_info->drb_qos);
// 12.1.2.4 flows_Mapped_To_DRB_List
drb_info->flows_to_be_setup_length = dRB_Info->flows_Mapped_To_DRB_List.list.count;
drb_info->flows_mapped_to_drb = calloc(drb_info->flows_to_be_setup_length, sizeof(f1ap_flows_mapped_to_drb_t));
AssertFatal(drb_info->flows_mapped_to_drb, "could not allocate memory for drb_p->drb_info.flows_mapped_to_drb\n");
f1ap_read_flows_mapped(&dRB_Info->flows_Mapped_To_DRB_List, drb_info->flows_mapped_to_drb, drb_info->flows_to_be_setup_length);
/* S-NSSAI */
f1ap_read_drb_nssai(&dRB_Info->sNSSAI, &drb_p->nssai);
}
}
}
}
}
@@ -305,6 +392,7 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_set
ie7->criticality = F1AP_Criticality_ignore;
ie7->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DRBs_Setup_List;
for (int i=0; i< resp->drbs_to_be_setup_length; i++) {
f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i];
//
asn1cSequenceAdd(ie7->value.choice.DRBs_Setup_List.list,
F1AP_DRBs_Setup_ItemIEs_t, drbs_setup_item_ies);
@@ -315,14 +403,17 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_set
/* ADD */
F1AP_DRBs_Setup_Item_t *drbs_setup_item=&drbs_setup_item_ies->value.choice.DRBs_Setup_Item;
/* dRBID */
drbs_setup_item->dRBID = resp->drbs_to_be_setup[i].drb_id;
drbs_setup_item->dRBID = drb->drb_id;
/* OPTIONAL */
/* lCID */
//drbs_setup_item.lCID = (F1AP_LCID_t *)calloc(1, sizeof(F1AP_LCID_t));
//drbs_setup_item.lCID = 1L;
for (int j=0; j<resp->drbs_to_be_setup[i].up_dl_tnl_length; j++) {
for (int j = 0; j < drb->up_dl_tnl_length; j++) {
const f1ap_up_tnl_t *tnl = &drb->up_dl_tnl[j];
DevAssert(tnl->teid > 0);
/* ADD */
asn1cSequenceAdd(drbs_setup_item->dLUPTNLInformation_ToBeSetup_List.list,
F1AP_DLUPTNLInformation_ToBeSetup_Item_t, dLUPTNLInformation_ToBeSetup_Item);
@@ -330,12 +421,9 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_set
/* gTPTunnel */
asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel,gTPTunnel);
/* transportLayerAddress */
struct sockaddr_in addr= {0};
inet_pton(AF_INET, getCxt(0)->net_config.DU_f1_ip_address.ipv4_address, &addr.sin_addr.s_addr);
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(addr.sin_addr.s_addr,
&gTPTunnel->transportLayerAddress);
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, &gTPTunnel->transportLayerAddress);
/* gTP_TEID */
INT32_TO_OCTET_STRING(resp->drbs_to_be_setup[i].up_dl_tnl[j].teid, &gTPTunnel->gTP_TEID);
INT32_TO_OCTET_STRING(tnl->teid, &gTPTunnel->gTP_TEID);
} // for j
} // for i
@@ -772,16 +860,6 @@ int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_r
return 0;
}
static instance_t du_create_gtpu_instance_to_cu(char *CUaddr, uint16_t CUport, char *DUaddr, uint16_t DUport)
{
openAddr_t tmp = {0};
strncpy(tmp.originHost, DUaddr, sizeof(tmp.originHost)-1);
strncpy(tmp.destinationHost, CUaddr, sizeof(tmp.destinationHost)-1);
sprintf(tmp.originService, "%d", DUport);
sprintf(tmp.destinationService, "%d", CUport);
return gtpv1Init(tmp);
}
int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
{
F1AP_UEContextModificationRequest_t *container;
@@ -853,27 +931,6 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t
// 3GPP assumes GTP-U is on port 2152, but OAI is configurable
drb_p->up_ul_tnl[0].port = getCxt(instance)->net_config.CUport;
extern instance_t DUuniqInstance;
if (DUuniqInstance == 0) {
char gtp_tunnel_ip_address[32];
snprintf(gtp_tunnel_ip_address,
sizeof(gtp_tunnel_ip_address),
"%d.%d.%d.%d",
drb_p->up_ul_tnl[0].tl_address & 0xff,
(drb_p->up_ul_tnl[0].tl_address >> 8) & 0xff,
(drb_p->up_ul_tnl[0].tl_address >> 16) & 0xff,
(drb_p->up_ul_tnl[0].tl_address >> 24) & 0xff);
getCxt(instance)->gtpInst = du_create_gtpu_instance_to_cu(gtp_tunnel_ip_address,
getCxt(instance)->net_config.CUport,
getCxt(instance)->net_config.DU_f1_ip_address.ipv4_address,
getCxt(instance)->net_config.DUport);
AssertFatal(getCxt(instance)->gtpInst > 0, "Failed to create CU F1-U UDP listener");
// Fixme: fully inconsistent instances management
// dirty global var is a bad fix
extern instance_t legacyInstanceMapping;
legacyInstanceMapping = DUuniqInstance = getCxt(instance)->gtpInst;
}
switch (drbs_tobesetupmod_item_p->rLCMode) {
case F1AP_RLCMode_rlc_am:
drb_p->rlc_mode = RLC_MODE_AM;
@@ -894,101 +951,22 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t
(F1AP_QoSInformation_ExtIEs_t *)drbs_tobesetupmod_item_p->qoSInformation.choice.choice_extension;
if (ie->id == F1AP_ProtocolIE_ID_id_DRB_Information && ie->criticality == F1AP_Criticality_reject
&& ie->value.present == F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information) {
F1AP_DRB_Information_t *dRB_Info = &ie->value.choice.DRB_Information;
f1ap_drb_information_t *drb_info = &f1ap_ue_context_modification_req->drbs_to_be_setup->drb_info;
/* 12.1.2.1 dRB_QoS */
{
/* QoS-Flow-Level-QoS-Parameters */
f1ap_qos_flow_level_qos_parameters_t *drb_qos = &drb_info->drb_qos;
F1AP_QoSFlowLevelQoSParameters_t *dRB_QoS = &dRB_Info->dRB_QoS;
{
/* QoS Characteristics*/
f1ap_qos_characteristics_t *drb_qos_char = &drb_qos->qos_characteristics;
F1AP_QoS_Characteristics_t *dRB_QoS_Char = &dRB_QoS->qoS_Characteristics;
const F1AP_DRB_Information_t *dRB_Info = &ie->value.choice.DRB_Information;
f1ap_drb_information_t *drb_info = &drb_p->drb_info;
if (dRB_QoS_Char->present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) {
drb_qos_char->qos_type = non_dynamic;
drb_qos_char->non_dynamic.fiveqi = dRB_QoS_Char->choice.non_Dynamic_5QI->fiveQI;
drb_qos_char->non_dynamic.qos_priority_level = (dRB_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel != NULL)
? *dRB_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel
: -1;
} else {
drb_qos_char->qos_type = dynamic;
drb_qos_char->dynamic.fiveqi =
(dRB_QoS_Char->choice.dynamic_5QI->fiveQI != NULL) ? *dRB_QoS_Char->choice.dynamic_5QI->fiveQI : -1;
drb_qos_char->dynamic.qos_priority_level = dRB_QoS_Char->choice.dynamic_5QI->qoSPriorityLevel;
drb_qos_char->dynamic.packet_delay_budget = dRB_QoS_Char->choice.dynamic_5QI->packetDelayBudget;
drb_qos_char->dynamic.packet_error_rate.per_scalar = dRB_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Scalar;
drb_qos_char->dynamic.packet_error_rate.per_exponent =
dRB_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Exponent;
}
}
/* nGRANallocationRetentionPriority */
drb_qos->alloc_reten_priority.priority_level = dRB_QoS->nGRANallocationRetentionPriority.priorityLevel;
drb_qos->alloc_reten_priority.preemption_vulnerability =
dRB_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability;
drb_qos->alloc_reten_priority.preemption_capability =
dRB_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability;
} // dRB_QoS
/* QoS-Flow-Level-QoS-Parameters */
/* QoS Characteristics*/
f1ap_read_drb_qos_param(&dRB_Info->dRB_QoS, &drb_info->drb_qos);
// 12.1.2.4 flows_Mapped_To_DRB_List
drb_info->flows_to_be_setup_length = dRB_Info->flows_Mapped_To_DRB_List.list.count;
drb_info->flows_mapped_to_drb = calloc(drb_info->flows_to_be_setup_length, sizeof(f1ap_flows_mapped_to_drb_t));
AssertFatal(drb_info->flows_mapped_to_drb, "could not allocate memory for drb_p->drb_info.flows_mapped_to_drb\n");
for (int k = 0; k < drb_p->drb_info.flows_to_be_setup_length; k++) {
f1ap_flows_mapped_to_drb_t *flows_mapped_to_drb = drb_info->flows_mapped_to_drb + k;
F1AP_Flows_Mapped_To_DRB_Item_t *flows_Mapped_To_Drb = dRB_Info->flows_Mapped_To_DRB_List.list.array[0] + k;
flows_mapped_to_drb->qfi = flows_Mapped_To_Drb->qoSFlowIdentifier;
/* QoS-Flow-Level-QoS-Parameters */
{
f1ap_qos_flow_level_qos_parameters_t *flow_qos = &flows_mapped_to_drb->qos_params;
F1AP_QoSFlowLevelQoSParameters_t *Flow_QoS = &flows_Mapped_To_Drb->qoSFlowLevelQoSParameters;
/* QoS Characteristics*/
{
f1ap_qos_characteristics_t *flow_qos_char = &flow_qos->qos_characteristics;
F1AP_QoS_Characteristics_t *Flow_QoS_Char = &Flow_QoS->qoS_Characteristics;
if (Flow_QoS_Char->present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) {
flow_qos_char->qos_type = non_dynamic;
flow_qos_char->non_dynamic.fiveqi = Flow_QoS_Char->choice.non_Dynamic_5QI->fiveQI;
flow_qos_char->non_dynamic.qos_priority_level =
(Flow_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel != NULL)
? *Flow_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel
: -1;
} else {
flow_qos_char->qos_type = dynamic;
flow_qos_char->dynamic.fiveqi =
(Flow_QoS_Char->choice.dynamic_5QI->fiveQI != NULL) ? *Flow_QoS_Char->choice.dynamic_5QI->fiveQI : -1;
flow_qos_char->dynamic.qos_priority_level = Flow_QoS_Char->choice.dynamic_5QI->qoSPriorityLevel;
flow_qos_char->dynamic.packet_delay_budget = Flow_QoS_Char->choice.dynamic_5QI->packetDelayBudget;
flow_qos_char->dynamic.packet_error_rate.per_scalar =
Flow_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Scalar;
flow_qos_char->dynamic.packet_error_rate.per_exponent =
Flow_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Exponent;
}
}
/* nGRANallocationRetentionPriority */
flow_qos->alloc_reten_priority.priority_level = Flow_QoS->nGRANallocationRetentionPriority.priorityLevel;
flow_qos->alloc_reten_priority.preemption_vulnerability =
Flow_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability;
flow_qos->alloc_reten_priority.preemption_capability =
Flow_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability;
}
}
f1ap_read_flows_mapped(&dRB_Info->flows_Mapped_To_DRB_List, drb_info->flows_mapped_to_drb, drb_info->flows_to_be_setup_length);
/* S-NSSAI */
OCTET_STRING_TO_INT8(&dRB_Info->sNSSAI.sST, drb_p->nssai.sst);
if (dRB_Info->sNSSAI.sD != NULL)
memcpy((uint8_t *)&drb_p->nssai.sd, dRB_Info->sNSSAI.sD->buf, 3);
else
drb_p->nssai.sd = 0xffffff;
f1ap_read_drb_nssai(&dRB_Info->sNSSAI, &drb_p->nssai);
}
}
}
@@ -1008,7 +986,6 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t
DevAssert(tbrel->id == F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item);
DevAssert(tbrel->value.present == F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item);
f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id = tbrel->value.choice.DRBs_ToBeReleased_Item.dRBID;
newGtpuDeleteOneTunnel(0, f1ap_ue_context_modification_req->gNB_DU_ue_id, f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id);
}
}
@@ -1166,20 +1143,8 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_cont
drbs_setupmod_item->dRBID = resp->drbs_to_be_setup[i].drb_id;
for (int j=0; j<resp->drbs_to_be_setup[i].up_dl_tnl_length; j++) {
f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i];
transport_layer_addr_t tl_addr = {0};
memcpy(tl_addr.buffer, &drb->up_ul_tnl[0].tl_address, sizeof(drb->up_ul_tnl[0].tl_address));
tl_addr.length = sizeof(drb->up_ul_tnl[0].tl_address) * 8;
drb->up_dl_tnl[j].teid = newGtpuCreateTunnel(getCxt(0)->gtpInst,
resp->gNB_DU_ue_id,
drb->drb_id,
drb->drb_id,
drb->up_ul_tnl[j].teid,
-1, // no qfi
tl_addr,
drb->up_ul_tnl[0].port,
DURecvCb,
NULL);
const f1ap_up_tnl_t *tnl = &resp->drbs_to_be_setup[i].up_dl_tnl[j];
DevAssert(tnl->teid > 0);
/* ADD */
asn1cSequenceAdd(drbs_setupmod_item->dLUPTNLInformation_ToBeSetup_List.list,
@@ -1188,12 +1153,9 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_cont
/* gTPTunnel */
asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel,gTPTunnel);
/* transportLayerAddress */
struct sockaddr_in addr= {0};
inet_pton(AF_INET, getCxt(0)->net_config.DU_f1_ip_address.ipv4_address, &addr.sin_addr.s_addr);
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(addr.sin_addr.s_addr,
&gTPTunnel->transportLayerAddress);
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, &gTPTunnel->transportLayerAddress);
/* gTP_TEID */
INT32_TO_OCTET_STRING(resp->drbs_to_be_setup[i].up_dl_tnl[j].teid, &gTPTunnel->gTP_TEID);
INT32_TO_OCTET_STRING(tnl->teid, &gTPTunnel->gTP_TEID);
} // for j
} // for i
}
+22 -18
View File
@@ -108,8 +108,7 @@ add_msg3(module_id_t module_idP, int CC_id, RA_t *ra, frame_t frameP,
uint8_t pusch_maxNumRepetitionCEmodeA_r13;
ul_req = &mac->UL_req_tmp[CC_id][ra->Msg3_subframe];
ul_req_body = &ul_req->ul_config_request_body;
AssertFatal(ra->state != IDLE, "RA is not active for RA %X\n",
ra->rnti);
AssertFatal(ra->eRA_state != IDLE, "RA is not active for RA %X\n", ra->rnti);
if (ra->rach_resource_type > 0) {
LOG_D (MAC, "[eNB %d][RAPROC] Frame %d, Subframe %d : CC_id %d CE level %d is active, Msg3 in (%d,%d)\n",
@@ -448,7 +447,7 @@ void generate_Msg2(module_id_t module_idP,
/* Program UL processing for Msg3, same as regular LTE */
get_Msg3alloc (&cc[CC_idP], subframeP, frameP, &ra->Msg3_frame, &ra->Msg3_subframe);
add_msg3 (module_idP, CC_idP, ra, frameP, subframeP);
ra->state = WAITMSG3;
ra->eRA_state = WAITMSG3;
/* DL request */
LOG_D(MAC, "[eNB %d][RAPROC] Frame %d, Subframe %d : In generate_Msg2, Programming TX Req\n",
module_idP,
@@ -467,8 +466,12 @@ void generate_Msg2(module_id_t module_idP,
} else {
if ((ra->Msg2_frame == frameP) && (ra->Msg2_subframe == subframeP)) {
LOG_D(MAC,
"[eNB %d] CC_id %d Frame %d, subframeP %d: Generating RAR DCI, state %d\n",
module_idP, CC_idP, frameP, subframeP, ra->state);
"[eNB %d] CC_id %d Frame %d, subframeP %d: Generating RAR DCI, state %s\n",
module_idP,
CC_idP,
frameP,
subframeP,
era_text[ra->eRA_state]);
// Allocate 4 PRBS starting in RB 0
first_rb = 0;
vrb_map[first_rb] = 1;
@@ -537,7 +540,7 @@ void generate_Msg2(module_id_t module_idP,
ra->Msg3_subframe);
fill_rar(module_idP, CC_idP, ra, frameP, cc[CC_idP].RAR_pdu.payload, N_RB_DL, 7);
add_msg3(module_idP, CC_idP, ra, frameP, subframeP);
ra->state = WAITMSG3;
ra->eRA_state = WAITMSG3;
LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d: state:WAITMSG3\n", module_idP, frameP, subframeP);
T(T_ENB_MAC_UE_DL_RAR_PDU_WITH_DATA, T_INT(module_idP),
T_INT(CC_idP), T_INT(ra->RA_rnti), T_INT(frameP),
@@ -819,7 +822,7 @@ generate_Msg4(module_id_t module_idP,
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = (10 * frameP) + subframeP;
dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.drms_table_flag = 0;
dl_req_body->number_pdu++;
ra->state = WAITMSG4ACK;
ra->eRA_state = WAITMSG4ACK;
lcid = 0;
UE_info->UE_sched_ctrl[UE_id].round[CC_idP][ra->harq_pid] = 0;
msg4_header = 1 + 6 + 1; // CR header, CR CE, SDU header
@@ -975,7 +978,7 @@ generate_Msg4(module_id_t module_idP,
dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, ra->rnti)) {
dl_req_body->number_dci++;
dl_req_body->number_pdu++;
ra->state = WAITMSG4ACK;
ra->eRA_state = WAITMSG4ACK;
LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d: state:WAITMSG4ACK\n", module_idP, frameP, subframeP);
// increment Absolute subframe by 8 for Msg4 retransmission
LOG_D(MAC,
@@ -1219,7 +1222,7 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP,
LOG_D(MAC,
"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged\n",
module_idP, CC_idP, frameP, subframeP);
ra->state = IDLE;
ra->eRA_state = IDLE;
LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d: state:IDLE\n", module_idP, frameP, subframeP);
UE_id = find_UE_id(module_idP, ra->rnti);
DevAssert(UE_id != -1);
@@ -1246,11 +1249,11 @@ schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) {
for (i = 0; i < NB_RA_PROC_MAX; i++) {
ra = (RA_t *) & cc[CC_id].ra[i];
if (ra->state == MSG2)
if (ra->eRA_state == MSG2)
generate_Msg2(module_idP, CC_id, frameP, subframeP, ra);
else if (ra->state == MSG4 && ra->Msg4_frame == frameP && ra->Msg4_subframe == subframeP )
else if (ra->eRA_state == MSG4 && ra->Msg4_frame == frameP && ra->Msg4_subframe == subframeP)
generate_Msg4(module_idP, CC_id, frameP, subframeP, ra);
else if (ra->state == WAITMSG4ACK)
else if (ra->eRA_state == WAITMSG4ACK)
check_Msg4_retransmission(module_idP, CC_id, frameP,
subframeP, ra);
} // for i=0 .. N_RA_PROC-1
@@ -1309,11 +1312,11 @@ initiate_ra_proc(module_id_t module_idP,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0);
for (i = 0; i < NB_RA_PROC_MAX; i++) {
if (ra[i].state == IDLE) {
if (ra[i].eRA_state == IDLE) {
int loop = 0;
LOG_D(MAC, "Frame %d, Subframe %d: Activating RA process %d\n",
frameP, subframeP, i);
ra[i].state = MSG2;
ra[i].eRA_state = MSG2;
ra[i].Msg4_delay_cnt=0;
ra[i].timing_offset = timing_offset;
ra[i].preamble_subframe = subframeP;
@@ -1410,7 +1413,8 @@ initiate_ra_proc(module_id_t module_idP,
ra[i].preamble_index = preamble_index;
failure_cnt = 0;
LOG_I(MAC,
"[eNB %d][RAPROC] CC_id %d Frame %d Activating RAR generation in Frame %d, subframe %d for process %d, rnti %x, state %d\n",
"[eNB %d][RAPROC] CC_id %d Frame %d Activating RAR generation in Frame %d, subframe %d for process %d, rnti %x, state "
"%d\n",
module_idP,
CC_id,
frameP,
@@ -1418,7 +1422,7 @@ initiate_ra_proc(module_id_t module_idP,
ra[i].Msg2_subframe,
i,
ra[i].rnti,
ra[i].state);
ra[i].eRA_state);
return;
}
}
@@ -1445,7 +1449,7 @@ cancel_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP,
for (i = 0; i < NB_RA_PROC_MAX; i++) {
if (rnti == ra[i].rnti) {
ra[i].state = IDLE;
ra[i].eRA_state = IDLE;
ra[i].timing_offset = 0;
ra[i].RRC_timer = 20;
ra[i].rnti = 0;
@@ -1461,7 +1465,7 @@ void clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP) {
for (i = 0; i < NB_RA_PROC_MAX; i++) {
LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Clear Random access information rnti %x\n", module_idP, CC_id, frameP, ra[i].rnti);
ra[i].state = IDLE;
ra[i].eRA_state = IDLE;
ra[i].timing_offset = 0;
ra[i].RRC_timer = 20;
ra[i].rnti = 0;
+2 -2
View File
@@ -428,11 +428,11 @@ void check_ra_rnti_mui(module_id_t mod_id, int CC_id, frame_t f, sub_frame_t sf,
int harq_pid = frame_subframe2_dl_harq_pid(tdd_config, f, sf);
RA_t *ra = &RC.mac[mod_id]->common_channels[CC_id].ra[0];
for (uint8_t ra_ii = 0; ra_ii < NB_RA_PROC_MAX; ra_ii++, ra++) {
if ((ra->rnti == rnti) && (ra->state == MSGCRNTI)) {
if ((ra->rnti == rnti) && (ra->eRA_state == MSGCRNTI)) {
for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) {
if (ra->crnti_rrc_mui == rlc_am_mui.rrc_mui[mui_num]) {
ra->crnti_harq_pid = harq_pid;
ra->state = MSGCRNTI_ACK;
ra->eRA_state = MSGCRNTI_ACK;
break;
}
}
+3 -3
View File
@@ -1583,11 +1583,11 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
RA_t *ra = &eNB->common_channels[CC_id].ra[0];
for (uint8_t ra_ii = 0; ra_ii < NB_RA_PROC_MAX; ra_ii++) {
if((ra[ra_ii].rnti == rnti) && (ra[ra_ii].state == MSGCRNTI)) {
if ((ra[ra_ii].rnti == rnti) && (ra[ra_ii].eRA_state == MSGCRNTI)) {
for(uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) {
if(ra[ra_ii].crnti_rrc_mui == rlc_am_mui.rrc_mui[mui_num]) {
ra[ra_ii].crnti_harq_pid = harq_pid;
ra[ra_ii].state = MSGCRNTI_ACK;
ra[ra_ii].eRA_state = MSGCRNTI_ACK;
break;
}
}
@@ -2869,7 +2869,7 @@ schedule_ulsch_fairRR(module_id_t module_idP, frame_t frameP,
// Msg3 is using 1 PRB so we need to increase first_rb accordingly
// not sure about the break (can there be more than 1 active RA procedure?)
for (i=0; i<NB_RA_PROC_MAX; i++) {
if ((cc->ra[i].state == WAITMSG3) &&(cc->ra[i].Msg3_subframe == sched_subframe)) {
if ((cc->ra[i].eRA_state == WAITMSG3) && (cc->ra[i].Msg3_subframe == sched_subframe)) {
ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_MSG3;
if (cc->tdd_Config == NULL) {
@@ -2005,12 +2005,9 @@ find_RA_id(module_id_t mod_idP,
RA_t *ra = (RA_t *) &RC.mac[mod_idP]->common_channels[CC_idP].ra[0];
for (RA_id = 0; RA_id < NB_RA_PROC_MAX; RA_id++) {
LOG_D(MAC, "Checking RA_id %d for %x : state %d\n",
RA_id,
rntiP,
ra[RA_id].state);
LOG_D(MAC, "Checking RA_id %d for %x : state %s\n", RA_id, rntiP, era_text[ra[RA_id].eRA_state]);
if (ra[RA_id].state != IDLE && ra[RA_id].rnti == rntiP)
if (ra[RA_id].eRA_state != IDLE && ra[RA_id].rnti == rntiP)
return RA_id;
}
@@ -3970,7 +3967,7 @@ extract_harq(module_id_t mod_idP,
if (sched_ctl->round[CC_idP][harq_pid] == 8) {
for (uint8_t ra_i = 0; ra_i < NB_RA_PROC_MAX; ra_i++) {
if (ra[ra_i].rnti == rnti && ra[ra_i].state == WAITMSG4ACK) {
if (ra[ra_i].rnti == rnti && ra[ra_i].eRA_state == WAITMSG4ACK) {
//Msg NACK num to MAC ,remove UE
// add UE info to freeList
LOG_I(RRC, "put UE %x into freeList\n",
@@ -3985,7 +3982,7 @@ extract_harq(module_id_t mod_idP,
}
for (uint8_t ra_i = 0; ra_i < NB_RA_PROC_MAX; ra_i++) {
if (ra[ra_i].rnti == rnti && ra[ra_i].state == MSGCRNTI_ACK && ra[ra_i].crnti_harq_pid == harq_pid) {
if (ra[ra_i].rnti == rnti && ra[ra_i].eRA_state == MSGCRNTI_ACK && ra[ra_i].crnti_harq_pid == harq_pid) {
LOG_D(MAC,"CRNTI Reconfiguration: ACK %d rnti %x round %d frame %d subframe %d \n",
harq_indication_tdd->harq_data[0].bundling.value_0,
rnti,
@@ -4077,7 +4074,7 @@ extract_harq(module_id_t mod_idP,
RA_t *ra = &eNB->common_channels[CC_idP].ra[0];
for (uint8_t ra_i = 0; ra_i < NB_RA_PROC_MAX; ra_i++) {
if (ra[ra_i].rnti == rnti && ra[ra_i].state == MSGCRNTI_ACK && ra[ra_i].crnti_harq_pid == harq_pid) {
if (ra[ra_i].rnti == rnti && ra[ra_i].eRA_state == MSGCRNTI_ACK && ra[ra_i].crnti_harq_pid == harq_pid) {
LOG_D(MAC,"CRNTI Reconfiguration: ACK %d rnti %x round %d frame %d subframe %d \n",
pdu[0],
rnti,
@@ -4122,7 +4119,7 @@ extract_harq(module_id_t mod_idP,
if (sched_ctl->round[CC_idP][harq_pid] == 8) {
for (uint8_t ra_i = 0; ra_i < NB_RA_PROC_MAX; ra_i++) {
if((ra[ra_i].rnti == rnti) && (ra[ra_i].state == WAITMSG4ACK)) {
if ((ra[ra_i].rnti == rnti) && (ra[ra_i].eRA_state == WAITMSG4ACK)) {
// Msg NACK num to MAC ,remove UE
// add UE info to freeList
LOG_I(RRC, "put UE %x into freeList\n",
+5 -4
View File
@@ -522,7 +522,7 @@ rx_sdu(const module_id_t enb_mod_idP,
/* Received a new rnti */
if (ret == 0) {
ra->state = MSGCRNTI;
ra->eRA_state = MSGCRNTI;
LOG_I(MAC, "[eNB %d] Frame %d, Subframe %d CC_id %d : (rnti %x UE_id %d) Received rnti(Msg4)\n",
enb_mod_idP,
frameP,
@@ -729,13 +729,14 @@ rx_sdu(const module_id_t enb_mod_idP,
if (RA_id != -1) {
RA_t *ra = &(mac->common_channels[CC_idP].ra[RA_id]);
LOG_D(MAC, "[mac %d][RAPROC] CC_id %d Checking proc %d : rnti (%x, %x), state %d\n",
LOG_D(MAC,
"[mac %d][RAPROC] CC_id %d Checking proc %d : rnti (%x, %x), state %s\n",
enb_mod_idP,
CC_idP,
RA_id,
ra->rnti,
current_rnti,
ra->state);
era_text[ra->eRA_state]);
if (UE_id < 0) {
memcpy(&(ra->cont_res_id[0]), payload_ptr, 6);
@@ -788,7 +789,7 @@ rx_sdu(const module_id_t enb_mod_idP,
}
// prepare transmission of Msg4
ra->state = MSG4;
ra->eRA_state = MSG4;
if(mac->common_channels[CC_idP].tdd_Config != NULL) {
switch(mac->common_channels[CC_idP].tdd_Config->subframeAssignment) {
+4 -2
View File
@@ -505,7 +505,9 @@ typedef struct {
} __attribute__ ((__packed__)) ULDCH_PDU;
/*!\brief RA process state*/
typedef enum { IDLE = 0, MSG2, WAITMSG3, MSG4, WAITMSG4ACK, MSGCRNTI, MSGCRNTI_ACK } RA_state;
typedef enum { IDLE = 0, MSG2, WAITMSG3, MSG4, WAITMSG4ACK, MSGCRNTI, MSGCRNTI_ACK } eRA_state;
static const char *const era_text[] = {"IDLE", "Ms2", "WAITMSG3", "WAITMSG4ACK", "MSGCRNTI", "MSGCRNTIACK"};
/*!\brief UE DLSCH scheduling states*/
typedef enum { S_DL_NONE = 0, S_DL_SCHEDULED } UE_DLSCH_STATUS;
/*!\brief scheduler mode */
@@ -1032,7 +1034,7 @@ typedef struct {
/*! \brief eNB template for the Random access information */
typedef struct {
/// Flag to indicate this process is active
RA_state state;
eRA_state eRA_state;
/// Subframe where preamble was received
uint8_t preamble_subframe;
/// Subframe where Msg2 is to be sent
+1 -1
View File
@@ -430,7 +430,7 @@ typedef struct prach_occasion_info {
// PRACH occasion slot details
// A PRACH occasion slot is a series of PRACH occasions in time (symbols) and frequency
typedef struct prach_occasion_slot {
prach_occasion_info_t prach_occasion[MAX_TDM][MAX_FDM]; // Starting symbol of each PRACH occasions in a slot
prach_occasion_info_t *prach_occasion; // Starting symbol of each PRACH occasions in a slot
uint8_t nb_of_prach_occasion_in_time;
uint8_t nb_of_prach_occasion_in_freq;
} prach_occasion_slot_t;
@@ -2248,118 +2248,6 @@ static const uint16_t table_7_3_1_1_2_32[3][15] = {
{0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};
void get_delta_arfcn(int i, uint32_t nrarfcn, uint64_t N_OFFs)
{
uint32_t delta_arfcn = nrarfcn - N_OFFs;
if(delta_arfcn % (nr_bandtable[i].step_size) != 0)
LOG_E(NR_MAC, "nrarfcn %u is not on the channel raster for step size %lu\n", nrarfcn, nr_bandtable[i].step_size);
}
uint32_t to_nrarfcn(int nr_bandP,
uint64_t dl_CarrierFreq,
uint8_t scs_index,
uint32_t bw)
{
uint64_t dl_CarrierFreq_by_1k = dl_CarrierFreq / 1000;
int bw_kHz = bw / 1000;
uint32_t nrarfcn;
int i = get_nr_table_idx(nr_bandP, scs_index);
LOG_I(NR_MAC,"Searching for nr band %d DL Carrier frequency %llu bw %u\n",nr_bandP,(long long unsigned int)dl_CarrierFreq,bw);
AssertFatal(dl_CarrierFreq_by_1k >= nr_bandtable[i].dl_min,
"Band %d, bw %u : DL carrier frequency %llu kHz < %llu\n",
nr_bandP, bw, (long long unsigned int)dl_CarrierFreq_by_1k,
(long long unsigned int)nr_bandtable[i].dl_min);
AssertFatal(dl_CarrierFreq_by_1k <= (nr_bandtable[i].dl_max - bw_kHz/2),
"Band %d, dl_CarrierFreq %llu bw %u: DL carrier frequency %llu kHz > %llu\n",
nr_bandP, (long long unsigned int)dl_CarrierFreq,bw, (long long unsigned int)dl_CarrierFreq_by_1k,
(long long unsigned int)(nr_bandtable[i].dl_max - bw_kHz/2));
int deltaFglobal = 60;
uint32_t N_REF_Offs = 2016667;
uint64_t F_REF_Offs_khz = 24250080;
if (dl_CarrierFreq < 24.25e9) {
deltaFglobal = 15;
N_REF_Offs = 600000;
F_REF_Offs_khz = 3000000;
}
if (dl_CarrierFreq < 3e9) {
deltaFglobal = 5;
N_REF_Offs = 0;
F_REF_Offs_khz = 0;
}
// This is equation before Table 5.4.2.1-1 in 38101-1-f30
// F_REF=F_REF_Offs + deltaF_Global(N_REF-NREF_REF_Offs)
nrarfcn = (((dl_CarrierFreq_by_1k - F_REF_Offs_khz)/deltaFglobal)+N_REF_Offs);
//get_delta_arfcn(i, nrarfcn, nr_bandtable[i].N_OFFs_DL);
return nrarfcn;
}
// This function computes the RF reference frequency from the NR-ARFCN according to 5.4.2.1 of 3GPP TS 38.104
// this function applies to both DL and UL
uint64_t from_nrarfcn(int nr_bandP,
uint8_t scs_index,
uint32_t nrarfcn)
{
int deltaFglobal = 5;
uint32_t N_REF_Offs = 0;
uint64_t F_REF_Offs_khz = 0;
uint64_t N_OFFs, frequency, freq_min;
int i = get_nr_table_idx(nr_bandP, scs_index);
if (nrarfcn > 599999 && nrarfcn < 2016667) {
deltaFglobal = 15;
N_REF_Offs = 600000;
F_REF_Offs_khz = 3000000;
}
if (nrarfcn > 2016666 && nrarfcn < 3279166) {
deltaFglobal = 60;
N_REF_Offs = 2016667;
F_REF_Offs_khz = 24250080;
}
int32_t delta_duplex = get_delta_duplex(nr_bandP, scs_index);
if (delta_duplex <= 0){ // DL band >= UL band
if (nrarfcn >= nr_bandtable[i].N_OFFs_DL){ // is TDD of FDD DL
N_OFFs = nr_bandtable[i].N_OFFs_DL;
freq_min = nr_bandtable[i].dl_min;
} else {// is FDD UL
N_OFFs = nr_bandtable[i].N_OFFs_DL + delta_duplex/deltaFglobal;
freq_min = nr_bandtable[i].ul_min;
}
} else { // UL band > DL band
if (nrarfcn >= nr_bandtable[i].N_OFFs_DL + delta_duplex/deltaFglobal){ // is FDD UL
N_OFFs = nr_bandtable[i].N_OFFs_DL + delta_duplex/deltaFglobal;
freq_min = nr_bandtable[i].ul_min;
} else { // is FDD DL
N_OFFs = nr_bandtable[i].N_OFFs_DL;
freq_min = nr_bandtable[i].dl_min;
}
}
LOG_D(NR_MAC, "Frequency from NR-ARFCN for N_OFFs %lu, duplex spacing %d KHz, deltaFglobal %d KHz\n", N_OFFs, delta_duplex, deltaFglobal);
AssertFatal(nrarfcn >= N_OFFs,"nrarfcn %u < N_OFFs[%d] %llu\n", nrarfcn, nr_bandtable[i].band, (long long unsigned int)N_OFFs);
get_delta_arfcn(i, nrarfcn, N_OFFs);
frequency = 1000 * (F_REF_Offs_khz + (nrarfcn - N_REF_Offs) * deltaFglobal);
LOG_D(NR_MAC, "Computing frequency (nrarfcn %llu => %llu KHz (freq_min %llu KHz, NR band %d N_OFFs %llu))\n",
(unsigned long long)nrarfcn,
(unsigned long long)frequency/1000,
(unsigned long long)freq_min,
nr_bandP,
(unsigned long long)N_OFFs);
return frequency;
}
void nr_get_tbs_dl(nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
int x_overhead,
uint8_t numdmrscdmgroupnodata,
@@ -55,10 +55,6 @@ uint32_t get_Y(const NR_SearchSpace_t *ss, int slot, rnti_t rnti);
uint8_t get_BG(uint32_t A, uint16_t R);
uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t dl_nrarfcn);
uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw);
int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config,
int dci_format,
int dmrs_TypeA_Position,
+150 -131
View File
@@ -427,18 +427,18 @@ static void modlist_ss(NR_SearchSpace_t *source, NR_SearchSpace_t *target)
{
target->searchSpaceId = source->searchSpaceId;
if (source->controlResourceSetId)
UPDATE_MAC_IE(target->controlResourceSetId, source->controlResourceSetId, NR_ControlResourceSetId_t);
UPDATE_IE(target->controlResourceSetId, source->controlResourceSetId, NR_ControlResourceSetId_t);
if (source->monitoringSlotPeriodicityAndOffset)
UPDATE_MAC_IE(target->monitoringSlotPeriodicityAndOffset,
source->monitoringSlotPeriodicityAndOffset,
struct NR_SearchSpace__monitoringSlotPeriodicityAndOffset);
UPDATE_MAC_IE(target->duration, source->duration, long);
UPDATE_IE(target->monitoringSlotPeriodicityAndOffset,
source->monitoringSlotPeriodicityAndOffset,
struct NR_SearchSpace__monitoringSlotPeriodicityAndOffset);
UPDATE_IE(target->duration, source->duration, long);
if (source->monitoringSymbolsWithinSlot)
UPDATE_MAC_IE(target->monitoringSymbolsWithinSlot, source->monitoringSymbolsWithinSlot, BIT_STRING_t);
UPDATE_IE(target->monitoringSymbolsWithinSlot, source->monitoringSymbolsWithinSlot, BIT_STRING_t);
if (source->nrofCandidates)
UPDATE_MAC_IE(target->nrofCandidates, source->nrofCandidates, struct NR_SearchSpace__nrofCandidates);
UPDATE_IE(target->nrofCandidates, source->nrofCandidates, struct NR_SearchSpace__nrofCandidates);
if (source->searchSpaceType)
UPDATE_MAC_IE(target->searchSpaceType, source->searchSpaceType, struct NR_SearchSpace__searchSpaceType);
UPDATE_IE(target->searchSpaceType, source->searchSpaceType, struct NR_SearchSpace__searchSpaceType);
}
static NR_SearchSpace_t *get_common_search_space(const NR_UE_MAC_INST_t *mac,
@@ -493,7 +493,7 @@ static void configure_common_ss_coreset(const NR_UE_MAC_INST_t *mac,
get_common_search_space(mac, pdcch_ConfigCommon->commonSearchSpaceList, pdcch, *pdcch_ConfigCommon->pagingSearchSpace);
}
UPDATE_MAC_IE(pdcch->commonControlResourceSet, pdcch_ConfigCommon->commonControlResourceSet, NR_ControlResourceSet_t);
UPDATE_IE(pdcch->commonControlResourceSet, pdcch_ConfigCommon->commonControlResourceSet, NR_ControlResourceSet_t);
}
}
@@ -516,15 +516,15 @@ static void modlist_coreset(NR_ControlResourceSet_t *source, NR_ControlResourceS
target->cce_REG_MappingType.choice.interleaved->reg_BundleSize = source->cce_REG_MappingType.choice.interleaved->reg_BundleSize;
target->cce_REG_MappingType.choice.interleaved->interleaverSize =
source->cce_REG_MappingType.choice.interleaved->interleaverSize;
UPDATE_MAC_IE(target->cce_REG_MappingType.choice.interleaved->shiftIndex,
source->cce_REG_MappingType.choice.interleaved->shiftIndex,
long);
UPDATE_IE(target->cce_REG_MappingType.choice.interleaved->shiftIndex,
source->cce_REG_MappingType.choice.interleaved->shiftIndex,
long);
} else {
free(shiftIndex);
target->cce_REG_MappingType = source->cce_REG_MappingType;
}
UPDATE_MAC_IE(target->tci_PresentInDCI, source->tci_PresentInDCI, long);
UPDATE_MAC_IE(target->pdcch_DMRS_ScramblingID, source->pdcch_DMRS_ScramblingID, long);
UPDATE_IE(target->tci_PresentInDCI, source->tci_PresentInDCI, long);
UPDATE_IE(target->pdcch_DMRS_ScramblingID, source->pdcch_DMRS_ScramblingID, long);
// TCI States
if (source->tci_StatesPDCCH_ToReleaseList) {
for (int i = 0; i < source->tci_StatesPDCCH_ToReleaseList->list.count; i++) {
@@ -553,9 +553,9 @@ static void modlist_coreset(NR_ControlResourceSet_t *source, NR_ControlResourceS
ASN_SEQUENCE_ADD(&target->tci_StatesPDCCH_ToAddList->list, source->tci_StatesPDCCH_ToAddList->list.array[i]);
}
} else
UPDATE_MAC_IE(target->tci_StatesPDCCH_ToAddList,
source->tci_StatesPDCCH_ToAddList,
struct NR_ControlResourceSet__tci_StatesPDCCH_ToAddList);
UPDATE_IE(target->tci_StatesPDCCH_ToAddList,
source->tci_StatesPDCCH_ToAddList,
struct NR_ControlResourceSet__tci_StatesPDCCH_ToAddList);
}
// end TCI States
}
@@ -812,14 +812,14 @@ void nr_rrc_mac_config_req_mib(module_id_t module_id,
static void setup_puschpowercontrol(NR_PUSCH_PowerControl_t *source, NR_PUSCH_PowerControl_t *target)
{
UPDATE_MAC_IE(target->tpc_Accumulation, source->tpc_Accumulation, long);
UPDATE_MAC_IE(target->msg3_Alpha, source->msg3_Alpha, NR_Alpha_t);
UPDATE_IE(target->tpc_Accumulation, source->tpc_Accumulation, long);
UPDATE_IE(target->msg3_Alpha, source->msg3_Alpha, NR_Alpha_t);
if (source->p0_NominalWithoutGrant)
UPDATE_MAC_IE(target->p0_NominalWithoutGrant, source->p0_NominalWithoutGrant, long);
UPDATE_IE(target->p0_NominalWithoutGrant, source->p0_NominalWithoutGrant, long);
if (source->p0_AlphaSets)
UPDATE_MAC_IE(target->p0_AlphaSets, source->p0_AlphaSets, struct NR_PUSCH_PowerControl__p0_AlphaSets);
UPDATE_MAC_IE(target->twoPUSCH_PC_AdjustmentStates, source->twoPUSCH_PC_AdjustmentStates, long);
UPDATE_MAC_IE(target->deltaMCS, source->deltaMCS, long);
UPDATE_IE(target->p0_AlphaSets, source->p0_AlphaSets, struct NR_PUSCH_PowerControl__p0_AlphaSets);
UPDATE_IE(target->twoPUSCH_PC_AdjustmentStates, source->twoPUSCH_PC_AdjustmentStates, long);
UPDATE_IE(target->deltaMCS, source->deltaMCS, long);
if (source->pathlossReferenceRSToReleaseList) {
RELEASE_IE_FROMLIST(source->pathlossReferenceRSToReleaseList,
target->pathlossReferenceRSToAddModList,
@@ -850,8 +850,8 @@ static void setup_puschpowercontrol(NR_PUSCH_PowerControl_t *source, NR_PUSCH_Po
static void setup_puschconfig(NR_PUSCH_Config_t *source, NR_PUSCH_Config_t *target)
{
UPDATE_MAC_IE(target->dataScramblingIdentityPUSCH, source->dataScramblingIdentityPUSCH, long);
UPDATE_MAC_IE(target->txConfig, source->txConfig, long);
UPDATE_IE(target->dataScramblingIdentityPUSCH, source->dataScramblingIdentityPUSCH, long);
UPDATE_IE(target->txConfig, source->txConfig, long);
if (source->dmrs_UplinkForPUSCH_MappingTypeA)
HANDLE_SETUPRELEASE_IE(target->dmrs_UplinkForPUSCH_MappingTypeA,
source->dmrs_UplinkForPUSCH_MappingTypeA,
@@ -867,25 +867,25 @@ static void setup_puschconfig(NR_PUSCH_Config_t *source, NR_PUSCH_Config_t *targ
target->pusch_PowerControl = calloc(1, sizeof(*target->pusch_PowerControl));
setup_puschpowercontrol(source->pusch_PowerControl, target->pusch_PowerControl);
}
UPDATE_MAC_IE(target->frequencyHopping, source->frequencyHopping, long);
UPDATE_IE(target->frequencyHopping, source->frequencyHopping, long);
if (source->frequencyHoppingOffsetLists)
UPDATE_MAC_IE(target->frequencyHoppingOffsetLists,
source->frequencyHoppingOffsetLists,
struct NR_PUSCH_Config__frequencyHoppingOffsetLists);
UPDATE_IE(target->frequencyHoppingOffsetLists,
source->frequencyHoppingOffsetLists,
struct NR_PUSCH_Config__frequencyHoppingOffsetLists);
target->resourceAllocation = source->resourceAllocation;
if (source->pusch_TimeDomainAllocationList)
HANDLE_SETUPRELEASE_IE(target->pusch_TimeDomainAllocationList,
source->pusch_TimeDomainAllocationList,
NR_PUSCH_TimeDomainResourceAllocationList_t,
asn_DEF_NR_SetupRelease_PUSCH_TimeDomainResourceAllocationList);
UPDATE_MAC_IE(target->pusch_AggregationFactor, source->pusch_AggregationFactor, long);
UPDATE_MAC_IE(target->mcs_Table, source->mcs_Table, long);
UPDATE_MAC_IE(target->mcs_TableTransformPrecoder, source->mcs_TableTransformPrecoder, long);
UPDATE_MAC_IE(target->transformPrecoder, source->transformPrecoder, long);
UPDATE_MAC_IE(target->codebookSubset, source->codebookSubset, long);
UPDATE_MAC_IE(target->maxRank, source->maxRank, long);
UPDATE_MAC_IE(target->rbg_Size, source->rbg_Size, long);
UPDATE_MAC_IE(target->tp_pi2BPSK, source->tp_pi2BPSK, long);
UPDATE_IE(target->pusch_AggregationFactor, source->pusch_AggregationFactor, long);
UPDATE_IE(target->mcs_Table, source->mcs_Table, long);
UPDATE_IE(target->mcs_TableTransformPrecoder, source->mcs_TableTransformPrecoder, long);
UPDATE_IE(target->transformPrecoder, source->transformPrecoder, long);
UPDATE_IE(target->codebookSubset, source->codebookSubset, long);
UPDATE_IE(target->maxRank, source->maxRank, long);
UPDATE_IE(target->rbg_Size, source->rbg_Size, long);
UPDATE_IE(target->tp_pi2BPSK, source->tp_pi2BPSK, long);
if (source->uci_OnPUSCH) {
if (source->uci_OnPUSCH->present == NR_SetupRelease_UCI_OnPUSCH_PR_release)
asn1cFreeStruc(asn_DEF_NR_UCI_OnPUSCH, target->uci_OnPUSCH);
@@ -893,9 +893,9 @@ static void setup_puschconfig(NR_PUSCH_Config_t *source, NR_PUSCH_Config_t *targ
if (target->uci_OnPUSCH) {
target->uci_OnPUSCH->choice.setup->scaling = source->uci_OnPUSCH->choice.setup->scaling;
if (source->uci_OnPUSCH->choice.setup->betaOffsets)
UPDATE_MAC_IE(target->uci_OnPUSCH->choice.setup->betaOffsets,
source->uci_OnPUSCH->choice.setup->betaOffsets,
struct NR_UCI_OnPUSCH__betaOffsets);
UPDATE_IE(target->uci_OnPUSCH->choice.setup->betaOffsets,
source->uci_OnPUSCH->choice.setup->betaOffsets,
struct NR_UCI_OnPUSCH__betaOffsets);
}
}
}
@@ -903,7 +903,7 @@ static void setup_puschconfig(NR_PUSCH_Config_t *source, NR_PUSCH_Config_t *targ
static void setup_pdschconfig(NR_PDSCH_Config_t *source, NR_PDSCH_Config_t *target)
{
UPDATE_MAC_IE(target->dataScramblingIdentityPDSCH, source->dataScramblingIdentityPDSCH, long);
UPDATE_IE(target->dataScramblingIdentityPDSCH, source->dataScramblingIdentityPDSCH, long);
if (source->dmrs_DownlinkForPDSCH_MappingTypeA)
HANDLE_SETUPRELEASE_IE(target->dmrs_DownlinkForPDSCH_MappingTypeA,
source->dmrs_DownlinkForPDSCH_MappingTypeA,
@@ -929,14 +929,14 @@ static void setup_pdschconfig(NR_PDSCH_Config_t *source, NR_PDSCH_Config_t *targ
NR_TCI_State_t);
}
// end TCI States
UPDATE_MAC_IE(target->vrb_ToPRB_Interleaver, source->vrb_ToPRB_Interleaver, long);
UPDATE_IE(target->vrb_ToPRB_Interleaver, source->vrb_ToPRB_Interleaver, long);
target->resourceAllocation = source->resourceAllocation;
if (source->pdsch_TimeDomainAllocationList)
HANDLE_SETUPRELEASE_IE(target->pdsch_TimeDomainAllocationList,
source->pdsch_TimeDomainAllocationList,
NR_PDSCH_TimeDomainResourceAllocationList_t,
asn_DEF_NR_SetupRelease_PDSCH_TimeDomainResourceAllocationList);
UPDATE_MAC_IE(target->pdsch_AggregationFactor, source->pdsch_AggregationFactor, long);
UPDATE_IE(target->pdsch_AggregationFactor, source->pdsch_AggregationFactor, long);
// rateMatchPattern
if (source->rateMatchPatternToReleaseList) {
RELEASE_IE_FROMLIST(source->rateMatchPatternToReleaseList,
@@ -952,12 +952,12 @@ static void setup_pdschconfig(NR_PDSCH_Config_t *source, NR_PDSCH_Config_t *targ
NR_RateMatchPattern_t);
}
// end rateMatchPattern
UPDATE_MAC_IE(target->rateMatchPatternGroup1, source->rateMatchPatternGroup1, NR_RateMatchPatternGroup_t);
UPDATE_MAC_IE(target->rateMatchPatternGroup2, source->rateMatchPatternGroup2, NR_RateMatchPatternGroup_t);
UPDATE_IE(target->rateMatchPatternGroup1, source->rateMatchPatternGroup1, NR_RateMatchPatternGroup_t);
UPDATE_IE(target->rateMatchPatternGroup2, source->rateMatchPatternGroup2, NR_RateMatchPatternGroup_t);
target->rbg_Size = source->rbg_Size;
UPDATE_MAC_IE(target->mcs_Table, source->mcs_Table, long);
UPDATE_MAC_IE(target->maxNrofCodeWordsScheduledByDCI, source->maxNrofCodeWordsScheduledByDCI, long);
UPDATE_MAC_NP_IE(target->prb_BundlingType, source->prb_BundlingType, struct NR_PDSCH_Config__prb_BundlingType);
UPDATE_IE(target->mcs_Table, source->mcs_Table, long);
UPDATE_IE(target->maxNrofCodeWordsScheduledByDCI, source->maxNrofCodeWordsScheduledByDCI, long);
UPDATE_NP_IE(target->prb_BundlingType, source->prb_BundlingType, struct NR_PDSCH_Config__prb_BundlingType);
AssertFatal(source->zp_CSI_RS_ResourceToAddModList == NULL, "Not handled\n");
AssertFatal(source->aperiodic_ZP_CSI_RS_ResourceSetsToAddModList == NULL, "Not handled\n");
AssertFatal(source->sp_ZP_CSI_RS_ResourceSetsToAddModList == NULL, "Not handled\n");
@@ -968,11 +968,11 @@ static void setup_sr_resource(NR_SchedulingRequestResourceConfig_t *target, NR_S
target->schedulingRequestResourceId = source->schedulingRequestResourceId;
target->schedulingRequestID = source->schedulingRequestID;
if (source->periodicityAndOffset)
UPDATE_MAC_IE(target->periodicityAndOffset,
source->periodicityAndOffset,
struct NR_SchedulingRequestResourceConfig__periodicityAndOffset);
UPDATE_IE(target->periodicityAndOffset,
source->periodicityAndOffset,
struct NR_SchedulingRequestResourceConfig__periodicityAndOffset);
if (source->resource)
UPDATE_MAC_IE(target->resource, source->resource, NR_PUCCH_ResourceId_t);
UPDATE_IE(target->resource, source->resource, NR_PUCCH_ResourceId_t);
}
static void setup_pucchconfig(NR_PUCCH_Config_t *source, NR_PUCCH_Config_t *target)
@@ -1043,11 +1043,11 @@ static void setup_pucchconfig(NR_PUCCH_Config_t *source, NR_PUCCH_Config_t *targ
}
if (source->multi_CSI_PUCCH_ResourceList)
UPDATE_MAC_IE(target->multi_CSI_PUCCH_ResourceList,
source->multi_CSI_PUCCH_ResourceList,
struct NR_PUCCH_Config__multi_CSI_PUCCH_ResourceList);
UPDATE_IE(target->multi_CSI_PUCCH_ResourceList,
source->multi_CSI_PUCCH_ResourceList,
struct NR_PUCCH_Config__multi_CSI_PUCCH_ResourceList);
if (source->dl_DataToUL_ACK)
UPDATE_MAC_IE(target->dl_DataToUL_ACK, source->dl_DataToUL_ACK, struct NR_PUCCH_Config__dl_DataToUL_ACK);
UPDATE_IE(target->dl_DataToUL_ACK, source->dl_DataToUL_ACK, struct NR_PUCCH_Config__dl_DataToUL_ACK);
// PUCCH-SpatialRelationInfo
if (source->spatialRelationInfoToAddModList) {
if (!target->spatialRelationInfoToAddModList)
@@ -1066,20 +1066,20 @@ static void setup_pucchconfig(NR_PUCCH_Config_t *source, NR_PUCCH_Config_t *targ
if (source->pucch_PowerControl) {
if (!target->pucch_PowerControl)
target->pucch_PowerControl = calloc(1, sizeof(*target->pucch_PowerControl));
UPDATE_MAC_IE(target->pucch_PowerControl->deltaF_PUCCH_f0, source->pucch_PowerControl->deltaF_PUCCH_f0, long);
UPDATE_MAC_IE(target->pucch_PowerControl->deltaF_PUCCH_f1, source->pucch_PowerControl->deltaF_PUCCH_f1, long);
UPDATE_MAC_IE(target->pucch_PowerControl->deltaF_PUCCH_f2, source->pucch_PowerControl->deltaF_PUCCH_f2, long);
UPDATE_MAC_IE(target->pucch_PowerControl->deltaF_PUCCH_f3, source->pucch_PowerControl->deltaF_PUCCH_f3, long);
UPDATE_MAC_IE(target->pucch_PowerControl->deltaF_PUCCH_f4, source->pucch_PowerControl->deltaF_PUCCH_f4, long);
UPDATE_IE(target->pucch_PowerControl->deltaF_PUCCH_f0, source->pucch_PowerControl->deltaF_PUCCH_f0, long);
UPDATE_IE(target->pucch_PowerControl->deltaF_PUCCH_f1, source->pucch_PowerControl->deltaF_PUCCH_f1, long);
UPDATE_IE(target->pucch_PowerControl->deltaF_PUCCH_f2, source->pucch_PowerControl->deltaF_PUCCH_f2, long);
UPDATE_IE(target->pucch_PowerControl->deltaF_PUCCH_f3, source->pucch_PowerControl->deltaF_PUCCH_f3, long);
UPDATE_IE(target->pucch_PowerControl->deltaF_PUCCH_f4, source->pucch_PowerControl->deltaF_PUCCH_f4, long);
if (source->pucch_PowerControl->p0_Set)
UPDATE_MAC_IE(target->pucch_PowerControl->p0_Set, source->pucch_PowerControl->p0_Set, struct NR_PUCCH_PowerControl__p0_Set);
UPDATE_IE(target->pucch_PowerControl->p0_Set, source->pucch_PowerControl->p0_Set, struct NR_PUCCH_PowerControl__p0_Set);
if (source->pucch_PowerControl->pathlossReferenceRSs)
UPDATE_MAC_IE(target->pucch_PowerControl->pathlossReferenceRSs,
source->pucch_PowerControl->pathlossReferenceRSs,
struct NR_PUCCH_PowerControl__pathlossReferenceRSs);
UPDATE_MAC_IE(target->pucch_PowerControl->twoPUCCH_PC_AdjustmentStates,
source->pucch_PowerControl->twoPUCCH_PC_AdjustmentStates,
long);
UPDATE_IE(target->pucch_PowerControl->pathlossReferenceRSs,
source->pucch_PowerControl->pathlossReferenceRSs,
struct NR_PUCCH_PowerControl__pathlossReferenceRSs);
UPDATE_IE(target->pucch_PowerControl->twoPUCCH_PC_AdjustmentStates,
source->pucch_PowerControl->twoPUCCH_PC_AdjustmentStates,
long);
}
}
@@ -1088,22 +1088,22 @@ static void handle_aperiodic_srs_type(struct NR_SRS_ResourceSet__resourceType__a
{
target->aperiodicSRS_ResourceTrigger = source->aperiodicSRS_ResourceTrigger;
if (source->csi_RS)
UPDATE_MAC_IE(target->csi_RS, source->csi_RS, NR_NZP_CSI_RS_ResourceId_t);
UPDATE_MAC_IE(target->slotOffset, source->slotOffset, long);
UPDATE_IE(target->csi_RS, source->csi_RS, NR_NZP_CSI_RS_ResourceId_t);
UPDATE_IE(target->slotOffset, source->slotOffset, long);
if (source->ext1 && source->ext1->aperiodicSRS_ResourceTriggerList)
UPDATE_MAC_IE(target->ext1->aperiodicSRS_ResourceTriggerList,
source->ext1->aperiodicSRS_ResourceTriggerList,
struct NR_SRS_ResourceSet__resourceType__aperiodic__ext1__aperiodicSRS_ResourceTriggerList);
UPDATE_IE(target->ext1->aperiodicSRS_ResourceTriggerList,
source->ext1->aperiodicSRS_ResourceTriggerList,
struct NR_SRS_ResourceSet__resourceType__aperiodic__ext1__aperiodicSRS_ResourceTriggerList);
}
static void setup_srsresourceset(NR_SRS_ResourceSet_t *target, NR_SRS_ResourceSet_t *source)
{
target->srs_ResourceSetId = source->srs_ResourceSetId;
if (source->srs_ResourceIdList)
UPDATE_MAC_IE(target->srs_ResourceIdList, source->srs_ResourceIdList, struct NR_SRS_ResourceSet__srs_ResourceIdList);
UPDATE_IE(target->srs_ResourceIdList, source->srs_ResourceIdList, struct NR_SRS_ResourceSet__srs_ResourceIdList);
if (target->resourceType.present != source->resourceType.present) {
UPDATE_MAC_NP_IE(target->resourceType, source->resourceType, struct NR_SRS_ResourceSet__resourceType);
UPDATE_NP_IE(target->resourceType, source->resourceType, struct NR_SRS_ResourceSet__resourceType);
}
else {
switch (source->resourceType.present) {
@@ -1112,32 +1112,32 @@ static void setup_srsresourceset(NR_SRS_ResourceSet_t *target, NR_SRS_ResourceSe
break;
case NR_SRS_ResourceSet__resourceType_PR_periodic:
if (source->resourceType.choice.periodic->associatedCSI_RS)
UPDATE_MAC_IE(target->resourceType.choice.periodic->associatedCSI_RS,
source->resourceType.choice.periodic->associatedCSI_RS,
NR_NZP_CSI_RS_ResourceId_t);
UPDATE_IE(target->resourceType.choice.periodic->associatedCSI_RS,
source->resourceType.choice.periodic->associatedCSI_RS,
NR_NZP_CSI_RS_ResourceId_t);
break;
case NR_SRS_ResourceSet__resourceType_PR_semi_persistent:
if (source->resourceType.choice.semi_persistent->associatedCSI_RS)
UPDATE_MAC_IE(target->resourceType.choice.semi_persistent->associatedCSI_RS,
source->resourceType.choice.semi_persistent->associatedCSI_RS,
NR_NZP_CSI_RS_ResourceId_t);
UPDATE_IE(target->resourceType.choice.semi_persistent->associatedCSI_RS,
source->resourceType.choice.semi_persistent->associatedCSI_RS,
NR_NZP_CSI_RS_ResourceId_t);
break;
default:
break;
}
}
target->usage = source->usage;
UPDATE_MAC_IE(target->alpha, source->alpha, NR_Alpha_t);
UPDATE_IE(target->alpha, source->alpha, NR_Alpha_t);
if (source->p0)
UPDATE_MAC_IE(target->p0, source->p0, long);
UPDATE_IE(target->p0, source->p0, long);
if (source->pathlossReferenceRS)
UPDATE_MAC_IE(target->pathlossReferenceRS, source->pathlossReferenceRS, struct NR_PathlossReferenceRS_Config);
UPDATE_MAC_IE(target->srs_PowerControlAdjustmentStates, source->srs_PowerControlAdjustmentStates, long);
UPDATE_IE(target->pathlossReferenceRS, source->pathlossReferenceRS, struct NR_PathlossReferenceRS_Config);
UPDATE_IE(target->srs_PowerControlAdjustmentStates, source->srs_PowerControlAdjustmentStates, long);
}
static void setup_srsconfig(NR_SRS_Config_t *source, NR_SRS_Config_t *target)
{
UPDATE_MAC_IE(target->tpc_Accumulation, source->tpc_Accumulation, long);
UPDATE_IE(target->tpc_Accumulation, source->tpc_Accumulation, long);
// SRS-Resource
if (source->srs_ResourceToAddModList) {
if (!target->srs_ResourceToAddModList)
@@ -1297,9 +1297,9 @@ static void configure_common_BWP_dl(NR_UE_MAC_INST_t *mac, int bwp_id, NR_BWP_Do
}
if (dl_common->pdsch_ConfigCommon) {
if (dl_common->pdsch_ConfigCommon->present == NR_SetupRelease_PDSCH_ConfigCommon_PR_setup)
UPDATE_MAC_IE(bwp->tdaList_Common,
dl_common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList,
NR_PDSCH_TimeDomainResourceAllocationList_t);
UPDATE_IE(bwp->tdaList_Common,
dl_common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList,
NR_PDSCH_TimeDomainResourceAllocationList_t);
if (dl_common->pdsch_ConfigCommon->present == NR_SetupRelease_PDSCH_ConfigCommon_PR_release)
asn1cFreeStruc(asn_DEF_NR_PDSCH_TimeDomainResourceAllocationList, bwp->tdaList_Common);
}
@@ -1340,10 +1340,10 @@ static void configure_common_BWP_ul(NR_UE_MAC_INST_t *mac, int bwp_id, NR_BWP_Up
asn_DEF_NR_PUCCH_ConfigCommon);
if (ul_common->pusch_ConfigCommon) {
if (ul_common->pusch_ConfigCommon->present == NR_SetupRelease_PUSCH_ConfigCommon_PR_setup) {
UPDATE_MAC_IE(bwp->tdaList_Common,
ul_common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList,
NR_PUSCH_TimeDomainResourceAllocationList_t);
UPDATE_MAC_IE(bwp->msg3_DeltaPreamble, ul_common->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble, long);
UPDATE_IE(bwp->tdaList_Common,
ul_common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList,
NR_PUSCH_TimeDomainResourceAllocationList_t);
UPDATE_IE(bwp->msg3_DeltaPreamble, ul_common->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble, long);
}
if (ul_common->pusch_ConfigCommon->present == NR_SetupRelease_PUSCH_ConfigCommon_PR_release) {
asn1cFreeStruc(asn_DEF_NR_PUSCH_TimeDomainResourceAllocationList, bwp->tdaList_Common);
@@ -1355,21 +1355,40 @@ static void configure_common_BWP_ul(NR_UE_MAC_INST_t *mac, int bwp_id, NR_BWP_Up
}
void nr_rrc_mac_config_req_reset(module_id_t module_id,
NR_UE_MAC_reset_cause_t reset_cause)
NR_UE_MAC_reset_cause_t cause)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
reset_mac_inst(mac);
reset_ra(&mac->ra);
release_mac_configuration(mac);
nr_ue_init_mac(mac);
// Sending to PHY a request to resync
// with no target cell ID
if (reset_cause != DETACH) {
mac->synch_request.Mod_id = module_id;
mac->synch_request.CC_id = 0;
mac->synch_request.synch_req.target_Nid_cell = -1;
mac->if_module->synch_request(&mac->synch_request);
switch (cause) {
case GO_TO_IDLE:
reset_ra(&mac->ra);
release_mac_configuration(mac, cause);
nr_ue_init_mac(mac);
nr_ue_mac_default_configs(mac);
// new sync but no target cell id -> -1
nr_ue_send_synch_request(mac, module_id, 0, -1);
break;
case DETACH:
reset_ra(&mac->ra);
reset_mac_inst(mac);
nr_ue_reset_sync_state(mac);
release_mac_configuration(mac, cause);
break;
case T300_EXPIRY:
reset_mac_inst(mac);
reset_ra(&mac->ra);
mac->state = UE_SYNC; // still in sync but need to restart RA
break;
case RE_ESTABLISHMENT:
reset_mac_inst(mac);
nr_ue_mac_default_configs(mac);
nr_ue_reset_sync_state(mac);
release_mac_configuration(mac, cause);
// new sync with old cell ID (re-establishment on the same cell)
nr_ue_send_synch_request(mac, module_id, 0, mac->physCellId);
break;
default:
AssertFatal(false, "Invalid MAC reset cause %d\n", cause);
}
}
@@ -1381,8 +1400,8 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id,
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
AssertFatal(scc, "SIB1 SCC should not be NULL\n");
UPDATE_MAC_IE(mac->tdd_UL_DL_ConfigurationCommon, scc->tdd_UL_DL_ConfigurationCommon, NR_TDD_UL_DL_ConfigCommon_t);
UPDATE_MAC_IE(mac->si_SchedulingInfo, si_SchedulingInfo, NR_SI_SchedulingInfo_t);
UPDATE_IE(mac->tdd_UL_DL_ConfigurationCommon, scc->tdd_UL_DL_ConfigurationCommon, NR_TDD_UL_DL_ConfigCommon_t);
UPDATE_IE(mac->si_SchedulingInfo, si_SchedulingInfo, NR_SI_SchedulingInfo_t);
config_common_ue_sa(mac, scc, cc_idP);
configure_common_BWP_dl(mac,
@@ -1421,7 +1440,7 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac,
AssertFatal(
reconfigurationWithSync->rach_ConfigDedicated->present == NR_ReconfigurationWithSync__rach_ConfigDedicated_PR_uplink,
"RACH on supplementaryUplink not supported\n");
UPDATE_MAC_IE(ra->rach_ConfigDedicated, reconfigurationWithSync->rach_ConfigDedicated->choice.uplink, NR_RACH_ConfigDedicated_t);
UPDATE_IE(ra->rach_ConfigDedicated, reconfigurationWithSync->rach_ConfigDedicated->choice.uplink, NR_RACH_ConfigDedicated_t);
}
if (reconfigurationWithSync->spCellConfigCommon) {
@@ -1429,7 +1448,7 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac,
if (scc->physCellId)
mac->physCellId = *scc->physCellId;
mac->dmrs_TypeA_Position = scc->dmrs_TypeA_Position;
UPDATE_MAC_IE(mac->tdd_UL_DL_ConfigurationCommon, scc->tdd_UL_DL_ConfigurationCommon, NR_TDD_UL_DL_ConfigCommon_t);
UPDATE_IE(mac->tdd_UL_DL_ConfigurationCommon, scc->tdd_UL_DL_ConfigurationCommon, NR_TDD_UL_DL_ConfigCommon_t);
config_common_ue(mac, scc, cc_idP);
if (scc->downlinkConfigCommon)
configure_common_BWP_dl(mac,
@@ -1442,7 +1461,7 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac,
}
mac->state = UE_NOT_SYNC;
ra->ra_state = RA_UE_IDLE;
ra->ra_state = nrRA_UE_IDLE;
nr_ue_mac_default_configs(mac);
if (!get_softmodem_params()->emulate_l1) {
@@ -1530,9 +1549,9 @@ static void configure_maccellgroup(NR_UE_MAC_INST_t *mac, const NR_MAC_CellGroup
static void configure_csi_resourcemapping(NR_CSI_RS_ResourceMapping_t *target, NR_CSI_RS_ResourceMapping_t *source)
{
if (target->frequencyDomainAllocation.present != source->frequencyDomainAllocation.present) {
UPDATE_MAC_NP_IE(target->frequencyDomainAllocation,
source->frequencyDomainAllocation,
struct NR_CSI_RS_ResourceMapping__frequencyDomainAllocation);
UPDATE_NP_IE(target->frequencyDomainAllocation,
source->frequencyDomainAllocation,
struct NR_CSI_RS_ResourceMapping__frequencyDomainAllocation);
}
else {
switch (source->frequencyDomainAllocation.present) {
@@ -1578,7 +1597,7 @@ static void configure_csi_resourcemapping(NR_CSI_RS_ResourceMapping_t *target, N
}
target->nrofPorts = source->nrofPorts;
target->firstOFDMSymbolInTimeDomain = source->firstOFDMSymbolInTimeDomain;
UPDATE_MAC_IE(target->firstOFDMSymbolInTimeDomain2, source->firstOFDMSymbolInTimeDomain2, long);
UPDATE_IE(target->firstOFDMSymbolInTimeDomain2, source->firstOFDMSymbolInTimeDomain2, long);
target->cdm_Type = source->cdm_Type;
target->density = source->density;
target->freqBand = source->freqBand;
@@ -1588,24 +1607,24 @@ static void configure_csirs_resource(NR_NZP_CSI_RS_Resource_t *target, NR_NZP_CS
{
configure_csi_resourcemapping(&target->resourceMapping, &source->resourceMapping);
target->powerControlOffset = source->powerControlOffset;
UPDATE_MAC_IE(target->powerControlOffsetSS, source->powerControlOffsetSS, long);
UPDATE_IE(target->powerControlOffsetSS, source->powerControlOffsetSS, long);
target->scramblingID = source->scramblingID;
if (source->periodicityAndOffset)
UPDATE_MAC_IE(target->periodicityAndOffset, source->periodicityAndOffset, NR_CSI_ResourcePeriodicityAndOffset_t);
UPDATE_IE(target->periodicityAndOffset, source->periodicityAndOffset, NR_CSI_ResourcePeriodicityAndOffset_t);
if (source->qcl_InfoPeriodicCSI_RS)
UPDATE_MAC_IE(target->qcl_InfoPeriodicCSI_RS, source->qcl_InfoPeriodicCSI_RS, NR_TCI_StateId_t);
UPDATE_IE(target->qcl_InfoPeriodicCSI_RS, source->qcl_InfoPeriodicCSI_RS, NR_TCI_StateId_t);
}
static void configure_csiim_resource(NR_CSI_IM_Resource_t *target, NR_CSI_IM_Resource_t *source)
{
if (source->csi_IM_ResourceElementPattern)
UPDATE_MAC_IE(target->csi_IM_ResourceElementPattern,
source->csi_IM_ResourceElementPattern,
struct NR_CSI_IM_Resource__csi_IM_ResourceElementPattern);
UPDATE_IE(target->csi_IM_ResourceElementPattern,
source->csi_IM_ResourceElementPattern,
struct NR_CSI_IM_Resource__csi_IM_ResourceElementPattern);
if (source->freqBand)
UPDATE_MAC_IE(target->freqBand, source->freqBand, NR_CSI_FrequencyOccupation_t);
UPDATE_IE(target->freqBand, source->freqBand, NR_CSI_FrequencyOccupation_t);
if (source->periodicityAndOffset)
UPDATE_MAC_IE(target->periodicityAndOffset, source->periodicityAndOffset, NR_CSI_ResourcePeriodicityAndOffset_t);
UPDATE_IE(target->periodicityAndOffset, source->periodicityAndOffset, NR_CSI_ResourcePeriodicityAndOffset_t);
}
static void configure_csiconfig(NR_UE_ServingCell_Info_t *sc_info, struct NR_SetupRelease_CSI_MeasConfig *csi_MeasConfig_sr)
@@ -1618,12 +1637,12 @@ static void configure_csiconfig(NR_UE_ServingCell_Info_t *sc_info, struct NR_Set
break;
case NR_SetupRelease_CSI_MeasConfig_PR_setup:
if (!sc_info->csi_MeasConfig) { // setup
UPDATE_MAC_IE(sc_info->csi_MeasConfig, csi_MeasConfig_sr->choice.setup, NR_CSI_MeasConfig_t);
UPDATE_IE(sc_info->csi_MeasConfig, csi_MeasConfig_sr->choice.setup, NR_CSI_MeasConfig_t);
} else { // modification
NR_CSI_MeasConfig_t *target = sc_info->csi_MeasConfig;
NR_CSI_MeasConfig_t *csi_MeasConfig = csi_MeasConfig_sr->choice.setup;
if (csi_MeasConfig->reportTriggerSize)
UPDATE_MAC_IE(target->reportTriggerSize, csi_MeasConfig->reportTriggerSize, long);
UPDATE_IE(target->reportTriggerSize, csi_MeasConfig->reportTriggerSize, long);
if (csi_MeasConfig->aperiodicTriggerStateList)
HANDLE_SETUPRELEASE_DIRECT(sc_info->aperiodicTriggerStateList,
csi_MeasConfig->aperiodicTriggerStateList,
@@ -1747,9 +1766,9 @@ static void configure_servingcell_info(NR_UE_ServingCell_Info_t *sc_info, NR_Ser
configure_csiconfig(sc_info, scd->csi_MeasConfig);
if (scd->supplementaryUplink)
UPDATE_MAC_IE(sc_info->supplementaryUplink, scd->supplementaryUplink, NR_UplinkConfig_t);
UPDATE_IE(sc_info->supplementaryUplink, scd->supplementaryUplink, NR_UplinkConfig_t);
if (scd->crossCarrierSchedulingConfig)
UPDATE_MAC_IE(sc_info->crossCarrierSchedulingConfig, scd->crossCarrierSchedulingConfig, NR_CrossCarrierSchedulingConfig_t);
UPDATE_IE(sc_info->crossCarrierSchedulingConfig, scd->crossCarrierSchedulingConfig, NR_CrossCarrierSchedulingConfig_t);
if (scd->pdsch_ServingCellConfig) {
switch (scd->pdsch_ServingCellConfig->present) {
case NR_SetupRelease_PDSCH_ServingCellConfig_PR_NOTHING:
@@ -1774,9 +1793,9 @@ static void configure_servingcell_info(NR_UE_ServingCell_Info_t *sc_info, NR_Ser
pdsch_servingcellconfig->codeBlockGroupTransmission,
NR_PDSCH_CodeBlockGroupTransmission_t,
asn_DEF_NR_PDSCH_CodeBlockGroupTransmission);
UPDATE_MAC_IE(sc_info->xOverhead_PDSCH, pdsch_servingcellconfig->xOverhead, long);
UPDATE_IE(sc_info->xOverhead_PDSCH, pdsch_servingcellconfig->xOverhead, long);
if (pdsch_servingcellconfig->ext1 && pdsch_servingcellconfig->ext1->maxMIMO_Layers)
UPDATE_MAC_IE(sc_info->maxMIMO_Layers_PDSCH, pdsch_servingcellconfig->ext1->maxMIMO_Layers, long);
UPDATE_IE(sc_info->maxMIMO_Layers_PDSCH, pdsch_servingcellconfig->ext1->maxMIMO_Layers, long);
break;
}
default:
@@ -1806,10 +1825,10 @@ static void configure_servingcell_info(NR_UE_ServingCell_Info_t *sc_info, NR_Ser
break;
case NR_SetupRelease_PUSCH_ServingCellConfig_PR_setup: {
NR_PUSCH_ServingCellConfig_t *pusch_servingcellconfig = scd->uplinkConfig->pusch_ServingCellConfig->choice.setup;
UPDATE_MAC_IE(sc_info->rateMatching_PUSCH, pusch_servingcellconfig->rateMatching, long);
UPDATE_MAC_IE(sc_info->xOverhead_PUSCH, pusch_servingcellconfig->xOverhead, long);
UPDATE_IE(sc_info->rateMatching_PUSCH, pusch_servingcellconfig->rateMatching, long);
UPDATE_IE(sc_info->xOverhead_PUSCH, pusch_servingcellconfig->xOverhead, long);
if (pusch_servingcellconfig->ext1 && pusch_servingcellconfig->ext1->maxMIMO_Layers)
UPDATE_MAC_IE(sc_info->maxMIMO_Layers_PUSCH, pusch_servingcellconfig->ext1->maxMIMO_Layers, long);
UPDATE_IE(sc_info->maxMIMO_Layers_PUSCH, pusch_servingcellconfig->ext1->maxMIMO_Layers, long);
if (pusch_servingcellconfig->codeBlockGroupTransmission)
HANDLE_SETUPRELEASE_DIRECT(sc_info->pusch_CGB_Transmission,
pusch_servingcellconfig->codeBlockGroupTransmission,
+14 -11
View File
@@ -238,13 +238,16 @@ typedef struct {
} NR_UE_SCHEDULING_INFO;
typedef enum {
RA_UE_IDLE = 0,
GENERATE_PREAMBLE = 1,
WAIT_RAR = 2,
WAIT_CONTENTION_RESOLUTION = 3,
RA_SUCCEEDED = 4,
RA_FAILED = 5
} RA_state_t;
nrRA_UE_IDLE = 0,
nrRA_GENERATE_PREAMBLE = 1,
nrRA_WAIT_RAR = 2,
nrRA_WAIT_CONTENTION_RESOLUTION = 3,
nrRA_SUCCEEDED = 4,
nrRA_FAILED = 5
} nrRA_UE_state_t;
static const char *const nrra_ue_text[] =
{"UE_IDLE", "GENERATE_PREAMBLE", "WAIT_RAR", "WAIT_CONTENTION_RESOLUTION", "RA_SUCCEEDED", "RA_FAILED"};
typedef struct {
/// PRACH format retrieved from prach_ConfigIndex
@@ -276,7 +279,7 @@ typedef struct {
// pointer to RACH config dedicated
NR_RACH_ConfigDedicated_t *rach_ConfigDedicated;
/// state of RA procedure
RA_state_t ra_state;
nrRA_UE_state_t ra_state;
/// RA contention type
uint8_t cfra;
/// RA rx frame offset: compensate RA rx offset introduced by OAI gNB.
@@ -423,15 +426,15 @@ typedef struct prach_association_pattern {
// SSB details
typedef struct ssb_info {
bool transmitted; // True if the SSB index is transmitted according to the SSB positions map configuration
prach_occasion_info_t *mapped_ro[MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN]; // List of mapped RACH Occasions to this SSB index
uint32_t nb_mapped_ro; // Total number of mapped ROs to this SSB index
} ssb_info_t;
// List of all the possible SSBs and their details
typedef struct ssb_list_info {
ssb_info_t tx_ssb[MAX_NB_SSB];
uint8_t nb_tx_ssb;
ssb_info_t *tx_ssb;
int nb_tx_ssb;
int nb_ssb_per_index[MAX_NB_SSB];
} ssb_list_info_t;
typedef struct nr_lcordered_info_s {
+5 -106
View File
@@ -41,111 +41,6 @@
#define NR_DL_MAX_DAI (4) /* TS 38.213 table 9.1.3-1 Value of counter DAI for DCI format 1_0 and 1_1 */
#define NR_DL_MAX_NB_CW (2) /* number of downlink code word */
// Macro updates DESTINATION with configuration from ORIGIN by swapping pointers
// Old configuration is freed after completing configuration
#define UPDATE_MAC_IE(DESTINATION, ORIGIN, TYPE) \
do { \
TYPE *tmp = ORIGIN; \
ORIGIN = DESTINATION; \
DESTINATION = tmp; \
} while(0); \
// Same as above but swapping ASN1 elements that are not pointers
#define UPDATE_MAC_NP_IE(DESTINATION, ORIGIN, TYPE) \
do { \
TYPE tmp = ORIGIN; \
ORIGIN = DESTINATION; \
DESTINATION = tmp; \
} while(0); \
// Macro handles reception of SetupRelease element ORIGIN (see NR_SetupRelease.h)
// If release (NR_SetupRelease_xxx_PR_release equivalent to 1), removing structure from DESTINATION
// If setup (NR_SetupRelease_xxx_PR_setup equivalent to 2), add or modify structure in DESTINATION
// Destination is not a SetupRelease structure
#define HANDLE_SETUPRELEASE_DIRECT(DESTINATION, ORIGIN, TYPE, ASN_DEF) \
do { \
if (ORIGIN->present == 1) { \
asn1cFreeStruc(ASN_DEF, DESTINATION); \
} \
if (ORIGIN->present == 2) \
UPDATE_MAC_IE(DESTINATION, ORIGIN->choice.setup, TYPE); \
} while(0); \
// Macro handles reception of SetupRelease element ORIGIN (see NR_SetupRelease.h)
// If release (NR_SetupRelease_xxx_PR_release equivalent to 1), removing structure from DESTINATION
// If setup (NR_SetupRelease_xxx_PR_setup equivalent to 2), add or modify structure in DESTINATION
// Destination is a SetupRelease structure
#define HANDLE_SETUPRELEASE_IE(DESTINATION, ORIGIN, TYPE, ASN_DEF) \
do { \
if (ORIGIN->present == 1) { \
asn1cFreeStruc(ASN_DEF, DESTINATION); \
} \
if (ORIGIN->present == 2) { \
if (!DESTINATION) \
DESTINATION = calloc(1, sizeof(*DESTINATION)); \
DESTINATION->present = ORIGIN->present; \
UPDATE_MAC_IE(DESTINATION->choice.setup, ORIGIN->choice.setup, TYPE); \
} \
} while(0); \
// Macro releases entries in list TARGET if the corresponding ID is found in list SOURCE.
// Prints an error if ID not found in list.
#define RELEASE_IE_FROMLIST(SOURCE, TARGET, FIELD) \
do { \
for (int iI = 0; iI < SOURCE->list.count; iI++) { \
long eL = *SOURCE->list.array[iI]; \
int iJ; \
for (iJ = 0; iJ < TARGET->list.count; iJ++) { \
if (eL == TARGET->list.array[iJ]->FIELD) \
break; \
} \
if (iJ == TARGET->list.count) \
asn_sequence_del(&TARGET->list, iJ, 1); \
else \
LOG_E(NR_MAC, "Element not present in the list, impossible to release\n"); \
} \
} while (0) \
// Macro adds or modifies entries of type TYPE in list TARGET with elements received in list SOURCE
#define ADDMOD_IE_FROMLIST(SOURCE, TARGET, FIELD, TYPE) \
do { \
for (int iI = 0; iI < SOURCE->list.count; iI++) { \
long eL = SOURCE->list.array[iI]->FIELD; \
int iJ; \
for (iJ = 0; iJ < TARGET->list.count; iJ++) { \
if (eL == TARGET->list.array[iJ]->FIELD) \
break; \
} \
if (iJ == TARGET->list.count) { \
TYPE *nEW = calloc(1, sizeof(*nEW)); \
ASN_SEQUENCE_ADD(&TARGET->list, nEW); \
} \
UPDATE_MAC_IE(TARGET->list.array[iJ], \
SOURCE->list.array[iI], \
TYPE); \
} \
} while (0) \
// Macro adds or modifies entries of type TYPE in list TARGET with elements received in list SOURCE
// Action performed by function FUNC
#define ADDMOD_IE_FROMLIST_WFUNCTION(SOURCE, TARGET, FIELD, TYPE, FUNC) \
do { \
for (int iI = 0; iI < SOURCE->list.count; iI++) { \
long eL = SOURCE->list.array[iI]->FIELD; \
int iJ; \
for (iJ = 0; iJ < TARGET->list.count; iJ++) { \
if (eL == TARGET->list.array[iJ]->FIELD) \
break; \
} \
if (iJ == TARGET->list.count) { \
TYPE *nEW = calloc(1, sizeof(*nEW)); \
ASN_SEQUENCE_ADD(&TARGET->list, nEW); \
} \
FUNC(TARGET->list.array[iJ], \
SOURCE->list.array[iI]); \
} \
} while (0)
/**\brief initialize the field in nr_mac instance
\param mac MAC pointer */
void nr_ue_init_mac(NR_UE_MAC_INST_t *mac);
@@ -205,7 +100,8 @@ NR_UE_MAC_INST_t *get_mac_inst(module_id_t module_id);
void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac);
void reset_ra(RA_config_t *ra);
void release_mac_configuration(NR_UE_MAC_INST_t *mac);
void release_mac_configuration(NR_UE_MAC_INST_t *mac,
NR_UE_MAC_reset_cause_t cause);
/**\brief called at each slot, slot length based on numerology. now use u=0, scs=15kHz, slot=1ms
performs BSR/SR/PHR procedures, random access procedure handler and DLSCH/ULSCH procedures.
@@ -450,6 +346,9 @@ void nr_get_prach_resources(NR_UE_MAC_INST_t *mac,
void prepare_msg4_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack);
void configure_initial_pucch(PUCCH_sched_t *pucch, int res_ind);
void nr_ue_reset_sync_state(NR_UE_MAC_INST_t *mac);
void nr_ue_send_synch_request(NR_UE_MAC_INST_t *mac, module_id_t module_id, int cc_id, int cell_id);
void init_RA(NR_UE_MAC_INST_t *mac,
NR_PRACH_RESOURCES_t *prach_resources,
NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon,
+93 -53
View File
@@ -56,12 +56,11 @@ void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data
void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
{
LOG_I(NR_MAC, "[UE%d] Initializing MAC\n", mac->ue_id);
mac->first_sync_frame = -1;
nr_ue_reset_sync_state(mac);
mac->get_sib1 = false;
mac->get_otherSI = false;
mac->phy_config_request_sent = false;
memset(&mac->phy_config, 0, sizeof(mac->phy_config));
mac->state = UE_NOT_SYNC;
mac->si_window_start = -1;
mac->servCellIndex = 0;
mac->harq_ACK_SpatialBundlingPUCCH = false;
@@ -69,42 +68,40 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
mac->uecap_maxMIMO_PDSCH_layers = 0;
mac->uecap_maxMIMO_PUSCH_layers_cb = 0;
mac->uecap_maxMIMO_PUSCH_layers_nocb = 0;
mac->p_Max = INT_MIN;
mac->p_Max_alt = INT_MIN;
reset_mac_inst(mac);
memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements));
memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment));
for (int i = 0; i < MAX_NUM_BWP_UE; i++) {
memset(&mac->ssb_list[i], 0, sizeof(mac->ssb_list[i]));
memset(&mac->prach_assoc_pattern[i], 0, sizeof(mac->prach_assoc_pattern[i]));
}
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) {
mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value
mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value
}
memset(mac->ssb_list, 0, sizeof(mac->ssb_list));
memset(mac->prach_assoc_pattern, 0, sizeof(mac->prach_assoc_pattern));
}
void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac)
{
// default values as defined in 38.331 sec 9.2.2
mac->scheduling_info.retxBSR_Timer = NR_BSR_Config__retxBSR_Timer_sf10240;
mac->scheduling_info.periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_infinity;
mac->scheduling_info.SR_COUNTER = 0;
mac->scheduling_info.SR_pending = 0;
mac->scheduling_info.sr_ProhibitTimer = 0;
mac->scheduling_info.sr_ProhibitTimer_Running = 0;
mac->scheduling_info.sr_id = -1; // invalid init value
mac->scheduling_info.retxBSR_Timer = NR_BSR_Config__retxBSR_Timer_sf80;
mac->scheduling_info.periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf10;
mac->scheduling_info.periodicPHR_Timer = NR_PHR_Config__phr_PeriodicTimer_sf10;
mac->scheduling_info.prohibitPHR_Timer = NR_PHR_Config__phr_ProhibitTimer_sf10;
}
// set init value 0xFFFF, make sure periodic timer and retx time counters are NOT active, after bsr transmission set the value
// configured by the NW.
mac->scheduling_info.periodicBSR_SF = NR_MAC_UE_BSR_TIMER_NOT_RUNNING;
mac->scheduling_info.retxBSR_SF = NR_MAC_UE_BSR_TIMER_NOT_RUNNING;
mac->BSR_reporting_active = NR_BSR_TRIGGER_NONE;
void nr_ue_send_synch_request(NR_UE_MAC_INST_t *mac, module_id_t module_id, int cc_id, int cell_id)
{
// Sending to PHY a request to resync
mac->synch_request.Mod_id = module_id;
mac->synch_request.CC_id = cc_id;
mac->synch_request.synch_req.target_Nid_cell = cell_id;
mac->if_module->synch_request(&mac->synch_request);
}
for (int i = 0; i < NR_MAX_NUM_LCID; i++) {
LOG_D(NR_MAC, "Applying default logical channel config for LCGID %d\n", i);
mac->scheduling_info.lc_sched_info[i].LCID_buffer_with_data = false;
mac->scheduling_info.lc_sched_info[i].LCID_buffer_remain = 0;
mac->scheduling_info.lc_sched_info[i].Bj = 0;
}
void nr_ue_reset_sync_state(NR_UE_MAC_INST_t *mac)
{
// reset synchornization status
mac->first_sync_frame = -1;
mac->state = UE_NOT_SYNC;
mac->ra.ra_state = nrRA_UE_IDLE;
}
NR_UE_MAC_INST_t *nr_l2_init_ue(int nb_inst)
@@ -144,14 +141,16 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
{
// MAC reset according to 38.321 Section 5.12
nr_ue_mac_default_configs(nr_mac);
// initialize Bj for each logical channel to zero
for (int i = 0; i < NR_MAX_NUM_LCID; i++)
// TODO reset also other status variables of LC, is this ok?
for (int i = 0; i < NR_MAX_NUM_LCID; i++) {
nr_mac->scheduling_info.lc_sched_info[i].Bj = 0;
nr_mac->scheduling_info.lc_sched_info[i].LCID_buffer_with_data = false;
nr_mac->scheduling_info.lc_sched_info[i].LCID_buffer_remain = 0;
}
// stop all running timers
// TODO
// TODO stop all running timers
nr_timer_stop(&nr_mac->ra.contention_resolution_timer);
// consider all timeAlignmentTimers as expired and perform the corresponding actions in clause 5.2
// TODO
@@ -161,8 +160,8 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
nr_mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value
// stop any ongoing RACH procedure
if (nr_mac->ra.ra_state < RA_SUCCEEDED)
nr_mac->ra.ra_state = RA_UE_IDLE;
if (nr_mac->ra.ra_state < nrRA_SUCCEEDED)
nr_mac->ra.ra_state = nrRA_UE_IDLE;
// discard explicitly signalled contention-free Random Access Resources
// TODO not sure what needs to be done here
@@ -171,10 +170,16 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
free_and_zero(nr_mac->ra.Msg3_buffer);
// cancel any triggered Scheduling Request procedure
// Done in default config
nr_mac->scheduling_info.SR_COUNTER = 0;
nr_mac->scheduling_info.SR_pending = 0;
nr_mac->scheduling_info.sr_ProhibitTimer = 0;
nr_mac->scheduling_info.sr_ProhibitTimer_Running = 0;
nr_mac->scheduling_info.sr_id = -1; // invalid init value
// cancel any triggered Buffer Status Reporting procedure
// Done in default config
nr_mac->scheduling_info.periodicBSR_SF = NR_MAC_UE_BSR_TIMER_NOT_RUNNING;
nr_mac->scheduling_info.retxBSR_SF = NR_MAC_UE_BSR_TIMER_NOT_RUNNING;
nr_mac->BSR_reporting_active = NR_BSR_TRIGGER_NONE;
// cancel any triggered Power Headroom Reporting procedure
// TODO PHR not implemented yet
@@ -189,17 +194,37 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
// release, if any, Temporary C-RNTI
nr_mac->ra.t_crnti = 0;
// free RACH structs
for (int i = 0; i < MAX_NUM_BWP_UE; i++) {
free(nr_mac->ssb_list[i].tx_ssb);
for (int j = 0; j < MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD; j++)
for (int k = 0; k < MAX_NB_FRAME_IN_PRACH_CONF_PERIOD; k++)
for (int l = 0; l < MAX_NB_SLOT_IN_FRAME; l++)
free(nr_mac->prach_assoc_pattern[i].prach_conf_period_list[j].prach_occasion_slot_map[k][l].prach_occasion);
}
// reset BFI_COUNTER
// TODO beam failure procedure not implemented
}
void release_mac_configuration(NR_UE_MAC_INST_t *mac)
void release_mac_configuration(NR_UE_MAC_INST_t *mac,
NR_UE_MAC_reset_cause_t cause)
{
asn1cFreeStruc(asn_DEF_NR_MIB, mac->mib);
asn1cFreeStruc(asn_DEF_NR_SI_SchedulingInfo, mac->si_SchedulingInfo);
asn1cFreeStruc(asn_DEF_NR_TDD_UL_DL_ConfigCommon, mac->tdd_UL_DL_ConfigurationCommon);
NR_UE_ServingCell_Info_t *sc = &mac->sc_info;
// if cause is Re-establishment, release spCellConfig only
if (cause == GO_TO_IDLE) {
asn1cFreeStruc(asn_DEF_NR_MIB, mac->mib);
asn1cFreeStruc(asn_DEF_NR_SearchSpace, mac->search_space_zero);
asn1cFreeStruc(asn_DEF_NR_ControlResourceSet, mac->coreset0);
asn1cFreeStruc(asn_DEF_NR_SI_SchedulingInfo, mac->si_SchedulingInfo);
asn1cFreeStruc(asn_DEF_NR_TDD_UL_DL_ConfigCommon, mac->tdd_UL_DL_ConfigurationCommon);
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i];
asn_sequence_del(&mac->lc_ordered_list, i, 0);
free(lc_info);
}
}
asn1cFreeStruc(asn_DEF_NR_CrossCarrierSchedulingConfig, sc->crossCarrierSchedulingConfig);
asn1cFreeStruc(asn_DEF_NR_SRS_CarrierSwitching, sc->carrierSwitching);
asn1cFreeStruc(asn_DEF_NR_UplinkConfig, sc->supplementaryUplink);
@@ -218,20 +243,35 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac)
mac->current_DL_BWP = NULL;
mac->current_UL_BWP = NULL;
for (int i = 0; i < mac->dl_BWPs.count; i++)
release_dl_BWP(mac, i);
for (int i = 0; i < mac->ul_BWPs.count; i++)
release_ul_BWP(mac, i);
asn1cFreeStruc(asn_DEF_NR_SearchSpace, mac->search_space_zero);
asn1cFreeStruc(asn_DEF_NR_ControlResourceSet, mac->coreset0);
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i];
asn_sequence_del(&mac->lc_ordered_list, i, 0);
free(lc_info);
// in case of re-establishment we don't need to release initial BWP config common
int first_bwp_rel = 0; // first BWP to release
if (cause == RE_ESTABLISHMENT) {
first_bwp_rel = 1;
// release dedicated BWP0 config
NR_UE_DL_BWP_t *bwp = mac->dl_BWPs.array[0];
NR_BWP_PDCCH_t *pdcch = &mac->config_BWP_PDCCH[0];
for (int i = 0; pdcch->list_Coreset.count; i++)
asn_sequence_del(&pdcch->list_Coreset, i, 1);
for (int i = 0; pdcch->list_SS.count; i++)
asn_sequence_del(&pdcch->list_SS, i, 1);
asn1cFreeStruc(asn_DEF_NR_PDSCH_Config, bwp->pdsch_Config);
NR_UE_UL_BWP_t *ubwp = mac->ul_BWPs.array[0];
asn1cFreeStruc(asn_DEF_NR_PUCCH_Config, ubwp->pucch_Config);
asn1cFreeStruc(asn_DEF_NR_SRS_Config, ubwp->srs_Config);
asn1cFreeStruc(asn_DEF_NR_PUSCH_Config, ubwp->pusch_Config);
mac->current_DL_BWP = bwp;
mac->current_UL_BWP = ubwp;
mac->sc_info.initial_dl_BWPSize = bwp->BWPSize;
mac->sc_info.initial_dl_BWPStart = bwp->BWPStart;
mac->sc_info.initial_ul_BWPSize = ubwp->BWPSize;
mac->sc_info.initial_ul_BWPStart = ubwp->BWPStart;
}
for (int i = first_bwp_rel; i < mac->dl_BWPs.count; i++)
release_dl_BWP(mac, i);
for (int i = first_bwp_rel; i < mac->ul_BWPs.count; i++)
release_ul_BWP(mac, i);
memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements));
memset(&mac->csirs_measurements, 0, sizeof(mac->csirs_measurements));
memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment));
+9 -10
View File
@@ -563,7 +563,7 @@ void nr_get_prach_resources(NR_UE_MAC_INST_t *mac,
void nr_Msg1_transmitted(NR_UE_MAC_INST_t *mac)
{
RA_config_t *ra = &mac->ra;
ra->ra_state = WAIT_RAR;
ra->ra_state = nrRA_WAIT_RAR;
ra->RA_attempt_number++;
}
@@ -580,7 +580,7 @@ void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, s
nr_timer_setup(&ra->contention_resolution_timer, RA_contention_resolution_timer_subframes * subframes_per_slot, 1);
nr_timer_start(&ra->contention_resolution_timer);
ra->ra_state = WAIT_CONTENTION_RESOLUTION;
ra->ra_state = nrRA_WAIT_CONTENTION_RESOLUTION;
}
void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max)
@@ -645,10 +645,10 @@ void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB
NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources;
// Delay init RA procedure to allow the convergence of the IIR filter on PRACH noise measurements at gNB side
if (ra->ra_state == RA_UE_IDLE) {
if (ra->ra_state == nrRA_UE_IDLE) {
if ((mac->first_sync_frame > -1 || get_softmodem_params()->do_ra || get_softmodem_params()->nsa) &&
((MAX_FRAME_NUMBER + frame - mac->first_sync_frame) % MAX_FRAME_NUMBER) > 150) {
ra->ra_state = GENERATE_PREAMBLE;
ra->ra_state = nrRA_GENERATE_PREAMBLE;
} else {
LOG_D(NR_MAC,"PRACH Condition not met: ra state %d, frame %d, sync_frame %d\n", ra->ra_state, frame, mac->first_sync_frame);
return;
@@ -657,8 +657,7 @@ void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB
LOG_D(NR_MAC, "[UE %d][%d.%d]: ra_state %d, RA_active %d\n", mac->ue_id, frame, nr_slot_tx, ra->ra_state, ra->RA_active);
if (ra->ra_state > RA_UE_IDLE && ra->ra_state < RA_SUCCEEDED) {
if (ra->ra_state > nrRA_UE_IDLE && ra->ra_state < nrRA_SUCCEEDED) {
if (ra->RA_active == 0) {
NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon;
NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric;
@@ -726,7 +725,7 @@ void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB
// Fill in preamble and PRACH resources
ra->RA_window_cnt--;
if (ra->ra_state == GENERATE_PREAMBLE) {
if (ra->ra_state == nrRA_GENERATE_PREAMBLE) {
nr_get_prach_resources(mac, CC_id, gNB_id, prach_resources, rach_ConfigDedicated);
}
} else if (ra->RA_backoff_cnt > 0) {
@@ -735,7 +734,7 @@ void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB
ra->RA_backoff_cnt--;
if ((ra->RA_backoff_cnt > 0 && ra->ra_state == GENERATE_PREAMBLE) || ra->RA_backoff_cnt == 0) {
if ((ra->RA_backoff_cnt > 0 && ra->ra_state == nrRA_GENERATE_PREAMBLE) || ra->RA_backoff_cnt == 0) {
nr_get_prach_resources(mac, CC_id, gNB_id, prach_resources, rach_ConfigDedicated);
}
}
@@ -828,7 +827,7 @@ void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame
LOG_D(MAC, "[UE %d] clearing RA_active flag...\n", mac->ue_id);
ra->RA_active = 0;
ra->ra_state = RA_SUCCEEDED;
ra->ra_state = nrRA_SUCCEEDED;
mac->state = UE_CONNECTED;
free_and_zero(ra->Msg3_buffer);
nr_mac_rrc_ra_ind(mac->ue_id, frame, true);
@@ -854,7 +853,7 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr
ra->first_Msg3 = true;
ra->ra_PreambleIndex = -1;
ra->ra_state = RA_UE_IDLE;
ra->ra_state = nrRA_UE_IDLE;
prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER++;
@@ -160,7 +160,7 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac,
rel15->coreset.pdcch_dmrs_scrambling_id = mac->physCellId;
}
rel15->num_dci_options = (mac->ra.ra_state == WAIT_RAR || rnti_type == TYPE_SI_RNTI_) ? 1 : 2;
rel15->num_dci_options = (mac->ra.ra_state == nrRA_WAIT_RAR || rnti_type == TYPE_SI_RNTI_) ? 1 : 2;
if (ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) {
if (ss->searchSpaceType->choice.ue_Specific->dci_Formats ==
@@ -406,11 +406,11 @@ bool is_ss_monitor_occasion(const int frame, const int slot, const int slots_per
return monitor;
}
bool monitior_dci_for_other_SI(NR_UE_MAC_INST_t *mac,
const NR_SearchSpace_t *ss,
const int slots_per_frame,
const int frame,
const int slot)
bool monitor_dci_for_other_SI(NR_UE_MAC_INST_t *mac,
const NR_SearchSpace_t *ss,
const int slots_per_frame,
const int frame,
const int slot)
{
const struct NR_SI_SchedulingInfo *si_SchedulingInfo = mac->si_SchedulingInfo;
// 5.2.2.3.2 in 331
@@ -444,18 +444,12 @@ bool monitior_dci_for_other_SI(NR_UE_MAC_INST_t *mac,
for (int i = 0; i < duration; i++) {
if (((frame * slots_per_frame + slot - offset - i) % period) == 0) {
int N = mac->ssb_list[bwp_id].nb_tx_ssb;
int K = 0; // k_th transmitted SSB
for (int i = 0; i < mac->mib_ssb; i++) {
if(mac->ssb_list[bwp_id].tx_ssb[i].transmitted)
K++;
}
int K = mac->ssb_list->nb_ssb_per_index[mac->mib_ssb];
// numbering current frame and slot in terms of monitoring occasions in window
int current_monitor_occasion = ((abs_slot - mac->si_window_start) % period) +
(duration * (abs_slot - mac->si_window_start) / period);
if (current_monitor_occasion % N == K)
return true;
else
return false;
return current_monitor_occasion % N == K;
}
}
}
@@ -508,20 +502,18 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl
// are same as PDCCH monitoring occasions for SIB1
const NR_SearchSpace_t *ss = pdcch_config->otherSI_SS ? pdcch_config->otherSI_SS : mac->search_space_zero;
// TODO configure SI-window
if (monitior_dci_for_other_SI(mac, ss, slots_per_frame, frame, slot)) {
if (monitor_dci_for_other_SI(mac, ss, slots_per_frame, frame, slot)) {
LOG_D(NR_MAC_DCI, "Monitoring DCI for other SIs in frame %d slot %d\n", frame, slot);
config_dci_pdu(mac, dl_config, TYPE_SI_RNTI_, slot, ss);
}
}
if (mac->state == UE_PERFORMING_RA &&
mac->ra.ra_state >= WAIT_RAR) {
if (mac->state == UE_PERFORMING_RA && mac->ra.ra_state >= nrRA_WAIT_RAR) {
// if RA is ongoing use RA search space
if (is_ss_monitor_occasion(frame, slot, slots_per_frame, pdcch_config->ra_SS)) {
int rnti_type = mac->ra.ra_state == WAIT_RAR ? TYPE_RA_RNTI_ : TYPE_TC_RNTI_;
int rnti_type = mac->ra.ra_state == nrRA_WAIT_RAR ? TYPE_RA_RNTI_ : TYPE_TC_RNTI_;
config_dci_pdu(mac, dl_config, rnti_type, slot, pdcch_config->ra_SS);
}
}
else if (mac->state == UE_CONNECTED) {
} else if (mac->state == UE_CONNECTED) {
for (int i = 0; i < pdcch_config->list_SS.count; i++) {
NR_SearchSpace_t *ss = pdcch_config->list_SS.array[i];
if (is_ss_monitor_occasion(frame, slot, slots_per_frame, ss))
+7 -9
View File
@@ -178,7 +178,7 @@ int get_rnti_type(const NR_UE_MAC_INST_t *mac, const uint16_t rnti)
if (rnti == ra->ra_rnti) {
rnti_type = TYPE_RA_RNTI_;
} else if (rnti == ra->t_crnti && (ra->ra_state == WAIT_RAR || ra->ra_state == WAIT_CONTENTION_RESOLUTION)) {
} else if (rnti == ra->t_crnti && (ra->ra_state == nrRA_WAIT_RAR || ra->ra_state == nrRA_WAIT_CONTENTION_RESOLUTION)) {
rnti_type = TYPE_TC_RNTI_;
} else if (rnti == mac->crnti) {
rnti_type = TYPE_C_RNTI_;
@@ -264,7 +264,7 @@ int8_t nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac,
{
if(ack_nack) {
LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n");
nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len);
nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len);
mac->get_sib1 = false;
mac->get_otherSI = false;
}
@@ -3504,7 +3504,7 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i
// MAC SDU: 6 bytes (UE Contention Resolution Identity)
mac_len = 6;
if(ra->ra_state == WAIT_CONTENTION_RESOLUTION) {
if (ra->ra_state == nrRA_WAIT_CONTENTION_RESOLUTION) {
LOG_I(MAC, "[UE %d][RAPROC] Frame %d : received contention resolution identity: 0x%02x%02x%02x%02x%02x%02x Terminating RA procedure\n",
mac->ue_id,
frameP,
@@ -3530,7 +3530,7 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i
} else if (!ra_success){
// TODO: Handle failure of RA procedure @ MAC layer
// nr_ra_failed(module_idP, CC_id, prach_resources, frameP, slot); // prach_resources is a PHY structure
ra->ra_state = RA_UE_IDLE;
ra->ra_state = nrRA_UE_IDLE;
ra->RA_active = 0;
}
}
@@ -3609,8 +3609,7 @@ int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
pdu, mac_ce);
}
if (crnti && (!get_softmodem_params()->sa && get_softmodem_params()->do_ra && mac->ra.ra_state != RA_SUCCEEDED)) {
if (crnti && (!get_softmodem_params()->sa && get_softmodem_params()->do_ra && mac->ra.ra_state != nrRA_SUCCEEDED)) {
LOG_D(NR_MAC, "In %s: generating C-RNTI MAC CE with C-RNTI %x\n", __FUNCTION__, (*crnti));
// MAC CE fixed subheader
@@ -3625,7 +3624,6 @@ int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
mac_ce_size = sizeof(uint16_t);
mac_ce += mac_ce_size;
mac_ce_len += mac_ce_size + sizeof(NR_MAC_SUBHEADER_FIXED);
}
if (truncated_bsr) {
@@ -3774,7 +3772,7 @@ int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
// - optimize: mu_pusch, j and table_6_1_2_1_1_2_time_dom_res_alloc_A are already defined in nr_ue_procedures
static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id)
{
frame_t frame = dl_info->frame;
frame_t frame = dl_info->frame;
int slot = dl_info->slot;
if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack == 0) {
@@ -3976,7 +3974,7 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d
if (!ra->cfra) {
ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8);
rnti = ra->t_crnti;
nr_mac_rrc_msg3_ind(mac->ue_id, rnti);
nr_mac_rrc_msg3_ind(mac->ue_id, rnti, dl_info->gNB_index);
}
fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH);
if (!pdu)
+162 -254
View File
@@ -553,6 +553,9 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
pusch_config_pdu->bwp_start = current_UL_BWP->BWPStart;
pusch_config_pdu->bwp_size = current_UL_BWP->BWPSize;
pusch_config_pdu->start_symbol_index = tda_info->startSymbolIndex;
pusch_config_pdu->nr_of_symbols = tda_info->nrOfSymbols;
/* Transform precoding */
pusch_config_pdu->transform_precoding = get_transformPrecoding(current_UL_BWP, dci_format, 0);
@@ -637,9 +640,6 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
return -1;
}
pusch_config_pdu->start_symbol_index = tda_info->startSymbolIndex;
pusch_config_pdu->nr_of_symbols = tda_info->nrOfSymbols;
/* FREQ_HOPPING_FLAG */
if ((pusch_Config!=NULL) && (pusch_Config->frequencyHopping!=NULL) && (pusch_Config->resourceAllocation != NR_PUSCH_Config__resourceAllocation_resourceAllocationType0)){
pusch_config_pdu->frequency_hopping = dci->frequency_hopping_flag.val;
@@ -1075,7 +1075,7 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator,
TBS_bytes,
ra->ra_state);
if (ra->ra_state == WAIT_RAR && !ra->cfra) {
if (ra->ra_state == nrRA_WAIT_RAR && !ra->cfra) {
nr_get_msg3_payload(mac, ulsch_input_buffer, TBS_bytes);
for (int k = 0; k < TBS_bytes; k++) {
LOG_D(NR_MAC, "(%i): 0x%x\n", k, ulsch_input_buffer[k]);
@@ -1083,7 +1083,7 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
mac_pdu_exist = 1;
} else {
if (ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator
&& (mac->state == UE_CONNECTED || (ra->ra_state == WAIT_RAR && ra->cfra))) {
&& (mac->state == UE_CONNECTED || (ra->ra_state == nrRA_WAIT_RAR && ra->cfra))) {
// Getting IP traffic to be transmitted
nr_ue_get_sdu(mac, cc_id, frame_tx, slot_tx, gNB_index, ulsch_input_buffer, TBS_bytes);
mac_pdu_exist = 1;
@@ -1096,13 +1096,13 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
ulcfg_pdu->pusch_config_pdu.tx_request_body.pdu_length = TBS_bytes;
number_of_pdus++;
}
if (ra->ra_state == WAIT_CONTENTION_RESOLUTION && !ra->cfra) {
if (ra->ra_state == nrRA_WAIT_CONTENTION_RESOLUTION && !ra->cfra) {
LOG_I(NR_MAC, "[RAPROC][%d.%d] RA-Msg3 retransmitted\n", frame_tx, slot_tx);
// 38.321 restart the ra-ContentionResolutionTimer at each HARQ retransmission in the first symbol after the end of the Msg3
// transmission
nr_Msg3_transmitted(mac, cc_id, frame_tx, slot_tx, gNB_index);
}
if (ra->ra_state == WAIT_RAR && !ra->cfra) {
if (ra->ra_state == nrRA_WAIT_RAR && !ra->cfra) {
LOG_A(NR_MAC, "[RAPROC][%d.%d] RA-Msg3 transmitted\n", frame_tx, slot_tx);
nr_Msg3_transmitted(mac, cc_id, frame_tx, slot_tx, gNB_index);
}
@@ -1697,19 +1697,19 @@ static void build_ro_list(NR_UE_MAC_INST_t *mac)
prach_occasion_slot_t *slot_map = &prach_conf_period_list->prach_occasion_slot_map[frame_idx][slot];
slot_map->nb_of_prach_occasion_in_time = N_t_slot;
slot_map->nb_of_prach_occasion_in_freq = nb_fdm;
slot_map->prach_occasion = malloc(N_t_slot * nb_fdm * sizeof(*slot_map->prach_occasion));
AssertFatal(slot_map->prach_occasion, "no memory available\n");
for (int n_prach_occ_in_time = 0; n_prach_occ_in_time < N_t_slot; n_prach_occ_in_time++) {
uint8_t start_symbol = prach_conf_start_symbol + n_prach_occ_in_time * N_dur;
LOG_D(NR_MAC,"PRACH Occ in time %d\n", n_prach_occ_in_time);
for (int n_prach_occ_in_freq = 0; n_prach_occ_in_freq < nb_fdm; n_prach_occ_in_freq++) {
prach_occasion_info_t *prach_occasion_p = &slot_map->prach_occasion[n_prach_occ_in_time][n_prach_occ_in_freq];
prach_occasion_p->start_symbol = start_symbol;
prach_occasion_p->fdm = n_prach_occ_in_freq;
prach_occasion_p->frame = frame;
prach_occasion_p->slot = slot;
prach_occasion_p->format = format;
slot_map->prach_occasion[n_prach_occ_in_time * nb_fdm + n_prach_occ_in_freq] =
(prach_occasion_info_t){.start_symbol = start_symbol,
.fdm = n_prach_occ_in_freq,
.frame = frame,
.slot = slot,
.format = format};
prach_assoc_pattern->prach_conf_period_list[period_idx].nb_of_prach_occasion++;
LOG_D(NR_MAC,"Adding a PRACH occasion: frame %u, slot-symbol %d-%d, occ_in_time-occ_in-freq %d-%d, nb ROs in conf period %d, for this slot: RO# in time %d, RO# in freq %d\n",
@@ -1734,17 +1734,15 @@ static void build_ssb_list(NR_UE_MAC_INST_t *mac)
fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
ssb_list->nb_tx_ssb = 0;
for(int ssb_index = 0; ssb_index < 64; ssb_index++) {
for (int ssb_index = 0; ssb_index < MAX_NB_SSB; ssb_index++) {
uint32_t curr_mask = cfg->ssb_table.ssb_mask_list[ssb_index / 32].ssb_mask;
// check if if current SSB is transmitted
if ((curr_mask >> (31 - (ssb_index % 32))) & 0x01) {
ssb_list->nb_ssb_per_index[ssb_index]=ssb_list->nb_tx_ssb;
ssb_list->nb_tx_ssb++;
ssb_list->tx_ssb[ssb_index].transmitted = true;
LOG_D(NR_MAC,"SSB idx %d transmitted\n", ssb_index);
}
else
ssb_list->tx_ssb[ssb_index].transmitted = false;
}
ssb_list->tx_ssb = calloc(ssb_list->nb_tx_ssb, sizeof(*ssb_list->tx_ssb));
}
// Map the transmitted SSBs to the ROs and create the association pattern according to the config
@@ -1755,49 +1753,18 @@ static void map_ssb_to_ro(NR_UE_MAC_INST_t *mac)
NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon;
NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present;
bool multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB
uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB
uint16_t required_nb_of_prach_occasion; // Nb of RACH occasions required to map all the SSBs
uint8_t required_nb_of_prach_conf_period; // Nb of PRACH configuration periods required to map all the SSBs
const struct {
// true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB
bool multiple_ssb_per_ro;
// Nb of SSBs per RACH or RACHs per SSB
int ssb_rach_ratio;
} config[] = {{false, 0}, {false, 8}, {false, 4}, {false, 2}, {true, 1}, {true, 2}, {true, 4}, {true, 8}, {true, 16}};
AssertFatal(ssb_perRACH_config <= NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen,
"Unsupported ssb_perRACH_config %d\n",
ssb_perRACH_config);
const bool multiple_ssb_per_ro = config[ssb_perRACH_config].multiple_ssb_per_ro;
const int ssb_rach_ratio = config[ssb_perRACH_config].ssb_rach_ratio;
// Determine the SSB to RACH mapping ratio
switch (ssb_perRACH_config){
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 8;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 4;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 2;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 1;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 2;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 4;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 8;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 16;
break;
default:
AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config);
break;
}
LOG_D(NR_MAC,"SSB rach ratio %d, Multiple SSB per RO %d\n", ssb_rach_ratio, multiple_ssb_per_ro);
const int bwp_id = mac->current_UL_BWP->bwp_id;
@@ -1809,230 +1776,171 @@ static void map_ssb_to_ro(NR_UE_MAC_INST_t *mac)
// (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule)
// There is only one possible association period which can contain up to 16 PRACH configuration periods
LOG_D(NR_MAC,"Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period\n");
if (true == multiple_ssb_per_ro) {
required_nb_of_prach_occasion = ((ssb_list->nb_tx_ssb - 1) + ssb_rach_ratio) / ssb_rach_ratio;
}
else {
required_nb_of_prach_occasion = ssb_list->nb_tx_ssb * ssb_rach_ratio;
}
const int required_nb_of_prach_occasion =
multiple_ssb_per_ro ? ((ssb_list->nb_tx_ssb - 1) + ssb_rach_ratio) / ssb_rach_ratio : ssb_list->nb_tx_ssb * ssb_rach_ratio;
prach_association_pattern_t *prach_assoc_pattern = &mac->prach_assoc_pattern[bwp_id];
prach_association_period_t *prach_association_period_list = &prach_assoc_pattern->prach_association_period_list[0];
AssertFatal(prach_assoc_pattern->prach_conf_period_list[0].nb_of_prach_occasion > 0,
"prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion shouldn't be 0 (nb_tx_ssb %d, ssb_rach_ratio %d)\n",
ssb_list->nb_tx_ssb, ssb_rach_ratio);
required_nb_of_prach_conf_period =
((required_nb_of_prach_occasion - 1) + prach_assoc_pattern->prach_conf_period_list[0].nb_of_prach_occasion)
/ prach_assoc_pattern->prach_conf_period_list[0].nb_of_prach_occasion;
const prach_conf_period_t *prach_conf_period = &prach_assoc_pattern->prach_conf_period_list[0];
AssertFatal(prach_conf_period->nb_of_prach_occasion > 0,
"prach_conf_period->nb_of_prach_occasion shouldn't be 0 (nb_tx_ssb %d, ssb_rach_ratio %d)\n",
ssb_list->nb_tx_ssb,
ssb_rach_ratio);
prach_association_period_t *prach_association_period = &prach_assoc_pattern->prach_association_period_list[0];
const int required_nb_of_prach_conf_period =
((required_nb_of_prach_occasion - 1) + prach_conf_period->nb_of_prach_occasion) / prach_conf_period->nb_of_prach_occasion;
if (required_nb_of_prach_conf_period == 1) {
prach_association_period_list->nb_of_prach_conf_period = 1;
prach_association_period->nb_of_prach_conf_period = 1;
}
else if (required_nb_of_prach_conf_period == 2) {
prach_association_period_list->nb_of_prach_conf_period = 2;
prach_association_period->nb_of_prach_conf_period = 2;
}
else if (required_nb_of_prach_conf_period <= 4) {
prach_association_period_list->nb_of_prach_conf_period = 4;
prach_association_period->nb_of_prach_conf_period = 4;
}
else if (required_nb_of_prach_conf_period <= 8) {
prach_association_period_list->nb_of_prach_conf_period = 8;
prach_association_period->nb_of_prach_conf_period = 8;
}
else if (required_nb_of_prach_conf_period <= 16) {
prach_association_period_list->nb_of_prach_conf_period = 16;
prach_association_period->nb_of_prach_conf_period = 16;
}
else {
AssertFatal(1 == 0, "Invalid number of PRACH config periods within an association period %d\n", required_nb_of_prach_conf_period);
}
prach_assoc_pattern->nb_of_assoc_period = 1; // WIP: only one possible association period
prach_association_period_list->nb_of_frame = prach_association_period_list->nb_of_prach_conf_period * prach_assoc_pattern->prach_conf_period_list[0].nb_of_frame;;
prach_assoc_pattern->nb_of_frame = prach_association_period_list->nb_of_frame;
prach_association_period->nb_of_frame = prach_association_period->nb_of_prach_conf_period * prach_conf_period->nb_of_frame;
prach_assoc_pattern->nb_of_frame = prach_association_period->nb_of_frame;
LOG_D(NR_MAC,"Assoc period %d, Nb of frames in assoc period %d\n",
prach_association_period_list->nb_of_prach_conf_period,
prach_association_period_list->nb_of_frame);
LOG_D(NR_MAC,
"Assoc period %d, Nb of frames in assoc period %d\n",
prach_association_period->nb_of_prach_conf_period,
prach_association_period->nb_of_frame);
// Proceed to the SSB to RO mapping
uint8_t ssb_idx = 0;
uint8_t prach_configuration_period_idx; // PRACH Configuration period index within the association pattern
prach_conf_period_t *prach_conf_period_p;
// Set the starting PRACH Configuration period index in the association_pattern map for this particular association period
int prach_configuration_period_idx =
0; // WIP: only one possible association period so the starting PRACH configuration period is automatically 0
// Map all the association periods within the association pattern period
LOG_D(NR_MAC,"Proceed to the SSB to RO mapping\n");
for (int association_period_idx = 0; association_period_idx < prach_assoc_pattern->nb_of_assoc_period; association_period_idx++) {
uint8_t frame=0;
uint8_t slot=0;
uint8_t ro_in_time=0;
uint8_t ro_in_freq=0;
// Set the starting PRACH Configuration period index in the association_pattern map for this particular association period
prach_configuration_period_idx = 0; // WIP: only one possible association period so the starting PRACH configuration period is automatically 0
// Check if we need to map multiple SSBs per RO or multiple ROs per SSB
if (true == multiple_ssb_per_ro) {
// --------------------
// --------------------
// Multiple SSBs per RO
// --------------------
// --------------------
// Check if we need to map multiple SSBs per RO or multiple ROs per SSB
if (multiple_ssb_per_ro) {
const prach_association_period_t *end =
prach_assoc_pattern->prach_association_period_list + prach_assoc_pattern->nb_of_assoc_period;
for (prach_association_period_t *prach_period = prach_assoc_pattern->prach_association_period_list; prach_period < end;
prach_period++) {
// Set the starting PRACH Configuration period index in the association_pattern map for this particular association period
// WIP: only one possible association period so the starting PRACH configuration period is automatically 0
// WIP: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO
// this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule
ssb_idx = 0;
// Go through the list of PRACH config periods within this association period
prach_association_period_list = &prach_assoc_pattern->prach_association_period_list[association_period_idx];
for (int n_prach_conf=0; n_prach_conf < prach_association_period_list->nb_of_prach_conf_period; n_prach_conf++, prach_configuration_period_idx++) {
int ssb_idx = 0;
bool done = false;
for (int i = 0; i < prach_period->nb_of_prach_conf_period && !done; i++, prach_configuration_period_idx++) {
prach_period->prach_conf_period_list[i] = &prach_assoc_pattern->prach_conf_period_list[prach_configuration_period_idx];
prach_conf_period_t *prach_conf = prach_period->prach_conf_period_list[i];
// Build the association period with its association PRACH Configuration indexes
prach_conf_period_p = &prach_assoc_pattern->prach_conf_period_list[prach_configuration_period_idx];
prach_association_period_list->prach_conf_period_list[n_prach_conf] = prach_conf_period_p;
// Go through all the ROs within the PRACH config period
for (frame=0; frame<prach_conf_period_p->nb_of_frame; frame++) {
for (slot=0; slot<prach_conf_period_p->nb_of_slot; slot++) {
for (ro_in_time=0; ro_in_time<prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) {
for (ro_in_freq=0; ro_in_freq<prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) {
prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq];
for (int frame = 0; frame < prach_conf->nb_of_frame && !done; frame++) {
for (int slot = 0; slot < prach_conf->nb_of_slot && !done; slot++) {
prach_occasion_slot_t *slot_map = &prach_conf->prach_occasion_slot_map[frame][slot];
for (int ro_in_time = 0; ro_in_time < slot_map->nb_of_prach_occasion_in_time && !done; ro_in_time++) {
for (int ro_in_freq = 0; ro_in_freq < slot_map->nb_of_prach_occasion_in_freq && !done; ro_in_freq++) {
prach_occasion_info_t *ro_p =
slot_map->prach_occasion + ro_in_time * slot_map->nb_of_prach_occasion_in_freq + ro_in_freq;
// Go through the list of transmitted SSBs and map the required amount of SSBs to this RO
// WIP: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO
// this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule
for (; ssb_idx<MAX_NB_SSB; ssb_idx++) {
for (; ssb_idx < ssb_list->nb_tx_ssb; ssb_idx++) {
ssb_info_t *tx_ssb = ssb_list->tx_ssb + ssb_idx;
// Map only the transmitted ssb_idx
if (true == ssb_list->tx_ssb[ssb_idx].transmitted) {
ro_p->mapped_ssb_idx[ro_p->nb_mapped_ssb] = ssb_idx;
ro_p->nb_mapped_ssb++;
ssb_list->tx_ssb[ssb_idx].mapped_ro[ssb_list->tx_ssb[ssb_idx].nb_mapped_ro] = ro_p;
ssb_list->tx_ssb[ssb_idx].nb_mapped_ro++;
AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list->tx_ssb[ssb_idx].nb_mapped_ro,
"Too many mapped ROs (%d) to a single SSB\n",
ssb_list->tx_ssb[ssb_idx].nb_mapped_ro);
LOG_D(NR_MAC, "Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n",
ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq,
prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq);
LOG_D(NR_MAC, "Nb mapped ROs for this ssb idx: in the association period only %u\n",
ssb_list->tx_ssb[ssb_idx].nb_mapped_ro);
// If all the required SSBs are mapped to this RO, exit the loop of SSBs
if (ro_p->nb_mapped_ssb == ssb_rach_ratio) {
ro_p->mapped_ssb_idx[ro_p->nb_mapped_ssb] = ssb_idx;
ro_p->nb_mapped_ssb++;
AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > tx_ssb->nb_mapped_ro + 1,
"Too many mapped ROs (%d) to a single SSB\n",
tx_ssb->nb_mapped_ro);
tx_ssb->mapped_ro[tx_ssb->nb_mapped_ro] = ro_p;
tx_ssb->nb_mapped_ro++;
LOG_D(NR_MAC,
"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n"
"Nb mapped ROs for this ssb idx: in the association period only %u\n",
ssb_idx,
ro_p->slot,
ro_p->start_symbol,
slot,
ro_in_time,
ro_in_freq,
slot_map->nb_of_prach_occasion_in_freq,
tx_ssb->nb_mapped_ro);
// If all the required SSBs are mapped to this RO, exit the loop of SSBs
if (ro_p->nb_mapped_ssb == ssb_rach_ratio) {
ssb_idx++;
break;
}
} // if ssb_idx is transmitted
} // for ssb_idx
// Exit the loop of ROs if there is no more SSB to map
if (MAX_NB_SSB == ssb_idx) break;
} // for ro_in_freq
// Exit the loop of ROs if there is no more SSB to map
if (MAX_NB_SSB == ssb_idx) break;
} // for ro_in_time
// Exit the loop of slots if there is no more SSB to map
if (MAX_NB_SSB == ssb_idx) break;
} // for slot
// Exit the loop frames if there is no more SSB to map
if (MAX_NB_SSB == ssb_idx) break;
} // for frame
// Exit the loop of PRACH configurations if there is no more SSB to map
if (MAX_NB_SSB == ssb_idx) break;
} // for n_prach_conf
// WIP: note that there is no re-mapping of the SSBs within the association period since there is no invalid ROs in the PRACH config periods that would create this situation
} // if multiple_ssbs_per_ro
else {
// --------------------
// --------------------
// Multiple ROs per SSB
// --------------------
// --------------------
}
done = MAX_NB_SSB == ssb_idx;
}
}
}
}
}
}
} else {
prach_association_period_t *end = prach_assoc_pattern->prach_association_period_list + prach_assoc_pattern->nb_of_assoc_period;
for (prach_association_period_t *prach_period = prach_assoc_pattern->prach_association_period_list; prach_period < end;
prach_period++) {
// Go through the list of transmitted SSBs
for (ssb_idx=0; ssb_idx<MAX_NB_SSB; ssb_idx++) {
for (int ssb_idx = 0; ssb_idx < ssb_list->nb_tx_ssb; ssb_idx++) {
ssb_info_t *tx_ssb = ssb_list->tx_ssb + ssb_idx;
uint8_t nb_mapped_ro_in_association_period=0; // Reset the nb of mapped ROs for the new SSB index
LOG_D(NR_MAC,"Checking ssb_idx %d => %d\n",
ssb_idx, ssb_list->tx_ssb[ssb_idx].transmitted);
bool done = false;
// Map all the required ROs to this SSB
// Go through the list of PRACH config periods within this association period
for (int i = 0; i < prach_period->nb_of_prach_conf_period && !done; i++, prach_configuration_period_idx++) {
// Build the association period with its association PRACH Configuration indexes
prach_period->prach_conf_period_list[i] = &prach_assoc_pattern->prach_conf_period_list[prach_configuration_period_idx];
prach_conf_period_t *prach_conf = prach_period->prach_conf_period_list[i];
for (int frame = 0; frame < prach_conf->nb_of_frame && !done; frame++) {
for (int slot = 0; slot < prach_conf->nb_of_slot && !done; slot++) {
prach_occasion_slot_t *slot_map = &prach_conf->prach_occasion_slot_map[frame][slot];
for (int ro_in_time = 0; ro_in_time < slot_map->nb_of_prach_occasion_in_time && !done; ro_in_time++) {
for (int ro_in_freq = 0; ro_in_freq < slot_map->nb_of_prach_occasion_in_freq && !done; ro_in_freq++) {
prach_occasion_info_t *ro_p =
slot_map->prach_occasion + ro_in_time * slot_map->nb_of_prach_occasion_in_freq + ro_in_freq;
ro_p->mapped_ssb_idx[0] = ssb_idx;
ro_p->nb_mapped_ssb = 1;
AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > tx_ssb->nb_mapped_ro + 1,
"Too many mapped ROs (%d) to a single SSB\n",
tx_ssb->nb_mapped_ro);
tx_ssb->mapped_ro[tx_ssb->nb_mapped_ro] = ro_p;
tx_ssb->nb_mapped_ro++;
nb_mapped_ro_in_association_period++;
done = nb_mapped_ro_in_association_period == ssb_rach_ratio;
// Map only the transmitted ssb_idx
if (true == ssb_list->tx_ssb[ssb_idx].transmitted) {
// Map all the required ROs to this SSB
// Go through the list of PRACH config periods within this association period
for (int n_prach_conf = 0; n_prach_conf<prach_assoc_pattern->prach_association_period_list[association_period_idx].nb_of_prach_conf_period; n_prach_conf++, prach_configuration_period_idx++) {
// Build the association period with its association PRACH Configuration indexes
prach_conf_period_p = &prach_assoc_pattern->prach_conf_period_list[prach_configuration_period_idx];
prach_assoc_pattern->prach_association_period_list[association_period_idx].prach_conf_period_list[n_prach_conf] = prach_conf_period_p;
for (; frame<prach_conf_period_p->nb_of_frame; frame++) {
for (; slot<prach_conf_period_p->nb_of_slot; slot++) {
for (; ro_in_time<prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) {
for (; ro_in_freq<prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) {
prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq];
ro_p->mapped_ssb_idx[0] = ssb_idx;
ro_p->nb_mapped_ssb = 1;
ssb_list->tx_ssb[ssb_idx].mapped_ro[ssb_list->tx_ssb[ssb_idx].nb_mapped_ro] = ro_p;
ssb_list->tx_ssb[ssb_idx].nb_mapped_ro++;
AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list->tx_ssb[ssb_idx].nb_mapped_ro,
"Too many mapped ROs (%d) to a single SSB\n",
ssb_list->tx_ssb[ssb_idx].nb_mapped_ro);
nb_mapped_ro_in_association_period++;
LOG_D(NR_MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n",
ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq,
prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq);
LOG_D(NR_MAC, "Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n",
ssb_list->tx_ssb[ssb_idx].nb_mapped_ro, nb_mapped_ro_in_association_period);
// Exit the loop if this SSB has been mapped to all the required ROs
// WIP: Assuming that ssb_rach_ratio equals the maximum nb of times a given ssb_idx is mapped within an association period:
// this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule
if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
ro_in_freq++;
break;
}
} // for ro_in_freq
LOG_D(NR_MAC,
"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n"
"Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n",
ssb_idx,
ro_p->slot,
ro_p->start_symbol,
slot,
ro_in_time,
ro_in_freq,
slot_map->nb_of_prach_occasion_in_freq,
tx_ssb->nb_mapped_ro,
nb_mapped_ro_in_association_period);
// Exit the loop if this SSB has been mapped to all the required ROs
if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
break;
}
else ro_in_freq = 0; // else go to the next time symbol in that slot and reset the freq index
} // for ro_in_time
// Exit the loop if this SSB has been mapped to all the required ROs
if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
break;
// WIP: Assuming that ssb_rach_ratio equals the maximum nb of times a given ssb_idx is mapped within an
// association period:
// this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule
}
else ro_in_time = 0; // else go to the next slot in that PRACH config period and reset the symbol index
} // for slot
// Exit the loop if this SSB has been mapped to all the required ROs
if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
break;
}
else slot = 0; // else go to the next frame in that PRACH config period and reset the slot index
} // for frame
// Exit the loop if this SSB has been mapped to all the required ROs
if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
break;
}
else frame = 0; // else go to the next PRACH config period in that association period and reset the frame index
} // for n_prach_conf
} // if ssb_idx is transmitted
} // for ssb_idx
} // else if multiple_ssbs_per_ro
} // for association_period_index
}
}
}
}
}
}
// Returns a RACH occasion if any matches the SSB idx, the frame and the slot
@@ -2076,10 +1984,10 @@ static int get_nr_prach_info_from_ssb_index(prach_association_pattern_t *prach_a
for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) {
for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) {
prach_occasion_info_t *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq];
for (uint8_t ssb_nb=0; ssb_nb<prach_occasion_info_p->nb_mapped_ssb; ssb_nb++) {
if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) {
prach_occasion_info_t *ro_p =
prach_occasion_slot_p->prach_occasion + ro_in_time * prach_occasion_slot_p->nb_of_prach_occasion_in_freq + ro_in_freq;
for (uint8_t ssb_nb = 0; ssb_nb < ro_p->nb_mapped_ssb; ssb_nb++) {
if (ro_p->mapped_ssb_idx[ssb_nb] == ssb_idx) {
nb_mapped_ssb++;
}
}
@@ -2095,12 +2003,12 @@ static int get_nr_prach_info_from_ssb_index(prach_association_pattern_t *prach_a
nb_mapped_ssb=0;
for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) {
for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) {
prach_occasion_info_t *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq];
for (uint8_t ssb_nb=0; ssb_nb<prach_occasion_info_p->nb_mapped_ssb; ssb_nb++) {
if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) {
prach_occasion_info_t *ro_p =
prach_occasion_slot_p->prach_occasion + ro_in_time * prach_occasion_slot_p->nb_of_prach_occasion_in_freq + ro_in_freq;
for (uint8_t ssb_nb = 0; ssb_nb < ro_p->nb_mapped_ssb; ssb_nb++) {
if (ro_p->mapped_ssb_idx[ssb_nb] == ssb_idx) {
if (nb_mapped_ssb == random_ssb_nb) {
*prach_occasion_info_pp = prach_occasion_info_p;
*prach_occasion_info_pp = ro_p;
return 1;
}
else {
@@ -2501,7 +2409,7 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, sub_fra
{
RA_config_t *ra = &mac->ra;
ra->RA_offset = 2; // to compensate the rx frame offset at the gNB
if(ra->ra_state != GENERATE_PREAMBLE)
if (ra->ra_state != nrRA_GENERATE_PREAMBLE)
return;
fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
+2 -1
View File
@@ -942,7 +942,8 @@ bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig
uint8_t ra_index = 0;
/* checking for free RA process */
for(; ra_index < NR_NB_RA_PROC_MAX; ra_index++) {
if((cc->ra[ra_index].state == RA_IDLE) && (!cc->ra[ra_index].cfra)) break;
if ((cc->ra[ra_index].ra_state == nrRA_gNB_IDLE) && (!cc->ra[ra_index].cfra))
break;
}
if (ra_index == NR_NB_RA_PROC_MAX) {
LOG_E(NR_MAC, "RA processes are not available for CFRA RNTI %04x\n", rnti);
+45 -27
View File
@@ -574,7 +574,7 @@ void nr_initiate_ra_proc(module_id_t module_idP,
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
NR_RA_t *ra = &cc->ra[i];
if (ra->state != RA_IDLE)
if (ra->ra_state != nrRA_gNB_IDLE)
continue;
pr_found = 0;
@@ -648,21 +648,26 @@ void nr_initiate_ra_proc(module_id_t module_idP,
LOG_D(NR_MAC, "%s() Msg2[%04d%d] SFN/SF:%04d%d\n", __FUNCTION__, ra->Msg2_frame, ra->Msg2_slot, frameP, slotP);
int loop = 0;
bool exist_connected_ue, exist_in_pending_ra_ue;
if (ra->rnti == 0) { // This condition allows for the usage of a preconfigured rnti for the CFRA
rnti_t trial = 0;
do {
// 3GPP TS 38.321 version 15.13.0 Section 7.1 Table 7.1-1: RNTI values
ra->rnti = (taus() % 0xffef) + 1;
while (trial < 1 || trial > 0xffef)
trial = (taus() % 0xffef) + 1;
exist_connected_ue = find_nr_UE(&nr_mac->UE_info, trial) != NULL;
exist_in_pending_ra_ue = find_nr_RA_id(module_idP, CC_id, trial) != -1;
loop++;
} while (loop != 100
&& !((find_nr_UE(&nr_mac->UE_info, ra->rnti) == NULL) && (find_nr_RA_id(module_idP, CC_id, ra->rnti) == -1)
&& ra->rnti >= 0x1 && ra->rnti <= 0xffef));
} while (loop < 100 && (exist_connected_ue || exist_in_pending_ra_ue) );
if (loop == 100) {
LOG_E(NR_MAC, "[RAPROC] initialisation random access aborted\n");
abort();
LOG_E(NR_MAC, "[RAPROC] initialisation random access: no more available RNTIs for new UE\n");
NR_SCHED_UNLOCK(&nr_mac->sched_lock);
return;
}
ra->rnti = trial;
}
ra->state = Msg2;
ra->ra_state = nrRA_Msg2;
ra->RA_rnti = ra_rnti;
ra->preamble_index = preamble_index;
ra->beam_id = cc->ssb_index[beam_index];
@@ -887,7 +892,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
ra->UL_BWP.scs);
// reset state to wait msg3
ra->state = WAIT_Msg3;
ra->ra_state = nrRA_WAIT_Msg3;
ra->Msg3_frame = sched_frame;
ra->Msg3_slot = sched_slot;
@@ -951,7 +956,7 @@ static void nr_get_Msg3alloc(module_id_t module_id,
NrOfSymbols <= Msg3maxsymb) {
ra->Msg3_tda_id = i;
ra->msg3_startsymb = StartSymbolIndex;
ra->msg3_nrsymb = NrOfSymbols;
ra->msg3_nbSymb = NrOfSymbols;
ra->Msg3_slot = temp_slot;
break;
}
@@ -1134,13 +1139,13 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_f
NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP;
NR_UE_ServingCell_Info_t *sc_info = &ra->sc_info;
if (ra->state == RA_IDLE) {
if (ra->ra_state == nrRA_gNB_IDLE) {
LOG_W(NR_MAC,"RA is not active for RA %X. skipping msg3 scheduling\n", ra->rnti);
return;
}
const int scs = ul_bwp->scs;
const uint16_t mask = SL_to_bitmap(ra->msg3_startsymb, ra->msg3_nrsymb);
const uint16_t mask = SL_to_bitmap(ra->msg3_startsymb, ra->msg3_nbSymb);
int buffer_index = ul_buffer_index(ra->Msg3_frame, ra->Msg3_slot, scs, mac->vrb_map_UL_size);
uint16_t *vrb_map_UL = &RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[buffer_index * MAX_BWP_SIZE];
for (int i = 0; i < ra->msg3_nb_rb; ++i) {
@@ -1309,8 +1314,15 @@ static void nr_generate_Msg2(module_id_t module_idP,
pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].pm_idx = 0;
pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = 0;
LOG_A(NR_MAC,"[gNB %d][RAPROC] CC_id %d Frame %d, slotP %d: Generating RA-Msg2 DCI, rnti 0x%x, state %d, CoreSetType %d\n",
module_idP, CC_id, frameP, slotP, ra->RA_rnti, ra->state,pdcch_pdu_rel15->CoreSetType);
LOG_A(NR_MAC,
"[gNB %d][RAPROC] CC_id %d Frame %d, slotP %d: Generating RA-Msg2 DCI, rnti 0x%x, state %d, CoreSetType %d\n",
module_idP,
CC_id,
frameP,
slotP,
ra->RA_rnti,
ra->ra_state,
pdcch_pdu_rel15->CoreSetType);
// SCF222: PDU index incremented for each PDSCH PDU sent in TX control message. This is used to associate control
// information to data and is reset every slot.
@@ -1483,8 +1495,14 @@ static void nr_generate_Msg2(module_id_t module_idP,
vrb_map[BWPStart + rb + rbStart] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols);
}
ra->state = WAIT_Msg3;
LOG_D(NR_MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: rnti %04x RA state %d\n", module_idP, frameP, slotP, ra->rnti, ra->state);
ra->ra_state = nrRA_WAIT_Msg3;
LOG_D(NR_MAC,
"[gNB %d][RAPROC] Frame %d, Subframe %d: rnti %04x RA state %s\n",
module_idP,
frameP,
slotP,
ra->rnti,
nrra_text[ra->ra_state]);
}
}
@@ -1933,7 +1951,7 @@ static void nr_generate_Msg4(module_id_t module_idP,
vrb_map[BWPStart + rb + rbStart] |= SL_to_bitmap(msg4_tda.startSymbolIndex, msg4_tda.nrOfSymbols);
}
ra->state = WAIT_Msg4_ACK;
ra->ra_state = nrRA_WAIT_Msg4_ACK;
LOG_I(NR_MAC,"UE %04x Generate msg4: feedback at %4d.%2d, payload %d bytes, next state WAIT_Msg4_ACK\n", ra->rnti, pucch->frame, pucch->ul_slot, harq->tb_size);
}
}
@@ -1971,7 +1989,7 @@ static void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, s
}
} else {
LOG_I(NR_MAC, "(UE %04x) Received Nack of RA-Msg4. Preparing retransmission!\n", ra->rnti);
ra->state = Msg4;
ra->ra_state = nrRA_Msg4;
}
}
}
@@ -1981,7 +1999,7 @@ void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, NR_RA_t
/* we assume that this function is mutex-protected from outside */
NR_SCHED_ENSURE_LOCKED(&RC.nrmac[module_idP]->sched_lock);
LOG_D(NR_MAC,"[gNB %d][RAPROC] CC_id %d Frame %d Clear Random access information rnti %x\n", module_idP, CC_id, frameP, ra->rnti);
ra->state = RA_IDLE;
ra->ra_state = nrRA_gNB_IDLE;
ra->timing_offset = 0;
ra->RRC_timer = 20;
ra->msg3_round = 0;
@@ -2122,10 +2140,10 @@ void nr_schedule_RA(module_id_t module_idP,
NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
NR_RA_t *ra = &cc->ra[i];
LOG_D(NR_MAC, "RA[state:%d]\n", ra->state);
LOG_D(NR_MAC, "RA[state:%d]\n", ra->ra_state);
// Check RA Contention Resolution timer
if (ra->state >= WAIT_Msg3) {
if (ra->ra_state >= nrRA_WAIT_Msg3) {
ra->contention_resolution_timer--;
if (ra->contention_resolution_timer < 0) {
LOG_W(NR_MAC, "(%d.%d) RA Contention Resolution timer expired for UE 0x%04x, RA procedure failed...\n", frameP, slotP, ra->rnti);
@@ -2135,19 +2153,19 @@ void nr_schedule_RA(module_id_t module_idP,
}
}
switch (ra->state) {
case Msg2:
switch (ra->ra_state) {
case nrRA_Msg2:
nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req);
break;
case Msg3_retransmission:
case nrRA_Msg3_retransmission:
nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra, ul_dci_req);
break;
case Msg3_dcch_dtch:
case nrRA_Msg3_dcch_dtch:
/* fallthrough */
case Msg4:
case nrRA_Msg4:
nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req);
break;
case WAIT_Msg4_ACK:
case nrRA_WAIT_Msg4_ACK:
nr_check_Msg4_Ack(module_idP, CC_id, frameP, slotP, ra);
break;
default:
@@ -2000,15 +2000,12 @@ NR_UE_info_t *find_nr_UE(NR_UEs_t *UEs, rnti_t rntiP)
int find_nr_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP)
{
NR_RA_t *ra = &RC.nrmac[mod_idP]->common_channels[CC_idP].ra[0];
NR_RA_t *ra = RC.nrmac[mod_idP]->common_channels[CC_idP].ra;
for (int RA_id = 0; RA_id < NR_NB_RA_PROC_MAX; RA_id++) {
LOG_D(NR_MAC, "Checking RA_id %d for %x : state %d\n",
RA_id,
rntiP,
ra[RA_id].state);
LOG_D(NR_MAC, "Checking RA_id %d for %x : state %s\n", RA_id, rntiP, nrra_text[ra[RA_id].ra_state]);
if (ra[RA_id].state != RA_IDLE && ra[RA_id].rnti == rntiP)
if (ra[RA_id].ra_state != nrRA_gNB_IDLE && ra[RA_id].rnti == rntiP)
return RA_id;
}
@@ -223,7 +223,7 @@ static int nr_process_mac_pdu(instance_t module_idP,
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i];
if (ra->state >= WAIT_Msg3 && ra->rnti == UE->rnti) {
if (ra->ra_state >= nrRA_WAIT_Msg3 && ra->rnti == UE->rnti) {
// remove UE context just created after Msg.3 in some milliseconds
// as the UE is one already known (not now, as the UE context is
// still needed for the moment)
@@ -231,7 +231,7 @@ static int nr_process_mac_pdu(instance_t module_idP,
//mac_remove_nr_ue(RC.nrmac[module_idP], ra->rnti);
// this UE is the one identified by the RNTI in pduP
ra->rnti = ((pduP[1]&0xFF)<<8)|(pduP[2]&0xFF);
ra->state = Msg3_dcch_dtch;
ra->ra_state = nrRA_Msg3_dcch_dtch;
break;
}
}
@@ -315,7 +315,7 @@ static int nr_process_mac_pdu(instance_t module_idP,
NR_UE_info_t* UE_idx = UE;
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i];
if (ra->state >= WAIT_Msg3 && ra->rnti == UE->rnti) {
if (ra->ra_state >= nrRA_WAIT_Msg3 && ra->rnti == UE->rnti) {
uint8_t *next_subpduP = pduP + mac_subheader_len + mac_len;
if ((pduP[mac_subheader_len+mac_len] & 0x3F) == UL_SCH_LCID_C_RNTI) {
crnti = ((next_subpduP[1]&0xFF)<<8)|(next_subpduP[2]&0xFF);
@@ -488,7 +488,7 @@ static bool get_UE_waiting_CFRA_msg3(const gNB_MAC_INST *gNB_mac, const int CC_i
bool UE_waiting_CFRA_msg3 = false;
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
const NR_RA_t *ra = &gNB_mac->common_channels[CC_id].ra[i];
if (ra->cfra == true && ra->state == WAIT_Msg3 && frame == ra->Msg3_frame && slot == ra->Msg3_slot) {
if (ra->cfra == true && ra->ra_state == nrRA_WAIT_Msg3 && frame == ra->Msg3_frame && slot == ra->Msg3_slot) {
UE_waiting_CFRA_msg3 = true;
break;
}
@@ -512,7 +512,7 @@ void handle_nr_ul_harq(const int CC_idP,
LOG_D(NR_MAC, "handle harq for rnti %04x, in RA process\n", crc_pdu->rnti);
for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) {
NR_RA_t *ra = &nrmac->common_channels[CC_idP].ra[i];
if (ra->state >= WAIT_Msg3 && ra->rnti == crc_pdu->rnti) {
if (ra->ra_state >= nrRA_WAIT_Msg3 && ra->rnti == crc_pdu->rnti) {
NR_SCHED_UNLOCK(&nrmac->sched_lock);
return;
}
@@ -708,11 +708,11 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
* it. */
for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) {
NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i];
if (ra->state != WAIT_Msg3)
if (ra->ra_state != nrRA_WAIT_Msg3)
continue;
if(no_sig) {
LOG_D(NR_MAC, "Random Access %i failed at state %i (no signal)\n", i, ra->state);
LOG_D(NR_MAC, "Random Access %i failed at state %s (no signal)\n", i, nrra_text[ra->ra_state]);
nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
} else {
@@ -724,7 +724,12 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
current_rnti);
if( (frameP==ra->Msg3_frame) && (slotP==ra->Msg3_slot) ) {
LOG_D(NR_MAC, "Random Access %i failed at state %i (TC_RNTI %04x RNTI %04x)\n", i, ra->state,ra->rnti,current_rnti);
LOG_D(NR_MAC,
"Random Access %i failed at state %s (TC_RNTI %04x RNTI %04x)\n",
i,
nrra_text[ra->ra_state],
ra->rnti,
current_rnti);
nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
}
@@ -733,7 +738,12 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
NR_UE_info_t *UE_msg3_stage = UE ? UE : add_new_nr_ue(gNB_mac, ra->rnti, ra->CellGroup);
if (!UE_msg3_stage) {
LOG_W(NR_MAC, "Random Access %i discarded at state %i (TC_RNTI %04x RNTI %04x): max number of users achieved!\n", i, ra->state, ra->rnti, current_rnti);
LOG_W(NR_MAC,
"Random Access %i discarded at state %s (TC_RNTI %04x RNTI %04x): max number of users achieved!\n",
i,
nrra_text[ra->ra_state],
ra->rnti,
current_rnti);
nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
return;
@@ -789,8 +799,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
// harq_pid set a non valid value because it is not used in this call
// the function is only called to decode the contention resolution sub-header
if (nr_process_mac_pdu(gnb_mod_idP, UE_msg3_stage, CC_idP, frameP, slotP, sduP, sdu_lenP, -1) == 0) {
if (ra->state == Msg3_dcch_dtch) {
if (ra->ra_state == nrRA_Msg3_dcch_dtch) {
// Check if the UE identified by C-RNTI still exists at the gNB
NR_UE_info_t * UE_C = find_nr_UE(&gNB_mac->UE_info, ra->rnti);
if (!UE_C) {
@@ -815,11 +824,9 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", UE_C->rnti);
nr_mac_trigger_reconfiguration(RC.nrmac[gnb_mod_idP], UE_C);
}
}
else {
LOG_I(NR_MAC, "Activating scheduling RA-Msg4 for TC_RNTI 0x%04x (state %d)\n",
ra->rnti, ra->state);
ra->state = Msg4;
} else {
LOG_I(NR_MAC, "Activating scheduling RA-Msg4 for TC_RNTI 0x%04x (state %s)\n", ra->rnti, nrra_text[ra->ra_state]);
ra->ra_state = nrRA_Msg4;
}
}
else {
@@ -832,7 +839,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
} else {
for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) {
NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i];
if (ra->state != WAIT_Msg3)
if (ra->ra_state != nrRA_WAIT_Msg3)
continue;
if( (frameP!=ra->Msg3_frame) || (slotP!=ra->Msg3_slot))
@@ -840,13 +847,13 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
// for CFRA (NSA) do not schedule retransmission of msg3
if (ra->cfra) {
LOG_D(NR_MAC, "Random Access %i failed at state %i (NSA msg3 reception failed)\n", i, ra->state);
LOG_D(NR_MAC, "Random Access %i failed at state %s (NSA msg3 reception failed)\n", i, nrra_text[ra->ra_state]);
nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
return;
}
if (ra->msg3_round >= gNB_mac->ul_bler.harq_round_max - 1) {
LOG_W(NR_MAC, "Random Access %i failed at state %i (Reached msg3 max harq rounds)\n", i, ra->state);
LOG_W(NR_MAC, "Random Access %i failed at state %s (Reached msg3 max harq rounds)\n", i, nrra_text[ra->ra_state]);
nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
return;
}
@@ -854,7 +861,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
LOG_D(NR_MAC, "Random Access %i Msg3 CRC did not pass)\n", i);
ra->msg3_round++;
ra->state = Msg3_retransmission;
ra->ra_state = nrRA_Msg3_retransmission;
}
}
}
@@ -23,8 +23,11 @@
#include "mac_proto.h"
#include "openair2/F1AP/f1ap_ids.h"
#include "openair2/F1AP/f1ap_common.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include "F1AP_CauseRadioNetwork.h"
#include "openair3/ocp-gtpu/gtp_itf.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
#include "uper_decoder.h"
#include "uper_encoder.h"
@@ -34,6 +37,59 @@ const uint64_t qos_fiveqi[26] = {1, 2, 3, 4, 65, 66, 67, 71, 72, 73, 74, 76, 5,
const uint64_t qos_priority[26] = {20, 40, 30, 50, 7, 20, 15, 56, 56, 56, 56, 56, 10,
60, 70, 80, 90, 5, 55, 65, 68, 19, 22, 24, 21, 18};
static instance_t get_f1_gtp_instance(void)
{
const f1ap_cudu_inst_t *inst = getCxt(0);
if (!inst)
return -1; // means no F1
return inst->gtpInst;
}
static int drb_gtpu_create(instance_t instance,
uint32_t ue_id,
int incoming_id,
int outgoing_id,
int qfi,
in_addr_t tlAddress, // only IPv4 now
teid_t outgoing_teid,
gtpCallback callBack,
gtpCallbackSDAP callBackSDAP,
gtpv1u_gnb_create_tunnel_resp_t *create_tunnel_resp)
{
gtpv1u_gnb_create_tunnel_req_t create_tunnel_req = {0};
create_tunnel_req.incoming_rb_id[0] = incoming_id;
create_tunnel_req.pdusession_id[0] = outgoing_id;
memcpy(&create_tunnel_req.dst_addr[0].buffer, &tlAddress, sizeof(uint8_t) * 4);
create_tunnel_req.dst_addr[0].length = 32;
create_tunnel_req.outgoing_teid[0] = outgoing_teid;
create_tunnel_req.outgoing_qfi[0] = qfi;
create_tunnel_req.num_tunnels = 1;
create_tunnel_req.ue_id = ue_id;
// we use gtpv1u_create_ngu_tunnel because it returns the interface
// address and port of the interface; apart from that, we also might call
// newGtpuCreateTunnel() directly
return gtpv1u_create_ngu_tunnel(instance, &create_tunnel_req, create_tunnel_resp, callBack, callBackSDAP);
}
bool DURecvCb(protocol_ctxt_t *ctxt_pP,
const srb_flag_t srb_flagP,
const rb_id_t rb_idP,
const mui_t muiP,
const confirm_t confirmP,
const sdu_size_t sdu_buffer_sizeP,
unsigned char *const sdu_buffer_pP,
const pdcp_transmission_mode_t modeP,
const uint32_t *sourceL2Id,
const uint32_t *destinationL2Id)
{
// The buffer comes from the stack in gtp-u thread, we have a make a separate buffer to enqueue in a inter-thread message queue
uint8_t *sdu = malloc16(sdu_buffer_sizeP);
memcpy(sdu, sdu_buffer_pP, sdu_buffer_sizeP);
du_rlc_data_req(ctxt_pP, srb_flagP, false, rb_idP, muiP, confirmP, sdu_buffer_sizeP, sdu);
return true;
}
static long get_lcid_from_drbid(int drb_id)
{
return drb_id + 3; /* LCID is DRB + 3 */
@@ -133,6 +189,7 @@ static int handle_ue_context_drbs_setup(int rnti,
NR_CellGroupConfig_t *cellGroupConfig)
{
DevAssert(req_drbs != NULL && resp_drbs != NULL && cellGroupConfig != NULL);
instance_t f1inst = get_f1_gtp_instance();
/* Note: the actual GTP tunnels are created in the F1AP breanch of
* ue_context_*_response() */
@@ -140,12 +197,32 @@ static int handle_ue_context_drbs_setup(int rnti,
AssertFatal(*resp_drbs != NULL, "out of memory\n");
for (int i = 0; i < drbs_len; i++) {
const f1ap_drb_to_be_setup_t *drb = &req_drbs[i];
f1ap_drb_to_be_setup_t *resp_drb = &(*resp_drbs)[i];
NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb);
nr_rlc_add_drb(rnti, drb->drb_id, rlc_BearerConfig);
(*resp_drbs)[i] = *drb;
*resp_drb = *drb;
// just put same number of tunnels in DL as in UL
(*resp_drbs)[i].up_dl_tnl_length = drb->up_ul_tnl_length;
DevAssert(drb->up_ul_tnl_length == 1);
resp_drb->up_dl_tnl_length = drb->up_ul_tnl_length;
if (f1inst >= 0) { // we actually use F1-U
int qfi = -1; // don't put PDU session marker in GTP
gtpv1u_gnb_create_tunnel_resp_t resp_f1 = {0};
int ret = drb_gtpu_create(f1inst,
rnti,
drb->drb_id,
drb->drb_id,
qfi,
drb->up_ul_tnl[0].tl_address,
drb->up_ul_tnl[0].teid,
DURecvCb,
NULL,
&resp_f1);
AssertFatal(ret >= 0, "Unable to create GTP Tunnel for F1-U\n");
memcpy(&resp_drb->up_dl_tnl[0].tl_address, &resp_f1.gnb_addr.buffer, 4);
resp_drb->up_dl_tnl[0].teid = resp_f1.gnb_NGu_teid[0];
}
int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig);
DevAssert(ret == 0);
@@ -159,6 +236,7 @@ static int handle_ue_context_drbs_release(int rnti,
NR_CellGroupConfig_t *cellGroupConfig)
{
DevAssert(req_drbs != NULL && cellGroupConfig != NULL);
instance_t f1inst = get_f1_gtp_instance();
cellGroupConfig->rlc_BearerToReleaseList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToReleaseList));
AssertFatal(cellGroupConfig->rlc_BearerToReleaseList != NULL, "out of memory\n");
@@ -178,6 +256,8 @@ static int handle_ue_context_drbs_release(int rnti,
}
if (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) {
nr_rlc_release_entity(rnti, lcid);
if (f1inst >= 0)
newGtpuDeleteOneTunnel(f1inst, rnti, drb->rb_id);
asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1);
long *plcid = malloc(sizeof(*plcid));
AssertFatal(plcid != NULL, "out of memory\n");
@@ -557,6 +637,10 @@ void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd)
return;
}
instance_t f1inst = get_f1_gtp_instance();
if (f1inst >= 0)
newGtpuDeleteAllTunnels(f1inst, cmd->gNB_DU_ue_id);
if (UE->UE_sched_ctrl.ul_failure || cmd->rrc_container_length == 0) {
/* The UE is already not connected anymore or we have nothing to forward*/
nr_mac_release_ue(mac, cmd->gNB_DU_ue_id);
@@ -632,6 +716,9 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc)
pthread_mutex_unlock(&mac->sched_lock);
nr_rlc_remove_ue(dl_rrc->gNB_DU_ue_id);
nr_rlc_update_rnti(*dl_rrc->old_gNB_DU_ue_id, dl_rrc->gNB_DU_ue_id);
instance_t f1inst = get_f1_gtp_instance();
if (f1inst >= 0) // we actually use F1-U
gtpv1u_update_ue_id(f1inst, *dl_rrc->old_gNB_DU_ue_id, dl_rrc->gNB_DU_ue_id);
}
/* the DU ue id is the RNTI */
+21 -35
View File
@@ -85,6 +85,7 @@
/* MAC */
#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h"
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
#include "NR_TAG.h"
#include <openair3/UICC/usim_interface.h>
@@ -111,15 +112,16 @@ typedef struct {
} NR_list_t;
typedef enum {
RA_IDLE = 0,
Msg2 = 1,
WAIT_Msg3 = 2,
Msg3_retransmission = 3,
Msg3_dcch_dtch = 4,
Msg4 = 5,
WAIT_Msg4_ACK = 6
nrRA_gNB_IDLE = 0,
nrRA_Msg2 = 1,
nrRA_WAIT_Msg3 = 2,
nrRA_Msg3_retransmission = 3,
nrRA_Msg3_dcch_dtch = 4,
nrRA_Msg4 = 5,
nrRA_WAIT_Msg4_ACK = 6
} RA_gNB_state_t;
static const char *const nrra_text[] =
{"IDLE", "Msg2", "WAIT_Msg3", "Msg3_retransmission", "Msg3_dcch_dtch", "Msg4", "WAIT_Msg4_ACK"};
typedef struct nr_pdsch_AntennaPorts_t {
int N1;
int N2;
@@ -160,7 +162,7 @@ typedef struct NR_sched_pdcch {
/*! \brief gNB template for the Random access information */
typedef struct {
/// Flag to indicate this process is active
RA_gNB_state_t state;
RA_gNB_state_t ra_state;
/// CORESET0 configured flag
int coreset0_configured;
/// Slot where preamble was received
@@ -174,7 +176,7 @@ typedef struct {
/// Frame where Msg3 is to be sent
frame_t Msg3_frame;
/// Msg3 time domain allocation index
uint8_t Msg3_tda_id;
int Msg3_tda_id;
/// harq_pid used for Msg4 transmission
uint8_t harq_pid;
/// UE RNTI allocated during RAR
@@ -190,25 +192,17 @@ typedef struct {
/// Timeout for RRC connection
int16_t RRC_timer;
/// Msg3 first RB
uint8_t msg3_first_rb;
int msg3_first_rb;
/// Msg3 number of RB
uint8_t msg3_nb_rb;
int msg3_nb_rb;
/// Msg3 BWP start
uint8_t msg3_bwp_start;
int msg3_bwp_start;
/// Msg3 TPC command
uint8_t msg3_TPC;
/// Msg3 ULdelay command
uint8_t msg3_ULdelay;
/// Msg3 cqireq command
uint8_t msg3_cqireq;
/// Round of Msg3 HARQ
uint8_t msg3_round;
int msg3_startsymb;
int msg3_nrsymb;
/// TBS used for Msg4
int msg4_TBsize;
/// MCS used for Msg4
int msg4_mcs;
int msg3_nbSymb;
/// MAC PDU length for Msg4
int mac_pdu_length;
/// RA search space
@@ -233,17 +227,12 @@ typedef struct {
/*! \brief gNB common channels */
typedef struct {
int Ncp;
int nr_band;
frame_type_t frame_type;
uint64_t dl_CarrierFreq;
NR_BCCH_BCH_Message_t *mib;
NR_BCCH_DL_SCH_Message_t *sib1;
NR_ServingCellConfigCommon_t *ServingCellConfigCommon;
/// pre-configured ServingCellConfig that is default for every UE
NR_ServingCellConfig_t *pre_ServingCellConfig;
NR_ARFCN_ValueEUTRA_t ul_CarrierFreq;
long ul_Bandwidth;
/// Outgoing MIB PDU for PHY
uint8_t MIB_pdu[3];
/// Outgoing BCCH pdu for PHY
@@ -256,23 +245,20 @@ typedef struct {
/// VRB map for common channels and PUSCH, dynamically allocated because
/// length depends on number of slots and RBs
uint16_t *vrb_map_UL;
/// number of subframe allocation pattern available for MBSFN sync area
uint8_t num_sf_allocation_pattern;
///Number of active SSBs
uint8_t num_active_ssb;
int num_active_ssb;
//Total available prach occasions per configuration period
uint32_t total_prach_occasions_per_config_period;
int total_prach_occasions_per_config_period;
//Total available prach occasions
uint32_t total_prach_occasions;
int total_prach_occasions;
//Max Association period
uint8_t max_association_period;
int max_association_period;
//SSB index
uint8_t ssb_index[MAX_NUM_OF_SSB];
//CB preambles for each SSB
uint8_t cb_preambles_per_ssb;
int cb_preambles_per_ssb;
} NR_COMMON_channels_t;
// SP ZP CSI-RS Resource Set Activation/Deactivation MAC CE
typedef struct sp_zp_csirs {
bool is_scheduled; //ZP CSI-RS ACT/Deact MAC CE is scheduled
+34 -4
View File
@@ -83,6 +83,24 @@ static void release_rlc_entity_from_lcid(nr_rlc_ue_t *ue, logical_chan_id_t chan
}
}
logical_chan_id_t nr_rlc_get_lcid_from_rb(int ue_id, bool is_srb, int rb_id)
{
nr_rlc_manager_lock(nr_rlc_ue_manager);
nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id);
for (logical_chan_id_t id = 1; id <= 32; id++) {
nr_rlc_rb_t *rb = &ue->lcid2rb[id - 1];
if (is_srb) {
if (rb->type == NR_RLC_SRB && rb->choice.srb_id == rb_id)
return id;
} else {
if (rb->type == NR_RLC_DRB && rb->choice.drb_id == rb_id)
return id;
}
}
LOG_E(RLC, "Couldn't find LCID corresponding to %s %d\n", is_srb ? "SRB" : "DRB", rb_id);
return 0;
}
static nr_rlc_entity_t *get_rlc_entity_from_lcid(nr_rlc_ue_t *ue, logical_chan_id_t channel_id)
{
if (channel_id == 0)
@@ -120,7 +138,7 @@ void nr_rlc_release_entity(int rnti, logical_chan_id_t channel_id)
void mac_rlc_data_ind(const module_id_t module_idP,
const rnti_t rntiP,
const eNB_index_t eNB_index,
const frame_t rameP,
const frame_t frameP,
const eNB_flag_t enb_flagP,
const MBMS_flag_t MBMS_flagP,
const logical_chan_id_t channel_idP,
@@ -631,9 +649,10 @@ void nr_rlc_reestablish_entity(int rnti, int lc_id)
nr_rlc_manager_lock(nr_rlc_ue_manager);
nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti);
if (ue == NULL)
if (ue == NULL) {
LOG_E(RLC, "RLC instance for the given UE was not found \n");
return;
}
nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, lc_id);
if (rb != NULL) {
@@ -644,7 +663,6 @@ void nr_rlc_reestablish_entity(int rnti, int lc_id)
}
nr_rlc_manager_unlock(nr_rlc_ue_manager);
}
void nr_rlc_reconfigure_entity(int rnti, int lc_id, NR_RLC_Config_t *rlc_Config)
{
nr_rlc_manager_lock(nr_rlc_ue_manager);
@@ -703,6 +721,18 @@ void nr_rlc_reconfigure_entity(int rnti, int lc_id, NR_RLC_Config_t *rlc_Config)
AssertFatal(um->ul_UM_RLC.sn_FieldLength == NULL, "Cannot handle different sn_FieldLength for DL and UL\n");
nr_rlc_entity_um_reconfigure(rb, t_reassembly, sn_field_length);
}
} else {
AssertFatal(rb->stats.mode == NR_RLC_AM, "Invalid RLC mode\n");
// default values as in 9.2.1 of 38.331
int sn_field_length = 12;
nr_rlc_entity_am_reconfigure(rb,
45, //t_poll_retransmit
35, //t_reassembly
0, //t_status_prohibit
-1, //poll_pdu
-1, //poll_byte
8, //max_retx_threshold
&sn_field_length);
}
nr_rlc_manager_unlock(nr_rlc_ue_manager);
}
+1
View File
@@ -45,6 +45,7 @@ void nr_rlc_add_srb(int rnti, int srb_id, const NR_RLC_BearerConfig_t *rlc_Beare
void nr_rlc_add_drb(int rnti, int drb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig);
void nr_rlc_reestablish_entity(int rnti, int lc_id);
logical_chan_id_t nr_rlc_get_lcid_from_rb(int ue_id, bool is_srb, int rb_id);
void nr_rlc_remove_ue(int rnti);
bool nr_rlc_update_rnti(int from_rnti, int to_rnti);
+27 -31
View File
@@ -348,13 +348,13 @@ static bool is_my_dci(NR_UE_MAC_INST_t *mac, nfapi_nr_dl_dci_pdu_t *received_pdu
return false;
if (received_pdu->RNTI == 0xFFFF && mac->phy_config_request_sent)
return false;
if (received_pdu->RNTI != mac->crnti && mac->ra.ra_state == RA_SUCCEEDED)
if (received_pdu->RNTI != mac->crnti && mac->ra.ra_state == nrRA_SUCCEEDED)
return false;
if (received_pdu->RNTI != mac->ra.t_crnti && mac->ra.ra_state == WAIT_CONTENTION_RESOLUTION)
if (received_pdu->RNTI != mac->ra.t_crnti && mac->ra.ra_state == nrRA_WAIT_CONTENTION_RESOLUTION)
return false;
if (received_pdu->RNTI != 0x10b && mac->ra.ra_state == WAIT_RAR)
if (received_pdu->RNTI != 0x10b && mac->ra.ra_state == nrRA_WAIT_RAR)
return false;
if (received_pdu->RNTI != 0xFFFF && mac->ra.ra_state <= GENERATE_PREAMBLE)
if (received_pdu->RNTI != 0xFFFF && mac->ra.ra_state <= nrRA_GENERATE_PREAMBLE)
return false;
}
return true;
@@ -477,8 +477,7 @@ static void fill_rx_ind(nfapi_nr_pdu_t *pdu_list, fapi_nr_rx_indication_t *rx_in
pdu += pdu_list->TLVs[j].length;
}
bool ack_nack = true;
if (mac->ra.ra_state >= RA_SUCCEEDED && should_drop_transport_block(rx_ind->slot, mac->crnti))
{
if (mac->ra.ra_state >= nrRA_SUCCEEDED && should_drop_transport_block(rx_ind->slot, mac->crnti)) {
ack_nack = false;
}
rx_ind->rx_indication_body[pdu_idx].pdsch_pdu.ack_nack = ack_nack;
@@ -742,10 +741,8 @@ void check_and_process_dci(nfapi_nr_dl_tti_request_t *dl_tti_request,
int slots_per_frame = 20; //30 kHZ subcarrier spacing
int slot_ahead = 2; // TODO: Make this dynamic
if (is_nr_UL_slot(mac->tdd_UL_DL_ConfigurationCommon,
(slot + slot_ahead) % slots_per_frame,
mac->frame_type)
&& mac->ra.ra_state != RA_SUCCEEDED) {
if (is_nr_UL_slot(mac->tdd_UL_DL_ConfigurationCommon, (slot + slot_ahead) % slots_per_frame, mac->frame_type)
&& mac->ra.ra_state != nrRA_SUCCEEDED) {
// If we filled dl_info AFTER we got the slot indication, we want to check if we should fill tx_req:
nr_uplink_indication_t ul_info = {.slot = (slot + slot_ahead) % slots_per_frame,
.frame = slot + slot_ahead >= slots_per_frame ? (frame + 1) % 1024 : frame};
@@ -873,25 +870,22 @@ static void enqueue_nr_nfapi_msg(void *buffer, ssize_t len, nfapi_p7_message_hea
NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE. If we have not yet completed the CBRA/
CFRA procedure, we need to queue all UL_TTI_REQs. */
for (int i = 0; i < ul_tti_request->n_pdus; i++) {
if (ul_tti_request->pdus_list[i].pdu_type == NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE &&
mac->ra.ra_state >= RA_SUCCEEDED) {
if (!put_queue(&nr_ul_tti_req_queue, ul_tti_request))
{
LOG_D(NR_PHY, "put_queue failed for ul_tti_request, calling put_queue_replace.\n");
nfapi_nr_ul_tti_request_t *evicted_ul_tti_req = put_queue_replace(&nr_ul_tti_req_queue, ul_tti_request);
free(evicted_ul_tti_req);
}
break;
if (ul_tti_request->pdus_list[i].pdu_type == NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE
&& mac->ra.ra_state >= nrRA_SUCCEEDED) {
if (!put_queue(&nr_ul_tti_req_queue, ul_tti_request)) {
LOG_D(NR_PHY, "put_queue failed for ul_tti_request, calling put_queue_replace.\n");
nfapi_nr_ul_tti_request_t *evicted_ul_tti_req = put_queue_replace(&nr_ul_tti_req_queue, ul_tti_request);
free(evicted_ul_tti_req);
}
else if (mac->ra.ra_state < RA_SUCCEEDED) {
if (!put_queue(&nr_ul_tti_req_queue, ul_tti_request))
{
LOG_D(NR_PHY, "put_queue failed for ul_tti_request, calling put_queue_replace.\n");
nfapi_nr_ul_tti_request_t *evicted_ul_tti_req = put_queue_replace(&nr_ul_tti_req_queue, ul_tti_request);
free(evicted_ul_tti_req);
}
break;
break;
} else if (mac->ra.ra_state < nrRA_SUCCEEDED) {
if (!put_queue(&nr_ul_tti_req_queue, ul_tti_request)) {
LOG_D(NR_PHY, "put_queue failed for ul_tti_request, calling put_queue_replace.\n");
nfapi_nr_ul_tti_request_t *evicted_ul_tti_req = put_queue_replace(&nr_ul_tti_req_queue, ul_tti_request);
free(evicted_ul_tti_req);
}
break;
}
}
break;
}
@@ -922,8 +916,7 @@ static void save_pdsch_pdu_for_crnti(nfapi_nr_dl_tti_request_t *dl_tti_request)
if (pdu_list->PDUType == NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE)
{
const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu = &pdu_list->pdsch_pdu.pdsch_pdu_rel15;
if (pdsch_pdu->rnti == mac->crnti && mac->ra.ra_state == RA_SUCCEEDED)
{
if (pdsch_pdu->rnti == mac->crnti && mac->ra.ra_state == nrRA_SUCCEEDED) {
read_channel_param(pdsch_pdu, dl_tti_request->Slot, count_sent);
count_sent++;
LOG_T(NR_MAC, "pdsch_pdu->rnti %x mac->crnti %x mac->ra.ra_state %d count_sent %d\n",
@@ -1039,6 +1032,7 @@ static int handle_bcch_bch(NR_UE_MAC_INST_t *mac,
uint32_t ssb_index,
uint32_t ssb_length,
uint16_t ssb_start_subcarrier,
long ssb_arfcn,
uint16_t cell_id)
{
mac->mib_ssb = ssb_index;
@@ -1048,7 +1042,8 @@ static int handle_bcch_bch(NR_UE_MAC_INST_t *mac,
mac->frequency_range = FR2;
else
mac->frequency_range = FR1;
nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, NR_BCCH_BCH, (uint8_t *) pduP, 3); // fixed 3 bytes MIB PDU
// fixed 3 bytes MIB PDU
nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, cell_id, ssb_arfcn, NR_BCCH_BCH, (uint8_t *) pduP, 3);
return 0;
}
@@ -1124,7 +1119,7 @@ void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, uint8_t ack_nac
if (current_harq->active) {
LOG_D(PHY,"Updating harq_status for harq_id %d, ack/nak %d\n", harq_pid, current_harq->ack);
// we can prepare feedback for MSG4 in advance
if (mac->ra.ra_state == WAIT_CONTENTION_RESOLUTION)
if (mac->ra.ra_state == nrRA_WAIT_CONTENTION_RESOLUTION)
prepare_msg4_feedback(mac, harq_pid, ack_nack);
else {
current_harq->ack = ack_nack;
@@ -1227,6 +1222,7 @@ static uint32_t nr_ue_dl_processing(nr_downlink_indication_t *dl_info)
rx_indication_body.ssb_pdu.ssb_index,
rx_indication_body.ssb_pdu.ssb_length,
rx_indication_body.ssb_pdu.ssb_start_subcarrier,
rx_indication_body.ssb_pdu.arfcn,
rx_indication_body.ssb_pdu.cell_id)) << FAPI_NR_RX_PDU_TYPE_SSB;
}
break;
@@ -121,8 +121,7 @@ bool should_drop_transport_block(int slot, uint16_t rnti)
/* We want to avoid dropping setup messages because this would be pathological. */
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
if (mac->ra.ra_state < RA_SUCCEEDED)
{
if (mac->ra.ra_state < nrRA_SUCCEEDED) {
LOG_D(NR_MAC, "Not dropping because MAC state: %d", mac->ra.ra_state);
return false;
}
+8 -5
View File
@@ -979,7 +979,10 @@ uint8_t do_NR_ULInformationTransfer(uint8_t **buffer, uint32_t pdu_length, uint8
return encoded;
}
uint8_t do_RRCReestablishmentRequest(uint8_t *buffer, uint16_t c_rnti)
uint8_t do_RRCReestablishmentRequest(uint8_t *buffer,
NR_ReestablishmentCause_t cause,
uint32_t cell_id,
uint16_t c_rnti)
{
asn_enc_rval_t enc_rval;
NR_UL_CCCH_Message_t ul_ccch_msg;
@@ -994,16 +997,16 @@ uint8_t do_RRCReestablishmentRequest(uint8_t *buffer, uint16_t c_rnti)
rrcReestablishmentRequest = ul_ccch_msg.message.choice.c1->choice.rrcReestablishmentRequest;
// test
rrcReestablishmentRequest->rrcReestablishmentRequest.reestablishmentCause = NR_ReestablishmentCause_reconfigurationFailure;
rrcReestablishmentRequest->rrcReestablishmentRequest.reestablishmentCause = cause;
rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.c_RNTI = c_rnti;
rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.physCellId = 0;
rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.physCellId = cell_id;
// TODO properly setting shortMAC-I (see 5.3.7.4 of 331)
rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.shortMAC_I.buf = buf;
rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.shortMAC_I.buf[0] = 0x08;
rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.shortMAC_I.buf[1] = 0x32;
rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.shortMAC_I.size = 2;
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
xer_fprint(stdout, &asn_DEF_NR_UL_CCCH_Message, (void *)&ul_ccch_msg);
}
+4 -1
View File
@@ -131,7 +131,10 @@ uint8_t do_NR_ULInformationTransfer(uint8_t **buffer,
uint32_t pdu_length,
uint8_t *pdu_buffer);
uint8_t do_RRCReestablishmentRequest(uint8_t *buffer, uint16_t c_rnti);
uint8_t do_RRCReestablishmentRequest(uint8_t *buffer,
NR_ReestablishmentCause_t cause,
uint32_t cell_id,
uint16_t c_rnti);
int do_RRCReestablishment(rrc_gNB_ue_context_t *const ue_context_pP,
uint8_t *const buffer,
-8
View File
@@ -1160,14 +1160,6 @@ static void rrc_handle_RRCSetupRequest(gNB_RRC_INST *rrc,
rrcSetupRequest->ue_Identity.choice.randomValue.buf,
rrcSetupRequest->ue_Identity.choice.randomValue.size);
/* if there is already a registered UE (with another RNTI) with this random_value,
* the current one must be removed from MAC/PHY (zombie UE)
*/
if ((ue_context_p = rrc_gNB_ue_context_random_exist(rrc, random_value))) {
LOG_W(NR_RRC, "new UE rnti (coming with random value) is already there, removing UE %x from MAC/PHY\n", msg->crnti);
AssertFatal(false, "not implemented\n");
}
ue_context_p = rrc_gNB_create_ue_context(assoc_id, msg->crnti, rrc, random_value, msg->gNB_DU_ue_id);
} else if (NR_InitialUE_Identity_PR_ng_5G_S_TMSI_Part1 == rrcSetupRequest->ue_Identity.present) {
/* <5G-S-TMSI> = <AMF Set ID><AMF Pointer><5G-TMSI> 48-bit */
+6 -1
View File
@@ -54,6 +54,8 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
const frame_t frame,
const int slot,
const rnti_t rnti,
const uint32_t cellid,
const long arfcn,
const channel_t channel,
const uint8_t* pduP,
const sdu_size_t pdu_len)
@@ -84,6 +86,8 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
NR_RRC_MAC_BCCH_DATA_IND (message_p).slot = slot;
NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu_size = sdu_size;
NR_RRC_MAC_BCCH_DATA_IND (message_p).gnb_index = gNB_index;
NR_RRC_MAC_BCCH_DATA_IND (message_p).phycellid = cellid;
NR_RRC_MAC_BCCH_DATA_IND (message_p).ssb_arfcn = arfcn;
NR_RRC_MAC_BCCH_DATA_IND (message_p).is_bch = (channel == NR_BCCH_BCH);
itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(module_id), message_p);
}
@@ -122,10 +126,11 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
return(0);
}
void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti)
void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, int gnb_id)
{
MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_MSG3_IND);
NR_RRC_MAC_MSG3_IND (message_p).rnti = rnti;
NR_RRC_MAC_MSG3_IND (message_p).gnb_id = gnb_id;
itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(mod_id), message_p);
}
+434 -113
View File
@@ -139,7 +139,7 @@ static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc,
static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc,
NR_RadioBearerConfig_t *const radioBearerConfig);
static void nr_rrc_ue_generate_rrcReestablishmentComplete(NR_RRCReestablishment_t *rrcReestablishment);
static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc, const NR_RRCReestablishment_t *rrcReestablishment);
static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_len);
static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc,
int gNB_index,
@@ -150,7 +150,19 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc,
OCTET_STRING_t *masterCellGroup,
long *fullConfig);
void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig);
static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig, NR_UE_Timers_Constants_t *timers);
static NR_RB_status_t get_DRB_status(const NR_UE_RRC_INST_t *rrc, NR_DRB_Identity_t drb_id)
{
AssertFatal(drb_id > 0 && drb_id < 33, "Invalid DRB ID %ld\n", drb_id);
return rrc->status_DRBs[drb_id - 1];
}
static void set_DRB_status(NR_UE_RRC_INST_t *rrc, NR_DRB_Identity_t drb_id, NR_RB_status_t status)
{
AssertFatal(drb_id > 0 && drb_id < 33, "Invalid DRB ID %ld\n", drb_id);
rrc->status_DRBs[drb_id - 1] = status;
}
static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc,
int gNB_index,
@@ -218,8 +230,7 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc,
}
if (ie->measConfig != NULL) {
LOG_I(NR_RRC, "Measurement Configuration is present\n");
// if some element need to be updated
nr_rrc_ue_process_measConfig(rrcNB, ie->measConfig);
nr_rrc_ue_process_measConfig(rrcNB, ie->measConfig, &rrc->timers_and_constants);
}
if (ie->lateNonCriticalExtension != NULL) {
// unuse now
@@ -296,11 +307,10 @@ NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int nb_inst)
rrc->ue_id = nr_ue;
// fill UE-NR-Capability @ UE-CapabilityRAT-Container here.
rrc->selected_plmn_identity = 1;
rrc->ra_trigger = RA_NOT_RUNNING;
rrc->dl_bwp_id = 0;
rrc->ul_bwp_id = 0;
rrc->as_security_activated = false;
rrc->ra_trigger = RA_NOT_RUNNING;
FILE *f = NULL;
if (uecap_file)
@@ -323,8 +333,8 @@ NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int nb_inst)
for (int j = 0; j < NR_NUM_SRB; j++)
rrc->Srb[j] = RB_NOT_PRESENT;
for (int j = 0; j < MAX_DRBS_PER_UE; j++)
rrc->status_DRBs[j] = RB_NOT_PRESENT;
for (int j = 1; j <= MAX_DRBS_PER_UE; j++)
set_DRB_status(rrc, j, RB_NOT_PRESENT);
// SRB0 activated by default
rrc->Srb[0] = RB_ESTABLISHED;
for (int j = 0; j < NR_MAX_NUM_LCID; j++)
@@ -348,42 +358,55 @@ bool check_si_validity(NR_UE_RRC_SI_INFO *SI_info, int si_type)
case NR_SIB_TypeInfo__type_sibType2:
if (!SI_info->sib2)
return false;
break;
case NR_SIB_TypeInfo__type_sibType3:
if (!SI_info->sib3)
return false;
break;
case NR_SIB_TypeInfo__type_sibType4:
if (!SI_info->sib4)
return false;
break;
case NR_SIB_TypeInfo__type_sibType5:
if (!SI_info->sib5)
return false;
break;
case NR_SIB_TypeInfo__type_sibType6:
if (!SI_info->sib6)
return false;
break;
case NR_SIB_TypeInfo__type_sibType7:
if (!SI_info->sib7)
return false;
break;
case NR_SIB_TypeInfo__type_sibType8:
if (!SI_info->sib8)
return false;
break;
case NR_SIB_TypeInfo__type_sibType9:
if (!SI_info->sib9)
return false;
break;
case NR_SIB_TypeInfo__type_sibType10_v1610:
if (!SI_info->sib10)
return false;
break;
case NR_SIB_TypeInfo__type_sibType11_v1610:
if (!SI_info->sib11)
return false;
break;
case NR_SIB_TypeInfo__type_sibType12_v1610:
if (!SI_info->sib12)
return false;
break;
case NR_SIB_TypeInfo__type_sibType13_v1610:
if (!SI_info->sib13)
return false;
break;
case NR_SIB_TypeInfo__type_sibType14_v1610:
if (!SI_info->sib14)
return false;
break;
default :
AssertFatal(false, "Invalid SIB type %d\n", si_type);
}
@@ -417,10 +440,14 @@ int check_si_status(NR_UE_RRC_SI_INFO *SI_info)
/*brief decode BCCH-BCH (MIB) message*/
static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc,
const uint8_t gNB_index,
const uint32_t phycellid,
const long ssb_arfcn,
uint8_t *const bufferP,
const uint8_t buffer_len)
{
NR_BCCH_BCH_Message_t *bcch_message = NULL;
rrc->phyCellID = phycellid;
rrc->arfcn_ssb = ssb_arfcn;
asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
&asn_DEF_NR_BCCH_BCH_Message,
@@ -433,6 +460,28 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc,
return;
}
// Actions following cell selection while T311 is running
NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
if (is_nr_timer_active(timers->T311)) {
nr_timer_stop(&timers->T311);
rrc->ra_trigger = RRC_CONNECTION_REESTABLISHMENT;
// preparing MSG3 for re-establishment in advance
uint8_t buffer[1024];
int buf_size = do_RRCReestablishmentRequest(buffer,
rrc->reestablishment_cause,
rrc->phyCellID,
rrc->rnti); // old rnti
nr_rlc_srb_recv_sdu(rrc->ue_id, 0, buffer, buf_size);
// apply the default MAC Cell Group configuration
// (done at MAC by calling nr_ue_mac_default_configs)
// apply the timeAlignmentTimerCommon included in SIB1
// not used
}
int get_sib = 0;
if (get_softmodem_params()->sa &&
bcch_message->message.choice.mib->cellBarred == NR_MIB__cellBarred_notBarred &&
@@ -565,16 +614,29 @@ static int nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si)
static void nr_rrc_handle_msg3_indication(NR_UE_RRC_INST_t *rrc, rnti_t rnti)
{
NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants;
switch (rrc->ra_trigger) {
case INITIAL_ACCESS_FROM_RRC_IDLE:
// After SIB1 is received, prepare RRCConnectionRequest
rrc->rnti = rnti;
// start timer T300
NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants;
nr_timer_start(&tac->T300);
break;
case RRC_CONNECTION_REESTABLISHMENT:
AssertFatal(1==0, "ra_trigger not implemented yet!\n");
rrc->rnti = rnti;
nr_timer_start(&tac->T301);
int srb_id = 1;
// re-establish PDCP for SRB1
nr_pdcp_reestablishment(rrc->ue_id, srb_id, true);
// re-establish RLC for SRB1
int lc_id = nr_rlc_get_lcid_from_rb(rrc->ue_id, true, 1);
nr_rlc_reestablish_entity(rrc->ue_id, lc_id);
// apply the specified configuration defined in 9.2.1 for SRB1
nr_rlc_reconfigure_entity(rrc->ue_id, lc_id, NULL);
// suspend integrity protection and ciphering for SRB1
nr_pdcp_config_set_security(rrc->ue_id, srb_id, 0, NULL, NULL, NULL);
// resume SRB1
rrc->Srb[srb_id] = RB_ESTABLISHED;
break;
case DURING_HANDOVER:
AssertFatal(1==0, "ra_trigger not implemented yet!\n");
@@ -725,7 +787,8 @@ static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc,
if (rrc->active_RLC_entity[lcid]) {
if (rlc_bearer->reestablishRLC)
nr_rlc_reestablish_entity(rrc->ue_id, lcid);
nr_rlc_reconfigure_entity(rrc->ue_id, lcid, rlc_bearer->rlc_Config);
if (rlc_bearer->rlc_Config)
nr_rlc_reconfigure_entity(rrc->ue_id, lcid, rlc_bearer->rlc_Config);
} else {
rrc->active_RLC_entity[lcid] = true;
AssertFatal(rlc_bearer->servedRadioBearer, "servedRadioBearer mandatory in case of setup\n");
@@ -751,6 +814,11 @@ void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t
if(spCellConfig != NULL) {
if (spCellConfig->reconfigurationWithSync != NULL) {
NR_ReconfigurationWithSync_t *reconfigurationWithSync = spCellConfig->reconfigurationWithSync;
if (reconfigurationWithSync->spCellConfigCommon &&
reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon &&
reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon->frequencyInfoDL &&
reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB)
rrc->arfcn_ssb = *reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB;
// perform Reconfiguration with sync according to 5.3.5.5.2
if (!rrc->as_security_activated && rrc->nrRrcState != RRC_STATE_IDLE_NR) {
// perform the actions upon going to RRC_IDLE as specified in 5.3.11
@@ -767,9 +835,9 @@ void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t
if (rrc->Srb[i] == RB_SUSPENDED)
rrc->Srb[i] = RB_ESTABLISHED;
}
for (int i = 0; i < MAX_DRBS_PER_UE; i++) {
if (rrc->status_DRBs[i] == RB_SUSPENDED)
rrc->status_DRBs[i] = RB_ESTABLISHED;
for (int i = 1; i <= MAX_DRBS_PER_UE; i++) {
if (get_DRB_status(rrc, i) == RB_SUSPENDED)
set_DRB_status(rrc, i, RB_ESTABLISHED);
}
// TODO reset MAC
}
@@ -848,6 +916,11 @@ static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc,
// if the RRCSetup is received in response to an RRCReestablishmentRequest
// or RRCResumeRequest or RRCResumeRequest1
// TODO none of the procedures implemented yet
if (rrc->ra_trigger == RRC_CONNECTION_REESTABLISHMENT) {
LOG_E(NR_RRC, "Handling of RRCSetup in response of RRCReestablishment not implemented yet. Going back to IDLE.\n");
nr_rrc_going_to_IDLE(rrc, OTHER, NULL);
return;
}
// perform the cell group configuration procedure in accordance with the received masterCellGroup
nr_rrc_ue_process_masterCellGroup(rrc,
@@ -1046,109 +1119,249 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc,
securityModeCommand->criticalExtensions.present);
}
//-----------------------------------------------------------------------------
void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig)
//-----------------------------------------------------------------------------
static void handle_meas_reporting_remove(rrcPerNB_t *rrc, int id, NR_UE_Timers_Constants_t *timers)
{
int i;
long ind;
NR_MeasObjectToAddMod_t *measObj = NULL;
NR_ReportConfigToAddMod_t *reportConfig = NULL;
// remove the measurement reporting entry for this measId if included
asn1cFreeStruc(asn_DEF_NR_VarMeasReport, rrc->MeasReport[id]);
// TODO stop the periodical reporting timer or timer T321, whichever is running,
// and reset the associated information (e.g. timeToTrigger) for this measId
nr_timer_stop(&timers->T321);
}
if (measConfig->measObjectToRemoveList != NULL) {
for (i = 0; i < measConfig->measObjectToRemoveList->list.count; i++) {
ind = *measConfig->measObjectToRemoveList->list.array[i];
free(rrc->MeasObj[ind - 1]);
}
}
if (measConfig->measObjectToAddModList != NULL) {
LOG_I(NR_RRC, "Measurement Object List is present\n");
for (i = 0; i < measConfig->measObjectToAddModList->list.count; i++) {
measObj = measConfig->measObjectToAddModList->list.array[i];
ind = measConfig->measObjectToAddModList->list.array[i]->measObjectId;
if (rrc->MeasObj[ind - 1]) {
LOG_D(NR_RRC, "Modifying measurement object %ld\n", ind);
memcpy(rrc->MeasObj[ind - 1], (char *)measObj, sizeof(NR_MeasObjectToAddMod_t));
} else {
LOG_I(NR_RRC, "Adding measurement object %ld\n", ind);
if (measObj->measObject.present == NR_MeasObjectToAddMod__measObject_PR_measObjectNR) {
rrc->MeasObj[ind - 1] = measObj;
}
}
}
LOG_I(NR_RRC, "call rrc_mac_config_req \n");
// rrc_mac_config_req_ue
}
if (measConfig->reportConfigToRemoveList != NULL) {
for (i = 0; i < measConfig->reportConfigToRemoveList->list.count; i++) {
ind = *measConfig->reportConfigToRemoveList->list.array[i];
free(rrc->ReportConfig[ind - 1]);
}
}
if (measConfig->reportConfigToAddModList != NULL) {
LOG_I(NR_RRC, "Report Configuration List is present\n");
for (i = 0; i < measConfig->reportConfigToAddModList->list.count; i++) {
ind = measConfig->reportConfigToAddModList->list.array[i]->reportConfigId;
reportConfig = measConfig->reportConfigToAddModList->list.array[i];
if (rrc->ReportConfig[ind - 1]) {
LOG_I(NR_RRC, "Modifying Report Configuration %ld\n", ind - 1);
memcpy(rrc->ReportConfig[ind - 1],
(char *)measConfig->reportConfigToAddModList->list.array[i],
sizeof(NR_ReportConfigToAddMod_t));
} else {
LOG_D(NR_RRC, "Adding Report Configuration %ld %p \n", ind - 1, measConfig->reportConfigToAddModList->list.array[i]);
if (reportConfig->reportConfig.present == NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR) {
rrc->ReportConfig[ind - 1] = measConfig->reportConfigToAddModList->list.array[i];
static void handle_measobj_remove(rrcPerNB_t *rrc, struct NR_MeasObjectToRemoveList *remove_list, NR_UE_Timers_Constants_t *timers)
{
// section 5.5.2.4 in 38.331
for (int i = 0; i < remove_list->list.count; i++) {
// for each measObjectId included in the received measObjectToRemoveList
// that is part of measObjectList in the configuration
NR_MeasObjectId_t id = *remove_list->list.array[i];
if (rrc->MeasObj[id - 1]) {
// remove the entry with the matching measObjectId from the measObjectList
asn1cFreeStruc(asn_DEF_NR_MeasObjectToAddMod, rrc->MeasObj[id - 1]);
// remove all measId associated with this measObjectId from the measIdList
for (int j = 0; j < MAX_MEAS_ID; j++) {
if (rrc->MeasId[j] && rrc->MeasId[j]->measObjectId == id) {
asn1cFreeStruc(asn_DEF_NR_MeasIdToAddMod, rrc->MeasId[j]);
handle_meas_reporting_remove(rrc, j, timers);
}
}
}
}
}
if (measConfig->measIdToRemoveList != NULL) {
for (i = 0; i < measConfig->measIdToRemoveList->list.count; i++) {
ind = *measConfig->measIdToRemoveList->list.array[i];
free(rrc->MeasId[ind - 1]);
static void update_ssb_configmob(NR_SSB_ConfigMobility_t *source, NR_SSB_ConfigMobility_t *target)
{
if (source->ssb_ToMeasure)
HANDLE_SETUPRELEASE_IE(target->ssb_ToMeasure, source->ssb_ToMeasure, NR_SSB_ToMeasure_t, asn_DEF_NR_SSB_ToMeasure);
target->deriveSSB_IndexFromCell = source->deriveSSB_IndexFromCell;
if (source->ss_RSSI_Measurement)
UPDATE_IE(target->ss_RSSI_Measurement, source->ss_RSSI_Measurement, NR_SS_RSSI_Measurement_t);
}
static void update_nr_measobj(NR_MeasObjectNR_t *source, NR_MeasObjectNR_t *target)
{
UPDATE_IE(target->ssbFrequency, source->ssbFrequency, NR_ARFCN_ValueNR_t);
UPDATE_IE(target->ssbSubcarrierSpacing, source->ssbSubcarrierSpacing, NR_SubcarrierSpacing_t);
UPDATE_IE(target->smtc1, source->smtc1, NR_SSB_MTC_t);
if (source->smtc2) {
target->smtc2->periodicity = source->smtc2->periodicity;
if (source->smtc2->pci_List)
UPDATE_IE(target->smtc2->pci_List, source->smtc2->pci_List, struct NR_SSB_MTC2__pci_List);
}
else
asn1cFreeStruc(asn_DEF_NR_SSB_MTC2, target->smtc2);
UPDATE_IE(target->refFreqCSI_RS, source->refFreqCSI_RS, NR_ARFCN_ValueNR_t);
if (source->referenceSignalConfig.ssb_ConfigMobility)
update_ssb_configmob(source->referenceSignalConfig.ssb_ConfigMobility, target->referenceSignalConfig.ssb_ConfigMobility);
UPDATE_IE(target->absThreshSS_BlocksConsolidation, source->absThreshSS_BlocksConsolidation, NR_ThresholdNR_t);
UPDATE_IE(target->absThreshCSI_RS_Consolidation, source->absThreshCSI_RS_Consolidation, NR_ThresholdNR_t);
UPDATE_IE(target->nrofSS_BlocksToAverage, source->nrofSS_BlocksToAverage, long);
UPDATE_IE(target->nrofCSI_RS_ResourcesToAverage, source->nrofCSI_RS_ResourcesToAverage, long);
target->quantityConfigIndex = source->quantityConfigIndex;
target->offsetMO = source->offsetMO;
if (source->cellsToRemoveList) {
RELEASE_IE_FROMLIST(source->cellsToRemoveList, target->cellsToAddModList, physCellId);
}
if (source->cellsToAddModList) {
if (!target->cellsToAddModList)
target->cellsToAddModList = calloc(1, sizeof(*target->cellsToAddModList));
ADDMOD_IE_FROMLIST(source->cellsToAddModList, target->cellsToAddModList, physCellId, NR_CellsToAddMod_t);
}
if (source->excludedCellsToRemoveList) {
RELEASE_IE_FROMLIST(source->excludedCellsToRemoveList, target->excludedCellsToAddModList, pci_RangeIndex);
}
if (source->excludedCellsToAddModList) {
if (!target->excludedCellsToAddModList)
target->excludedCellsToAddModList = calloc(1, sizeof(*target->excludedCellsToAddModList));
ADDMOD_IE_FROMLIST(source->excludedCellsToAddModList, target->excludedCellsToAddModList, pci_RangeIndex, NR_PCI_RangeElement_t);
}
if (source->allowedCellsToRemoveList) {
RELEASE_IE_FROMLIST(source->allowedCellsToRemoveList, target->allowedCellsToAddModList, pci_RangeIndex);
}
if (source->allowedCellsToAddModList) {
if (!target->allowedCellsToAddModList)
target->allowedCellsToAddModList = calloc(1, sizeof(*target->allowedCellsToAddModList));
ADDMOD_IE_FROMLIST(source->allowedCellsToAddModList, target->allowedCellsToAddModList, pci_RangeIndex, NR_PCI_RangeElement_t);
}
if (source->ext1) {
UPDATE_IE(target->ext1->freqBandIndicatorNR, source->ext1->freqBandIndicatorNR, NR_FreqBandIndicatorNR_t);
UPDATE_IE(target->ext1->measCycleSCell, source->ext1->measCycleSCell, long);
}
}
static void handle_measobj_addmod(rrcPerNB_t *rrc, struct NR_MeasObjectToAddModList *addmod_list)
{
// section 5.5.2.5 in 38.331
for (int i = 0; i < addmod_list->list.count; i++) {
NR_MeasObjectToAddMod_t *measObj = addmod_list->list.array[i];
if (measObj->measObject.present != NR_MeasObjectToAddMod__measObject_PR_measObjectNR) {
LOG_E(NR_RRC, "Cannot handle MeasObjt other than NR\n");
continue;
}
NR_MeasObjectId_t id = measObj->measObjectId;
if (rrc->MeasObj[id]) {
update_nr_measobj(measObj->measObject.choice.measObjectNR, rrc->MeasObj[id]->measObject.choice.measObjectNR);
}
else {
// add a new entry for the received measObject to the measObjectList
UPDATE_IE(rrc->MeasObj[id], addmod_list->list.array[i], NR_MeasObjectToAddMod_t);
}
}
}
if (measConfig->measIdToAddModList != NULL) {
for (i = 0; i < measConfig->measIdToAddModList->list.count; i++) {
ind = measConfig->measIdToAddModList->list.array[i]->measId;
if (rrc->MeasId[ind - 1]) {
LOG_D(NR_RRC, "Modifying Measurement ID %ld\n", ind - 1);
memcpy(rrc->MeasId[ind - 1], (char *)measConfig->measIdToAddModList->list.array[i], sizeof(NR_MeasIdToAddMod_t));
} else {
LOG_D(NR_RRC, "Adding Measurement ID %ld %p\n", ind - 1, measConfig->measIdToAddModList->list.array[i]);
rrc->MeasId[ind - 1] = measConfig->measIdToAddModList->list.array[i];
static void handle_reportconfig_remove(rrcPerNB_t *rrc,
struct NR_ReportConfigToRemoveList *remove_list,
NR_UE_Timers_Constants_t *timers)
{
for (int i = 0; i < remove_list->list.count; i++) {
NR_ReportConfigId_t id = *remove_list->list.array[i];
// remove the entry with the matching reportConfigId from the reportConfigList
asn1cFreeStruc(asn_DEF_NR_ReportConfigToAddMod, rrc->ReportConfig[id]);
for (int j = 0; j < MAX_MEAS_ID; j++) {
if (rrc->MeasId[j] && rrc->MeasId[j]->reportConfigId == id) {
// remove all measId associated with the reportConfigId from the measIdList
asn1cFreeStruc(asn_DEF_NR_MeasIdToAddMod, rrc->MeasId[j]);
handle_meas_reporting_remove(rrc, j, timers);
}
}
}
}
if (measConfig->quantityConfig != NULL) {
if (rrc->QuantityConfig) {
LOG_D(NR_RRC, "Modifying Quantity Configuration \n");
memcpy(rrc->QuantityConfig, (char *)measConfig->quantityConfig, sizeof(NR_QuantityConfig_t));
} else {
LOG_D(NR_RRC, "Adding Quantity configuration\n");
rrc->QuantityConfig = measConfig->quantityConfig;
static void handle_reportconfig_addmod(rrcPerNB_t *rrc,
struct NR_ReportConfigToAddModList *addmod_list,
NR_UE_Timers_Constants_t *timers)
{
for (int i = 0; i < addmod_list->list.count; i++) {
NR_ReportConfigToAddMod_t *rep = addmod_list->list.array[i];
if (rep->reportConfig.present != NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR) {
LOG_E(NR_RRC, "Cannot handle reportConfig type other than NR\n");
continue;
}
NR_ReportConfigId_t id = rep->reportConfigId;
if (rrc->ReportConfig[id]) {
for (int j = 0; j < MAX_MEAS_ID; j++) {
// for each measId associated with this reportConfigId included in the measIdList
if (rrc->MeasId[j] && rrc->MeasId[j]->reportConfigId == id)
handle_meas_reporting_remove(rrc, j, timers);
}
}
UPDATE_IE(rrc->ReportConfig[id], addmod_list->list.array[i], NR_ReportConfigToAddMod_t);
}
}
static void handle_quantityconfig(rrcPerNB_t *rrc, NR_QuantityConfig_t *quantityConfig, NR_UE_Timers_Constants_t *timers)
{
if (quantityConfig->quantityConfigNR_List) {
for (int i = 0; i < quantityConfig->quantityConfigNR_List->list.count; i++) {
NR_QuantityConfigNR_t *quantityNR = quantityConfig->quantityConfigNR_List->list.array[i];
if (!rrc->QuantityConfig[i])
rrc->QuantityConfig[i] = calloc(1, sizeof(*rrc->QuantityConfig[i]));
rrc->QuantityConfig[i]->quantityConfigCell = quantityNR->quantityConfigCell;
if (quantityNR->quantityConfigRS_Index)
UPDATE_IE(rrc->QuantityConfig[i]->quantityConfigRS_Index, quantityNR->quantityConfigRS_Index, struct NR_QuantityConfigRS);
}
}
for (int j = 0; j < MAX_MEAS_ID; j++) {
// for each measId included in the measIdList
if (rrc->MeasId[j])
handle_meas_reporting_remove(rrc, j, timers);
}
}
if (measConfig->measGapConfig != NULL) {
if (rrc->measGapConfig) {
memcpy(rrc->measGapConfig, (char *)measConfig->measGapConfig, sizeof(NR_MeasGapConfig_t));
} else {
rrc->measGapConfig = measConfig->measGapConfig;
static void handle_measid_remove(rrcPerNB_t *rrc, struct NR_MeasIdToRemoveList *remove_list, NR_UE_Timers_Constants_t *timers)
{
for (int i = 0; i < remove_list->list.count; i++) {
NR_MeasId_t id = *remove_list->list.array[i];
if (rrc->MeasId[id]) {
asn1cFreeStruc(asn_DEF_NR_MeasIdToAddMod, rrc->MeasId[id]);
handle_meas_reporting_remove(rrc, id, timers);
}
}
}
static void handle_measid_addmod(rrcPerNB_t *rrc, struct NR_MeasIdToAddModList *addmod_list, NR_UE_Timers_Constants_t *timers)
{
for (int i = 0; i < addmod_list->list.count; i++) {
NR_MeasId_t id = addmod_list->list.array[i]->measId;
NR_ReportConfigId_t reportId = addmod_list->list.array[i]->reportConfigId;
NR_MeasObjectId_t measObjectId = addmod_list->list.array[i]->measObjectId;
UPDATE_IE(rrc->MeasId[id], addmod_list->list.array[i], NR_MeasIdToAddMod_t);
handle_meas_reporting_remove(rrc, id, timers);
if (rrc->ReportConfig[reportId]) {
NR_ReportConfigToAddMod_t *report = rrc->ReportConfig[reportId];
AssertFatal(report->reportConfig.present == NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR,
"Only NR config report is supported\n");
NR_ReportConfigNR_t *reportNR = report->reportConfig.choice.reportConfigNR;
// if the reportType is set to reportCGI in the reportConfig associated with this measId
if (reportNR->reportType.present == NR_ReportConfigNR__reportType_PR_reportCGI) {
if (rrc->MeasObj[measObjectId]) {
if (rrc->MeasObj[measObjectId]->measObject.present == NR_MeasObjectToAddMod__measObject_PR_measObjectNR) {
NR_MeasObjectNR_t *obj_nr = rrc->MeasObj[measObjectId]->measObject.choice.measObjectNR;
NR_ARFCN_ValueNR_t freq = 0;
if (obj_nr->ssbFrequency)
freq = *obj_nr->ssbFrequency;
else if (obj_nr->refFreqCSI_RS)
freq = *obj_nr->refFreqCSI_RS;
AssertFatal(freq > 0, "Invalid ARFCN frequency for this measurement object\n");
if (freq > 2016666)
nr_timer_setup(&timers->T321, 16000, 10); // 16 seconds for FR2
else
nr_timer_setup(&timers->T321, 2000, 10); // 2 seconds for FR1
}
else // EUTRA
nr_timer_setup(&timers->T321, 1000, 10); // 1 second for EUTRA
nr_timer_start(&timers->T321);
}
}
}
}
}
static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig, NR_UE_Timers_Constants_t *timers)
{
if (measConfig->measObjectToRemoveList)
handle_measobj_remove(rrc, measConfig->measObjectToRemoveList, timers);
if (measConfig->measObjectToAddModList)
handle_measobj_addmod(rrc, measConfig->measObjectToAddModList);
if (measConfig->reportConfigToRemoveList)
handle_reportconfig_remove(rrc, measConfig->reportConfigToRemoveList, timers);
if (measConfig->reportConfigToAddModList)
handle_reportconfig_addmod(rrc, measConfig->reportConfigToAddModList, timers);
if (measConfig->quantityConfig)
handle_quantityconfig(rrc, measConfig->quantityConfig, timers);
if (measConfig->measIdToRemoveList)
handle_measid_remove(rrc, measConfig->measIdToRemoveList, timers);
if (measConfig->measIdToAddModList)
handle_measid_addmod(rrc, measConfig->measIdToAddModList, timers);
AssertFatal(!measConfig->measGapConfig, "Measurement gaps not yet supported\n");
AssertFatal(!measConfig->measGapSharingConfig, "Measurement gaps not yet supported\n");
if (measConfig->s_MeasureConfig) {
if (measConfig->s_MeasureConfig->present == NR_MeasConfig__s_MeasureConfig_PR_ssb_RSRP) {
@@ -1169,8 +1382,10 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc,
if (LOG_DEBUGFLAG(DEBUG_ASN1))
xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void *)radioBearerConfig);
if (radioBearerConfig->srb3_ToRelease)
if (radioBearerConfig->srb3_ToRelease) {
nr_pdcp_release_srb(ue_rrc->ue_id, 3);
ue_rrc->Srb[3] = RB_NOT_PRESENT;
}
uint8_t kRRCenc[NR_K_KEY_SIZE] = {0};
uint8_t kRRCint[NR_K_KEY_SIZE] = {0};
@@ -1195,7 +1410,8 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc,
if (radioBearerConfig->srb_ToAddModList != NULL) {
for (int cnt = 0; cnt < radioBearerConfig->srb_ToAddModList->list.count; cnt++) {
struct NR_SRB_ToAddMod *srb = radioBearerConfig->srb_ToAddModList->list.array[cnt];
if (ue_rrc->Srb[srb->srb_Identity] == RB_NOT_PRESENT)
if (ue_rrc->Srb[srb->srb_Identity] == RB_NOT_PRESENT) {
ue_rrc->Srb[srb->srb_Identity] = RB_ESTABLISHED;
add_srb(false,
ue_rrc->ue_id,
radioBearerConfig->srb_ToAddModList->list.array[cnt],
@@ -1203,21 +1419,28 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc,
ue_rrc->integrityProtAlgorithm,
kRRCenc,
kRRCint);
}
else {
AssertFatal(srb->discardOnPDCP == NULL, "discardOnPDCP not yet implemented\n");
AssertFatal(srb->reestablishPDCP == NULL, "reestablishPDCP not yet implemented\n");
if (srb->reestablishPDCP) {
ue_rrc->Srb[srb->srb_Identity] = RB_ESTABLISHED;
nr_pdcp_reestablishment(ue_rrc->ue_id, srb->srb_Identity, true);
// TODO configure the PDCP entity to apply the integrity protection algorithm
// TODO configure the PDCP entity to apply the ciphering algorithm
}
if (srb->pdcp_Config && srb->pdcp_Config->t_Reordering)
nr_pdcp_reconfigure_srb(ue_rrc->ue_id, srb->srb_Identity, *srb->pdcp_Config->t_Reordering);
}
ue_rrc->Srb[srb->srb_Identity] = RB_ESTABLISHED;
}
}
if (radioBearerConfig->drb_ToReleaseList) {
for (int cnt = 0; cnt < radioBearerConfig->drb_ToReleaseList->list.count; cnt++) {
NR_DRB_Identity_t *DRB_id = radioBearerConfig->drb_ToReleaseList->list.array[cnt];
if (DRB_id)
if (DRB_id) {
nr_pdcp_release_drb(ue_rrc->ue_id, *DRB_id);
set_DRB_status(ue_rrc, *DRB_id, RB_NOT_PRESENT);
}
}
}
@@ -1229,9 +1452,13 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc,
for (int cnt = 0; cnt < radioBearerConfig->drb_ToAddModList->list.count; cnt++) {
struct NR_DRB_ToAddMod *drb = radioBearerConfig->drb_ToAddModList->list.array[cnt];
int DRB_id = drb->drb_Identity;
/* DRB is already established and configured */
if (ue_rrc->status_DRBs[DRB_id] == RB_ESTABLISHED) {
AssertFatal(drb->reestablishPDCP == NULL, "reestablishPDCP not yet implemented\n");
if (get_DRB_status(ue_rrc, DRB_id) != RB_NOT_PRESENT) {
if (drb->reestablishPDCP) {
set_DRB_status(ue_rrc, DRB_id, RB_ESTABLISHED);
nr_pdcp_reestablishment(ue_rrc->ue_id, DRB_id, false);
// TODO configure the PDCP entity to apply the integrity protection algorithm
// TODO configure the PDCP entity to apply the ciphering algorithm
}
AssertFatal(drb->recoverPDCP == NULL, "recoverPDCP not yet implemented\n");
/* sdap-Config is included (SA mode) */
NR_SDAP_Config_t *sdap_Config = drb->cnAssociation ? drb->cnAssociation->choice.sdap_Config : NULL;
@@ -1242,7 +1469,7 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc,
if (sdap_Config)
nr_reconfigure_sdap_entity(sdap_Config, ue_rrc->ue_id, sdap_Config->pdu_Session, DRB_id);
} else {
ue_rrc->status_DRBs[DRB_id] = RB_ESTABLISHED;
set_DRB_status(ue_rrc ,DRB_id, RB_ESTABLISHED);
add_drb(false,
ue_rrc->ue_id,
radioBearerConfig->drb_ToAddModList->list.array[cnt],
@@ -1272,6 +1499,56 @@ static void nr_rrc_ue_generate_RRCReconfigurationComplete(NR_UE_RRC_INST_t *rrc,
nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL);
}
static void nr_rrc_ue_process_rrcReestablishment(NR_UE_RRC_INST_t *rrc,
const int gNB_index,
const NR_RRCReestablishment_t *rrcReestablishment)
{
// implementign procedues as described in 38.331 section 5.3.7.5
// stop timer T301
NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
nr_timer_stop(&timers->T301);
// store the nextHopChainingCount value
NR_RRCReestablishment_IEs_t *ies = rrcReestablishment->criticalExtensions.choice.rrcReestablishment;
AssertFatal(ies, "Not expecting RRCReestablishment_IEs to be NULL\n");
// TODO need to understand how to use nextHopChainingCount
// int nh = rrcReestablishment->criticalExtensions.choice.rrcReestablishment->nextHopChainingCount;
// update the K gNB key based on the current K gNB key or the NH, using the stored nextHopChainingCount value
nr_derive_key_ng_ran_star(rrc->phyCellID, rrc->arfcn_ssb, rrc->kgnb, rrc->kgnb);
// derive the K RRCenc and K UPenc keys associated with the previously configured cipheringAlgorithm
// derive the K RRCint and K UPint keys associated with the previously configured integrityProtAlgorithm
uint8_t kRRCenc[16] = {0};
uint8_t kRRCint[16] = {0};
uint8_t kUPenc[16] = {0};
uint8_t kUPint[16] = {0};
nr_derive_key(UP_ENC_ALG, rrc->cipheringAlgorithm, rrc->kgnb, kUPenc);
nr_derive_key(UP_INT_ALG, rrc->integrityProtAlgorithm, rrc->kgnb, kUPint);
nr_derive_key(RRC_ENC_ALG, rrc->cipheringAlgorithm, rrc->kgnb, kRRCenc);
nr_derive_key(RRC_INT_ALG, rrc->integrityProtAlgorithm, rrc->kgnb, kRRCint);
// TODO request lower layers to verify the integrity protection of the RRCReestablishment message
// TODO if the integrity protection check of the RRCReestablishment message fails -> go to IDLE
// configure lower layers to resume integrity protection for SRB1
// configure lower layers to resume ciphering for SRB1
int srb_id = 1;
int security_mode = (rrc->integrityProtAlgorithm << 4)
| rrc->cipheringAlgorithm;
nr_pdcp_config_set_security(rrc->ue_id, srb_id, security_mode, kRRCenc, kRRCint, kUPenc);
// release the measurement gap configuration indicated by the measGapConfig, if configured
rrcPerNB_t *rrcNB = rrc->perNB + gNB_index;
asn1cFreeStruc(asn_DEF_NR_MeasGapConfig, rrcNB->measGapConfig);
// resetting the RA trigger state after receiving MSG4 with RRCReestablishment
rrc->ra_trigger = RA_NOT_RUNNING;
// submit the RRCReestablishmentComplete message to lower layers for transmission
nr_rrc_ue_generate_rrcReestablishmentComplete(rrc, rrcReestablishment);
}
static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc,
const srb_id_t Srb_id,
const uint8_t *const Buffer,
@@ -1327,7 +1604,7 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc,
case NR_DL_DCCH_MessageType__c1_PR_rrcReestablishment:
LOG_I(NR_RRC, "Logical Channel DL-DCCH (SRB1), Received RRCReestablishment\n");
nr_rrc_ue_generate_rrcReestablishmentComplete(c1->choice.rrcReestablishment);
nr_rrc_ue_process_rrcReestablishment(rrc, gNB_indexP, c1->choice.rrcReestablishment);
break;
case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer: {
@@ -1442,7 +1719,7 @@ void *rrc_nrue(void *notUsed)
LOG_D(NR_RRC, "[UE %ld] Received %s: gNB %d\n", rrc->ue_id, ITTI_MSG_NAME(msg_p), NR_RRC_MAC_BCCH_DATA_IND(msg_p).gnb_index);
NRRrcMacBcchDataInd *bcch = &NR_RRC_MAC_BCCH_DATA_IND(msg_p);
if (bcch->is_bch)
nr_rrc_ue_decode_NR_BCCH_BCH_Message(rrc, bcch->gnb_index, bcch->sdu, bcch->sdu_size);
nr_rrc_ue_decode_NR_BCCH_BCH_Message(rrc, bcch->gnb_index, bcch->phycellid, bcch->ssb_arfcn, bcch->sdu, bcch->sdu_size);
else
nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(rrc, bcch->gnb_index, bcch->sdu, bcch->sdu_size, bcch->rsrq, bcch->rsrp);
break;
@@ -1589,12 +1866,56 @@ static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECa
}
}
static void nr_rrc_ue_generate_rrcReestablishmentComplete(NR_RRCReestablishment_t *rrcReestablishment)
void nr_rrc_initiate_rrcReestablishment(NR_UE_RRC_INST_t *rrc,
NR_ReestablishmentCause_t cause,
const int gnb_id)
{
rrc->reestablishment_cause = cause;
NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
rrcPerNB_t *rrcNB = rrc->perNB + gnb_id;
// reset timers to SIB1 as part of release of spCellConfig
// it needs to be done before handling timers
set_rlf_sib1_timers_and_constants(timers, rrcNB->SInfo.sib1);
// stop timer T310, if running
nr_timer_stop(&timers->T310);
// stop timer T304, if running
nr_timer_stop(&timers->T304);
// start timer T311
nr_timer_start(&timers->T311);
// suspend all RBs, except SRB0
for (int i = 1; i < 4; i++) {
if (rrc->Srb[i] == RB_ESTABLISHED) {
rrc->Srb[i] = RB_SUSPENDED;
nr_pdcp_suspend_srb(rrc->ue_id, i);
}
}
for (int i = 1; i <= MAX_DRBS_PER_UE; i++) {
if (get_DRB_status(rrc, i) == RB_ESTABLISHED) {
set_DRB_status(rrc, i, RB_SUSPENDED);
nr_pdcp_suspend_drb(rrc->ue_id, i);
}
}
// release the MCG SCell(s), if configured
// no SCell configured in our implementation
// reset MAC
// release spCellConfig, if configured
// perform cell selection in accordance with the cell selection process
nr_rrc_mac_config_req_reset(rrc->ue_id, RE_ESTABLISHMENT);
}
static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc,
const NR_RRCReestablishment_t *rrcReestablishment)
{
uint8_t buffer[RRC_BUFFER_SIZE] = {0};
int size = do_RRCReestablishmentComplete(buffer, RRC_BUFFER_SIZE,
rrcReestablishment->rrc_TransactionIdentifier);
LOG_I(NR_RRC, "[RAPROC] Logical Channel UL-DCCH (SRB1), Generating RRCReestablishmentComplete (bytes %d)\n", size);
int srb_id = 1; // RRC re-establishment complete on SRB1
nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL);
}
void *recv_msgs_from_lte_ue(void *args_p)
@@ -1839,9 +2160,9 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc,
// release all radio resources, including release of the RLC entity,
// the MAC configuration and the associated PDCP entity
// and SDAP for all established RBs
for (int i = 0; i < MAX_DRBS_PER_UE; i++) {
if (rrc->status_DRBs[i] != RB_NOT_PRESENT) {
rrc->status_DRBs[i] = RB_NOT_PRESENT;
for (int i = 1; i <= MAX_DRBS_PER_UE; i++) {
if (get_DRB_status(rrc, i) != RB_NOT_PRESENT) {
set_DRB_status(rrc, i, RB_NOT_PRESENT);
nr_pdcp_release_drb(rrc->ue_id, i);
}
}
+11 -3
View File
@@ -56,6 +56,9 @@
#include "NR_UE-NR-Capability.h"
#include "NR_SL-PreconfigurationNR-r16.h"
#include "NR_MasterInformationBlockSidelink.h"
#include "NR_ReestablishmentCause.h"
#include "NR_MeasurementReport.h"
#include "NR_VarMeasReport.h"
#include "RRC/NR/nr_rrc_common.h"
#include "as_message.h"
@@ -65,6 +68,7 @@
#define MAX_MEAS_OBJ 7
#define MAX_MEAS_CONFIG 7
#define MAX_MEAS_ID 7
#define MAX_QUANTITY_CONFIG 2
typedef uint32_t channel_t;
@@ -85,8 +89,6 @@ typedef enum Rrc_State_NR_e {
RRC_STATE_INACTIVE_NR,
RRC_STATE_CONNECTED_NR,
RRC_STATE_DETACH_NR,
RRC_STATE_FIRST_NR = RRC_STATE_IDLE_NR,
RRC_STATE_LAST_NR = RRC_STATE_CONNECTED_NR,
} Rrc_State_NR_t;
typedef enum requested_SI_List_e {
@@ -155,6 +157,7 @@ typedef struct NR_UE_Timers_Constants_s {
NR_timer_t T311;
NR_timer_t T319;
NR_timer_t T320;
NR_timer_t T321;
NR_timer_t T325;
NR_timer_t T390;
// counters
@@ -175,8 +178,9 @@ typedef enum { RB_NOT_PRESENT, RB_ESTABLISHED, RB_SUSPENDED } NR_RB_status_t;
typedef struct rrcPerNB {
NR_MeasObjectToAddMod_t *MeasObj[MAX_MEAS_OBJ];
NR_ReportConfigToAddMod_t *ReportConfig[MAX_MEAS_CONFIG];
NR_QuantityConfig_t *QuantityConfig;
NR_QuantityConfigNR_t *QuantityConfig[MAX_QUANTITY_CONFIG];
NR_MeasIdToAddMod_t *MeasId[MAX_MEAS_ID];
NR_VarMeasReport_t *MeasReport[MAX_MEAS_ID];
NR_MeasGapConfig_t *measGapConfig;
NR_UE_RRC_SI_INFO SInfo;
NR_RSRP_Range_t s_measure;
@@ -187,10 +191,14 @@ typedef struct NR_UE_RRC_INST_s {
rrcPerNB_t perNB[NB_CNX_UE];
rnti_t rnti;
uint32_t phyCellID;
long arfcn_ssb;
OAI_NR_UECapability_t UECap;
NR_UE_Timers_Constants_t timers_and_constants;
RA_trigger_t ra_trigger;
NR_ReestablishmentCause_t reestablishment_cause;
plmn_t plmnID;
NR_BWP_Id_t dl_bwp_id;
+4 -1
View File
@@ -73,6 +73,8 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
const frame_t frame,
const int slot,
const rnti_t rnti,
const uint32_t cellid,
const long arfcn,
const channel_t channel,
const uint8_t* pduP,
const sdu_size_t pdu_len);
@@ -86,7 +88,8 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc,
NR_RRCRelease_t *RRCRelease);
void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success);
void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti);
void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, int gnb_id);
void set_rlf_sib1_timers_and_constants(NR_UE_Timers_Constants_t *tac, NR_SIB1_t *sib1);
/**\brief RRC UE task.
\param void *args_p Pointer on arguments to start the task. */
+10 -2
View File
@@ -121,10 +121,18 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc)
bool t300_expired = nr_timer_tick(&timers->T300);
if(t300_expired) {
LOG_W(NR_RRC, "Timer T300 expired\n");
LOG_W(NR_RRC, "Timer T300 expired! No timely response to RRCSetupRequest\n");
handle_t300_expiry(rrc);
}
bool t301_expired = nr_timer_tick(&timers->T301);
// Upon T301 expiry, the UE shall perform the actions upon going to RRC_IDLE
// with release cause 'RRC connection failure'
if(t301_expired) {
LOG_W(NR_RRC, "Timer T301 expired! No timely response to RRCReestabilshmentRequest\n");
nr_rrc_going_to_IDLE(rrc, RRC_CONNECTION_FAILURE, NULL);
}
bool t304_expired = nr_timer_tick(&timers->T304);
if(t304_expired) {
LOG_W(NR_RRC, "Timer T304 expired\n");
@@ -146,7 +154,7 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc)
bool t311_expired = nr_timer_tick(&timers->T311);
if(t311_expired) {
LOG_W(NR_RRC, "Timer T311 expired\n");
LOG_W(NR_RRC, "Timer T311 expired! No suitable cell found in time after initiation of re-establishment\n");
// Upon T311 expiry, the UE shall perform the actions upon going to RRC_IDLE
// with release cause 'RRC connection failure'
nr_rrc_going_to_IDLE(rrc, RRC_CONNECTION_FAILURE, NULL);