Skip to content

Commit 792a739

Browse files
Merge pull request #29 from microsoft/matt/25.04_features
Matt/25.04 features
2 parents 41fccbc + 5f1a73d commit 792a739

17 files changed

Lines changed: 832 additions & 29 deletions

codelets/slice_mgmt/Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
PROTO_AND_SCHEMA := \
2+
slice_mgmt^slice_mgmt_req \
3+
slice_mgmt^slice_mgmt_ind \
4+
5+
6+
include ../Makefile.defs
7+
include ../Makefile.common
8+

codelets/slice_mgmt/slice_mgmt.cpp

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
/*
3+
This codelet allows an app to configure the allocations of slices.
4+
*/
5+
6+
#include <linux/bpf.h>
7+
8+
#include <string.h>
9+
10+
#include "jbpf_srsran_contexts.h"
11+
#include "slice_mgmt.pb.h"
12+
13+
#define SEC(NAME) __attribute__((section(NAME), used))
14+
15+
#include "jbpf_defs.h"
16+
#include "jbpf_helper.h"
17+
18+
#include "../utils/misc_utils.h"
19+
20+
21+
22+
// The input request channel
23+
jbpf_control_input_map(slice_request_map, slice_mgmt_req, 1);
24+
25+
// Temporary map to store an incoming request. Used as stack is too small for a local variable.
26+
struct jbpf_load_map_def SEC("maps") input_request_tmp = {
27+
.type = JBPF_MAP_TYPE_ARRAY,
28+
.key_size = sizeof(int),
29+
.value_size = sizeof(slice_mgmt_req),
30+
.max_entries = 1,
31+
};
32+
33+
typedef struct {
34+
int requested;
35+
slice_mgmt_set_req request;
36+
} slice_mgmt_set_request_t;
37+
38+
// Map to store "SET" requests. This is maintained as the request might be for a specific sfn/sn
39+
struct jbpf_load_map_def SEC("maps") set_request_map = {
40+
.type = JBPF_MAP_TYPE_ARRAY,
41+
.key_size = sizeof(int),
42+
.value_size = sizeof(slice_mgmt_set_request_t),
43+
.max_entries = 1,
44+
};
45+
46+
// Flag to indicate if an INDICATION needs to be sent to higher layers
47+
struct jbpf_load_map_def SEC("maps") indication_trigger_map = {
48+
.type = JBPF_MAP_TYPE_ARRAY,
49+
.key_size = sizeof(int),
50+
.value_size = sizeof(uint32_t),
51+
.max_entries = 1,
52+
};
53+
54+
// Latest config sent back to the app
55+
jbpf_output_map(slice_indication_map, slice_mgmt_ind, 16);
56+
57+
58+
59+
extern "C" SEC("jbpf_srsran_generic")
60+
uint64_t jbpf_main(void* state)
61+
{
62+
int zero_index=0;
63+
64+
int i=0;
65+
int j=0;
66+
67+
struct jbpf_ran_generic_ctx* ctx = (jbpf_ran_generic_ctx*)state;
68+
69+
jbpf_slice_allocation& data = *reinterpret_cast<jbpf_slice_allocation*>(ctx->data);
70+
71+
// Ensure the object is within valid bounds
72+
if (reinterpret_cast<const uint8_t*>(&data) + sizeof(jbpf_slice_allocation) > reinterpret_cast<const uint8_t*>(ctx->data_end)) {
73+
return JBPF_CODELET_FAILURE; // Out-of-bounds access
74+
}
75+
76+
// get sfn and slot_index from metadata
77+
uint32_t sfn = (uint32_t) (ctx->srs_meta_data1 >> 16) & 0xFFFF;
78+
uint32_t slot_index = (uint32_t) (ctx->srs_meta_data1 & 0xFFFF);
79+
80+
// Flag to indicate if an INDICATION needs to be sent to higher layers
81+
uint32_t *indication_triggered = (uint32_t*)jbpf_map_lookup_elem(&indication_trigger_map, &zero_index);
82+
if (!indication_triggered) {
83+
return JBPF_CODELET_FAILURE;
84+
}
85+
86+
// Temporary map to store an incoming request. Used as stack is too small for a local variable.
87+
slice_mgmt_req *input_req_tmp = (slice_mgmt_req*)jbpf_map_lookup_elem(&input_request_tmp, &zero_index);
88+
if (!input_req_tmp) {
89+
return JBPF_CODELET_FAILURE;
90+
}
91+
92+
// Map to store "SET" requests. This is maintained as the request might be for a specific sfn/sn
93+
slice_mgmt_set_request_t *set_request = (slice_mgmt_set_request_t*)jbpf_map_lookup_elem(&set_request_map, &zero_index);
94+
if (!set_request) {
95+
return JBPF_CODELET_FAILURE;
96+
}
97+
98+
99+
// has there has previously been a trigger to send the latest slice-config
100+
if (*indication_triggered == 1) {
101+
102+
// send latest received config from the RAN
103+
104+
slice_mgmt_ind* ind = (slice_mgmt_ind*)jbpf_get_output_buf(&slice_indication_map);
105+
if (!ind) {
106+
return JBPF_CODELET_FAILURE;
107+
}
108+
109+
ind->timestamp = jbpf_time_get_ns();
110+
ind->sfn = sfn;
111+
ind->slot_index = slot_index;
112+
113+
// map from jbpf_slice_allocation to slice_mgmt
114+
ind->slice_count = 0;
115+
for (i=0; i<data.num_slices; i++) {
116+
if (i >= JBPF_MAX_SLICES) return JBPF_CODELET_FAILURE;
117+
ind->slice[ind->slice_count % 16].pci = data.slices[i % JBPF_MAX_SLICES].pci;
118+
ind->slice[ind->slice_count % 16].plmn_id = data.slices[i % JBPF_MAX_SLICES].plmn_id;
119+
ind->slice[ind->slice_count % 16].nssai.sst = data.slices[i % JBPF_MAX_SLICES].nssai.sst;
120+
ind->slice[ind->slice_count % 16].nssai.sd = data.slices[i % JBPF_MAX_SLICES].nssai.sd;
121+
ind->slice[ind->slice_count % 16].min_prb_policy_ratio = data.slices[i % JBPF_MAX_SLICES].min_prb_policy_ratio;
122+
ind->slice[ind->slice_count % 16].max_prb_policy_ratio = data.slices[i % JBPF_MAX_SLICES].max_prb_policy_ratio;
123+
ind->slice[ind->slice_count % 16].priority = data.slices[i % JBPF_MAX_SLICES].priority;
124+
ind->slice_count++;
125+
}
126+
127+
// send to the higher layer app
128+
if (jbpf_send_output(&slice_indication_map) < 0) {
129+
return JBPF_CODELET_FAILURE;
130+
}
131+
132+
jbpf_printf_debug("slice-allocation INDICATION sent to higher layers\n");
133+
134+
// clear trigger flag
135+
*indication_triggered = 0;
136+
}
137+
138+
// get request from "slice_request_map"
139+
if (jbpf_control_input_receive(&slice_request_map, input_req_tmp, sizeof(slice_mgmt_req)) > 0) {
140+
141+
if (input_req_tmp->msg_type == slice_mgmt_msg_type_GET_SLICE_ALLOC) {
142+
143+
jbpf_printf_debug("GET_SLICE_ALLOC received from higher layers.\n");
144+
145+
// request received to send latest slice config to higher layer app
146+
147+
// set flag to send cfg to higher layer app
148+
*indication_triggered = 1;
149+
150+
} else if (input_req_tmp->msg_type == slice_mgmt_msg_type_SET_SLICE_ALLOC) {
151+
152+
jbpf_printf_debug("SET_SLICE_ALLOC received from higher layers\n");
153+
154+
// request received to set new slice config
155+
156+
// check set_req is present
157+
if (!input_req_tmp->has_set_req) {
158+
// require set_req not present !!
159+
return JBPF_CODELET_FAILURE;
160+
}
161+
162+
// update the latest waiting set request in "set_request_map"
163+
memcpy(&set_request->request, &input_req_tmp->set_req, sizeof(slice_mgmt_set_req));
164+
set_request->requested = true;
165+
166+
} else {
167+
// Unexpected msg_type in request
168+
return JBPF_CODELET_FAILURE;
169+
}
170+
}
171+
172+
if (set_request->requested) {
173+
174+
// does the request have sfn/slot set, and match the currennt sfn/slot of the RAN
175+
bool update_ran_now =
176+
(!set_request->request.has_sfn || set_request->request.sfn == sfn) &&
177+
(!set_request->request.has_slot_index || set_request->request.slot_index == slot_index);
178+
179+
// update the RAN now if sf/slot matches.
180+
if (update_ran_now) {
181+
182+
jbpf_printf_debug("New slice-allocation will be configured now (sfn/slot=%d/%d) \n", sfn, slot_index);
183+
184+
// clear flag so we dont repeatedly process the request
185+
set_request->requested = 0;
186+
187+
// set flag to send cfg to higher layer app
188+
*indication_triggered = 1;
189+
190+
// update "data" with the requested config
191+
192+
// validate that the set-request has no new slices,
193+
if (set_request->request.slice_count > data.num_slices) {
194+
// the rtequest has too many slices. so this request will be dropped
195+
return JBPF_CODELET_FAILURE;
196+
}
197+
// validate that no static parameters have changed
198+
for (i=0; i<set_request->request.slice_count; i++) {
199+
// find slice
200+
bool slice_found = false;
201+
for (j=0; j<data.num_slices && (!slice_found); j++) {
202+
slice_found = ((data.slices[j % JBPF_MAX_SLICES].pci == set_request->request.slice[i].pci) &&
203+
(data.slices[j % JBPF_MAX_SLICES].plmn_id == set_request->request.slice[i].plmn_id) &&
204+
(data.slices[j % JBPF_MAX_SLICES].nssai.sst == set_request->request.slice[i].nssai.sst) &&
205+
(data.slices[j % JBPF_MAX_SLICES].nssai.sd == set_request->request.slice[i].nssai.sd));
206+
}
207+
if (!slice_found) {
208+
// slice could not be found
209+
return JBPF_CODELET_FAILURE;
210+
}
211+
}
212+
213+
// if we reach here all slices in the request are validated
214+
// update the dynamic paramters to those from the set-request
215+
for (i=0; i<set_request->request.slice_count; i++) {
216+
for (j=0; j<data.num_slices; j++) {
217+
bool slice_found = ((data.slices[j % JBPF_MAX_SLICES].pci == set_request->request.slice[i].pci) &&
218+
(data.slices[j % JBPF_MAX_SLICES].plmn_id == set_request->request.slice[i].plmn_id) &&
219+
(data.slices[j % JBPF_MAX_SLICES].nssai.sst == set_request->request.slice[i].nssai.sst) &&
220+
(data.slices[j % JBPF_MAX_SLICES].nssai.sd == set_request->request.slice[i].nssai.sd));
221+
if (slice_found) {
222+
data.slices[j % JBPF_MAX_SLICES].min_prb_policy_ratio = set_request->request.slice[i].min_prb_policy_ratio;
223+
data.slices[j % JBPF_MAX_SLICES].max_prb_policy_ratio = set_request->request.slice[i].max_prb_policy_ratio;
224+
data.slices[j % JBPF_MAX_SLICES].priority = set_request->request.slice[i].priority;
225+
}
226+
}
227+
}
228+
229+
// return resukt to show that an update has taken place
230+
return JBPF_CTRL_CODELET_SUCCESS;
231+
}
232+
}
233+
234+
return JBPF_CODELET_SUCCESS;
235+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
slice_mgmt_set_req.slice max_count:16
4+
slice_mgmt_ind.slice max_count:16
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
syntax = "proto2";
5+
6+
message nssai_t {
7+
required uint32 sst = 1;
8+
required uint32 sd = 2;
9+
}
10+
11+
message slice_t {
12+
required uint32 pci = 1;
13+
required uint32 plmn_id = 2;
14+
required nssai_t nssai = 3;
15+
required uint32 min_prb_policy_ratio = 4; // Sets the minimum percentage of PRBs to be allocated to the slice. Supported [0 - 100].
16+
required uint32 max_prb_policy_ratio = 5; //Sets the minimum percentage of PRBs to be allocated to the slice. Supported [0 - 100].
17+
required uint32 priority = 6; // Sets the slice priority. Values: [0 - 254].
18+
}
19+
20+
enum slice_mgmt_msg_type {
21+
UNKNOWN = 0;
22+
GET_SLICE_ALLOC = 1;
23+
SET_SLICE_ALLOC = 2;
24+
}
25+
26+
message slice_mgmt_set_req {
27+
optional uint32 sfn = 1;
28+
optional uint32 slot_index = 2;
29+
repeated slice_t slice = 3;
30+
}
31+
32+
message slice_mgmt_req {
33+
required slice_mgmt_msg_type msg_type = 1;
34+
optional slice_mgmt_set_req set_req = 2; // Used if msg_type == GET_SLICE_ALLOC
35+
}
36+
37+
message slice_mgmt_ind {
38+
required uint64 timestamp = 1;
39+
required uint32 sfn = 2;
40+
required uint32 slot_index = 3;
41+
repeated slice_t slice = 4;
42+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT license.
3+
4+
codeletset_id: slice_mgmt
5+
6+
codelet_descriptor:
7+
8+
- codelet_name: slice_mgmt
9+
codelet_path: ${JBPF_CODELETS}/slice_mgmt/slice_mgmt.o
10+
hook_name: mac_sched_slice_mgmt
11+
priority: 1
12+
in_io_channel:
13+
- name: slice_request_map
14+
# forward_destination: DestinationNone
15+
serde:
16+
file_path: ${JBPF_CODELETS}/slice_mgmt/slice_mgmt:slice_mgmt_req_serializer.so
17+
protobuf:
18+
package_path: ${JBPF_CODELETS}/slice_mgmt/slice_mgmt.pb
19+
msg_name: slice_mgmt_req
20+
out_io_channel:
21+
- name: slice_indication_map
22+
forward_destination: DestinationNone
23+
serde:
24+
file_path: ${JBPF_CODELETS}/slice_mgmt/slice_mgmt:slice_mgmt_ind_serializer.so
25+
protobuf:
26+
package_path: ${JBPF_CODELETS}/slice_mgmt/slice_mgmt.pb
27+
msg_name: slice_mgmt_ind

codelets/utils/misc_utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#ifndef MISC_UTILS_H
55
#define MISC_UTILS_H
66

7+
#define JBPF_CTRL_CODELET_SUCCESS (1)
78
#define JBPF_CODELET_SUCCESS (0)
89
#define JBPF_CODELET_FAILURE (-1)
910

containers/Docker/Scripts/msft_config.yaml

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ cu_cp:
1515
sd: 163
1616
- sst: 1
1717
sd: 164
18+
- sst: 1
19+
sd: 165
1820
- plmn: "00101"
1921
tai_slice_support_list:
2022
- sst: 1
@@ -23,8 +25,11 @@ cu_cp:
2325
sd: 163
2426
- sst: 1
2527
sd: 164
28+
- sst: 1
29+
sd: 165
2630
security:
27-
nea_pref_list: nea2,nea1,nea3,nea0 # required for iPhone
31+
nia_pref_list: nia2,nia1
32+
nea_pref_list: nea2,nea1,nea3,nea0 # nea2 required for iPhone
2833
mobility:
2934
cells:
3035
- nr_cell_id: 0x66C000 # For the default gnb_id=411 (gnb_id_bit_length=22), NR cell IDs start with 0x66C000 and increment for each cell of the DU.
@@ -34,7 +39,6 @@ cu_cp:
3439
report_type: periodical
3540
report_interval_ms: 1024
3641

37-
3842
cell_cfg:
3943
dl_arfcn: 630684
4044
common_scs: 30
@@ -47,10 +51,6 @@ cell_cfg:
4751
ssb_block_power_dbm: -21
4852
nof_antennas_dl: 4
4953
nof_antennas_ul: 4
50-
# tdd_ul_dl_cfg:
51-
# nof_dl_symbols: 5
52-
# nof_dl_slots: 5
53-
# nof_ul_slots: 4
5454
tdd_ul_dl_cfg:
5555
dl_ul_tx_period: 10
5656
nof_dl_slots: 7
@@ -64,6 +64,19 @@ cell_cfg:
6464
prach_frequency_start: 12
6565
pusch:
6666
mcs_table: qam256
67+
slicing: # Use default slice allocations
68+
- # slice=internet
69+
sst: 1
70+
sd: 162
71+
- # slice=internet2
72+
sst: 1
73+
sd: 163
74+
- # slice=internet3
75+
sst: 1
76+
sd: 164
77+
- # slice=default
78+
sst: 1
79+
sd: 165
6780

6881
cells:
6982
- pci: 1

0 commit comments

Comments
 (0)