23constexpr const char* LOG_TAG =
"CApi";
83 return ErrorCode::SUCCESS;
90 return ErrorCode::SUCCESS;
101 uint32_t request_message_id,
105 return ErrorCode::NOT_FOUND;
128 if (!desc)
return nullptr;
146 uint32_t ran_function_id,
150 if (!sm)
return static_cast<int>(ErrorCode::INVALID_PARAM);
162 if (data && data_len) {
165 pdu.
choice = std::move(msg);
167 return static_cast<int>(sm->
emit_pdu(std::move(pdu)));
175 if (!sm)
return static_cast<int>(ErrorCode::INVALID_PARAM);
183 return static_cast<int>(sm->
emit_pdu(std::move(pdu)));
215 h->
agent = std::make_unique<E3Agent>(std::move(cfg));
228 if (!agent || !agent->
agent)
return static_cast<int>(ErrorCode::STATE_ERROR);
229 return static_cast<int>(agent->
agent->init());
233 if (!agent || !agent->
agent)
return static_cast<int>(ErrorCode::STATE_ERROR);
234 return static_cast<int>(agent->
agent->start());
238 if (!agent || !agent->
agent)
return;
239 agent->
agent->stop();
243 if (!agent || !agent->
agent || !sm)
return static_cast<int>(ErrorCode::INVALID_PARAM);
253 <<
" bytes of ran_function_data; E3AP requires 1.."
255 return static_cast<int>(ErrorCode::INVALID_PARAM);
261 std::unique_ptr<ServiceModel> uptr(sm);
262 return static_cast<int>(agent->
agent->register_sm(std::move(uptr)));
264 return static_cast<int>(ErrorCode::INTERNAL_ERROR);
270 return static_cast<int>(agent->
agent->state());
274 if (!agent || !agent->
agent)
return 0;
275 return agent->
agent->is_running() ? 1 : 0;
282 if (!agent || !agent->
agent)
return static_cast<int>(ErrorCode::INVALID_PARAM);
286 return static_cast<int>(ErrorCode::SUCCESS);
289 agent->
agent->set_dapp_report_handler(
291 const uint8_t* report_data =
303 return static_cast<int>(ErrorCode::SUCCESS);
307 if (out_len) *out_len = v.size();
308 if (v.empty())
return nullptr;
309 uint32_t* arr = (uint32_t*)malloc(
sizeof(uint32_t) * v.size());
310 if (!arr)
return nullptr;
311 memcpy(arr, v.data(),
sizeof(uint32_t) * v.size());
316 if (!agent || !agent->
agent) {
if (out_len) *out_len = 0;
return nullptr; }
317 auto v = agent->
agent->get_available_ran_functions();
322 if (!agent || !agent->
agent) {
if (out_len) *out_len = 0;
return nullptr; }
323 auto v = agent->
agent->get_registered_dapps();
328 if (!agent || !agent->
agent) {
if (out_len) *out_len = 0;
return nullptr; }
329 auto v = agent->
agent->get_dapp_subscriptions(dapp_id);
334 if (!agent || !agent->
agent) {
if (out_len) *out_len = 0;
return nullptr; }
335 auto v = agent->
agent->get_ran_function_subscribers(ran_function_id);
340 if (!agent || !agent->
agent) {
if (out_len) *out_len = 0;
return nullptr; }
341 auto v = agent->
agent->get_active_ran_functions();
348 uint32_t ran_function_id
350 if (!agent || !agent->
agent)
return 0;
351 return agent->
agent->get_subscription_periodicity(dapp_id, ran_function_id);
357 uint32_t ran_function_id,
360 if (!agent || !agent->
agent) {
if (out_len) *out_len = 0;
return nullptr; }
361 auto v = agent->
agent->get_subscription_telemetry_ids(dapp_id, ran_function_id);
368 uint32_t ran_function_id,
371 if (!agent || !agent->
agent) {
if (out_len) *out_len = 0;
return nullptr; }
372 auto v = agent->
agent->get_subscription_control_ids(dapp_id, ran_function_id);
383 uint32_t ran_function_id,
387 if (!agent || !agent->
agent)
return static_cast<int>(ErrorCode::INVALID_PARAM);
388 std::vector<uint8_t> buf;
389 if (data && data_len) buf.assign(data, data + data_len);
390 return static_cast<int>(agent->
agent->send_indication(dapp_id, ran_function_id, buf));
396 uint32_t ran_function_id,
397 const uint8_t* control_data,
398 size_t control_data_len,
401 if (!agent || !agent->
agent)
return static_cast<int>(ErrorCode::INVALID_PARAM);
402 std::vector<uint8_t> buf;
403 if (control_data && control_data_len) buf.assign(control_data, control_data + control_data_len);
404 return static_cast<int>(
405 agent->
agent->send_xapp_control(dapp_id, ran_function_id, buf, sequence_id));
413 if (!agent || !agent->
agent)
return static_cast<int>(ErrorCode::INVALID_PARAM);
415 return static_cast<int>(agent->
agent->send_message_ack(request_id, rc));
419 if (!agent || !agent->
agent)
return 0;
420 return agent->
agent->dapp_count();
424 if (!agent || !agent->
agent)
return 0;
425 return agent->
agent->subscription_count();
430#define X(name, val) case val: return #name;
433 default:
return "UNKNOWN_ERROR_CODE";
441 if (!agent || !agent->
agent)
return static_cast<int>(ErrorCode::INVALID_PARAM);
445 return static_cast<int>(ErrorCode::SUCCESS);
448 agent->
agent->set_dapp_status_changed_handler(
449 [handler]() { handler(); }
452 return static_cast<int>(ErrorCode::SUCCESS);
void e3_agent_free_uint32_array(uint32_t *arr)
Free an array previously returned by the e3_agent_get_* helpers.
e3_error_t e3_agent_register_sm(e3_agent_handle_t *agent, e3_service_model_handle_t *sm)
Register a ServiceModel implementation with the agent.
e3_service_model_handle_t * e3_service_model_create_from_c(const e3_c_service_model_desc_t *desc)
Create a ServiceModel implementation backed by C callbacks.
uint32_t e3_agent_get_subscription_periodicity(e3_agent_handle_t *agent, uint32_t dapp_id, uint32_t ran_function_id)
Get the reporting periodicity a dApp requested for a RAN function.
uint32_t * e3_agent_get_ran_function_subscribers(e3_agent_handle_t *agent, uint32_t ran_function_id, size_t *out_len)
Return a newly-allocated array of dApp IDs subscribed to a RAN function.
void e3_agent_destroy(e3_agent_handle_t *agent)
Destroy an E3Agent handle.
void e3_agent_stop(e3_agent_handle_t *agent)
Stop the agent and release runtime resources.
size_t e3_agent_subscription_count(e3_agent_handle_t *agent)
Total number of active subscriptions tracked by the agent.
e3_error_t e3_agent_set_dapp_report_handler(e3_agent_handle_t *agent, e3_dapp_report_cb handler)
Set callback for incoming dApp reports (dApp -> RAN).
const char * e3_error_to_string(e3_error_t code)
Convert a numeric error code to a human-readable name.
e3_agent_handle_t * e3_agent_create_default()
Create/destroy an E3Agent handle.
e3_error_t e3_agent_send_message_ack(e3_agent_handle_t *agent, uint32_t request_id, int response_code)
Send a message acknowledgment (e.g. ack a control/request from dApp).
int e3_agent_is_running(e3_agent_handle_t *agent)
Query whether the agent is currently running.
uint32_t * e3_agent_get_registered_dapps(e3_agent_handle_t *agent, size_t *out_len)
Return a newly-allocated array of registered dApp IDs.
e3_error_t e3_service_model_emit_message_ack(e3_service_model_handle_t *sm, uint32_t request_id, int response_code)
Emit a message acknowledgment from a ServiceModel.
int e3_agent_get_state(e3_agent_handle_t *agent)
Get the agent state as an integer matching libe3::AgentState.
e3_error_t e3_agent_start(e3_agent_handle_t *agent)
Start the agent processing threads and accept dApp connections.
void e3_service_model_destroy(e3_service_model_handle_t *sm)
Destroy a C-backed ServiceModel handle.
e3_agent_handle_t * e3_agent_create_with_config(const e3_config_t *config)
Create a new E3Agent with the given configuration.
e3_error_t e3_agent_send_indication(e3_agent_handle_t *agent, uint32_t dapp_id, uint32_t ran_function_id, const uint8_t *data, size_t data_len)
Send an indication message to a specific dApp.
e3_error_t e3_agent_init(e3_agent_handle_t *agent)
Initialize the agent.
uint32_t * e3_agent_get_active_ran_functions(e3_agent_handle_t *agent, size_t *out_len)
Return a newly-allocated array of RAN function IDs that currently have at least one subscriber (RAN r...
uint32_t * e3_agent_get_dapp_subscriptions(e3_agent_handle_t *agent, uint32_t dapp_id, size_t *out_len)
Return a newly-allocated array of RAN function IDs subscribed by a dApp.
uint32_t * e3_agent_get_subscription_control_ids(e3_agent_handle_t *agent, uint32_t dapp_id, uint32_t ran_function_id, size_t *out_len)
Get the control IDs a dApp requested for a RAN function.
e3_error_t e3_service_model_emit_indication(e3_service_model_handle_t *sm, uint32_t dapp_id, uint32_t ran_function_id, const uint8_t *data, size_t data_len)
Emit an indication message from a ServiceModel to the outbound queue.
size_t e3_agent_dapp_count(e3_agent_handle_t *agent)
Number of registered dApps known to the agent.
uint32_t * e3_agent_get_subscription_telemetry_ids(e3_agent_handle_t *agent, uint32_t dapp_id, uint32_t ran_function_id, size_t *out_len)
Get the telemetry IDs a dApp requested for a RAN function.
uint32_t * e3_agent_get_available_ran_functions(e3_agent_handle_t *agent, size_t *out_len)
Return a newly-allocated array of available RAN function IDs.
e3_error_t e3_agent_send_xapp_control(e3_agent_handle_t *agent, uint32_t dapp_id, uint32_t ran_function_id, const uint8_t *control_data, size_t control_data_len, uint32_t sequence_id)
Send an xApp control action to a specific dApp (e.g. from E2/SM).
static uint32_t * copy_vector_u32_to_c(const std::vector< uint32_t > &v, size_t *out_len)
e3_error_t e3_agent_set_dapp_status_changed_handler(e3_agent_handle_t *agent, e3_dapp_status_changed_cb handler)
Set callback for dApp status changes.
void(* e3_dapp_status_changed_cb)(void)
struct e3_agent_handle_s e3_agent_handle_t
void(* e3_dapp_report_cb)(uint32_t dapp_id, uint32_t ran_function_id, const uint8_t *report_data, size_t report_data_len, uint32_t sequence_id)
e3_error_t(* e3_sm_process_control_cb)(e3_service_model_handle_t *sm_handle, void *sm_context, uint32_t request_message_id, uint32_t dapp_id, uint32_t ran_function_id, uint32_t control_id, const uint8_t *data, size_t data_len, uint32_t sequence_id)
void(* e3_sm_destroy_cb)(void *sm_context)
e3_error_t(* e3_sm_start_cb)(void *sm_context)
void(* e3_sm_stop_cb)(void *sm_context)
int(* e3_sm_is_running_cb)(void *sm_context)
struct e3_service_model_handle_s e3_service_model_handle_t
e3_error_t(* e3_sm_init_cb)(void *sm_context)
ErrorCode emit_outbound(Pdu &&pdu)
Emit an outbound PDU produced by the SM.
E3Agent - Main façade class for RAN vendors.
libe3 error codes - shared C/C++ definitions
int e3_error_t
C error type alias.
#define LIBE3_ERROR_CODE_LIST
X-macro list of all libe3 error codes.
Lock-free per-thread latency stamp recorder (header-only, C99).
static void latrec_tstamp(uint64_t seq, uint8_t stage, uint64_t aux, uint64_t aux2)
static uint64_t latrec_seq_next(void)
static uint64_t latrec_ctx(void)
Logging facility for libe3.
#define E3_LOG_ERROR(component)
ErrorCode
Error codes returned by libe3 operations Use shared error-code list (see libe3/error_codes....
E3TransportLayer
Transport layer types (matches Python E3TransportLayer).
std::function< void()> DAppStatusChangedHandler
ResponseCode
E3AP response codes.
@ NEGATIVE
Request rejected.
@ POSITIVE
Request accepted.
std::function< void(const DAppReport &)> DAppReportHandler
constexpr size_t MAX_PROTOCOL_DATA_SIZE
E3LinkLayer
Link layer types (matches Python E3LinkLayer).
EncodingFormat
E3AP encoding formats supported by the library.
Service Model Interface - Extension point for RAN vendors.
std::unique_ptr< E3Agent > agent
Descriptor describing a ServiceModel implemented in C.
const uint32_t * control_ids
const uint8_t * ran_function_data
const uint32_t * telemetry_ids
e3_sm_is_running_cb sm_is_running
size_t ran_function_data_len
e3_sm_process_control_cb sm_process_control
e3_sm_destroy_cb sm_destroy
Configuration for creating an E3Agent from C.
const char * setup_endpoint
const char * ran_identifier
const char * subscriber_endpoint
const char * publisher_endpoint
ErrorCode start() override
Start the SM processing.
uint32_t ran_function_id_s
void stop() override
Stop the SM processing.
void destroy() override
Destroy the SM and release resources.
e3_sm_process_control_cb sm_process_control
ErrorCode handle_control_action(uint32_t request_message_id, const DAppControlAction &action) override
Process a control action from a dApp.
std::vector< uint32_t > control_ids_s
ErrorCode init() override
Initialize the SM.
bool is_running() const override
Check if SM is currently running.
std::vector< uint32_t > telemetry_ids() const override
Get telemetry IDs supported by this SM.
bool transferred_to_agent
std::string name() const override
Get SM name.
std::vector< uint32_t > control_ids() const override
Get control IDs supported by this SM.
uint32_t ran_function_id() const override
Get RAN function ID for this SM.
std::vector< uint32_t > telemetry_ids_s
uint32_t version() const override
Get SM version.
std::vector< uint8_t > ran_function_data_s
e3_sm_is_running_cb sm_is_running
std::vector< uint8_t > ran_function_data() const override
RAN-function-specific opaque data (required, 1..32768 bytes).
e3_sm_destroy_cb sm_destroy
ErrorCode emit_pdu(Pdu &&pdu)
e3_service_model_handle_s(const e3_c_service_model_desc_t &desc)
E3AP dApp Control Action structure.
uint32_t ran_function_identifier
std::vector< uint8_t > action_data
uint32_t control_identifier
Control identifier.
E3AP dApp Report structure.
std::vector< uint8_t > report_data
uint32_t ran_function_identifier
Configuration for E3Agent.
std::string log_path
Path of the shared log file. Empty (default) => auto-generated.
std::string subscriber_endpoint
Endpoint URI for inbound channel.
int log_level
Logging verbosity: 0=none, 1=error, 2=warn, 3=info, 4=debug, 5=trace.
uint16_t setup_port
Port used for E3AP setup channel.
int io_thread_affinity
CPU core to pin the subscriber and publisher I/O threads to.
EncodingFormat encoding
PDU encoding format (ASN.1 PER or JSON).
E3LinkLayer link_layer
Link-layer transport (ZMQ or POSIX).
std::string publisher_endpoint
Endpoint URI for outbound channel.
uint16_t subscriber_port
Port used for inbound control/subscription channel.
std::string ran_identifier
Unique identifier for this RAN function (e.g. "DU-1").
E3TransportLayer transport_layer
Transport-layer protocol (SCTP, TCP, IPC).
size_t io_threads
Number of I/O threads (used by ZMQ context).
std::string setup_endpoint
Endpoint URI for setup channel.
uint16_t publisher_port
Port used for outbound indication/publication channel.
E3AP Indication Message structure.
uint32_t ran_function_identifier
RAN function identifier.
std::vector< uint8_t > protocol_data
E3AP Message Acknowledgment structure.
ResponseCode response_code
Response code (positive/negative).
uint32_t request_id
ID of the request being acknowledged.
Generic E3AP PDU structure.
uint64_t enqueue_seq
Set by queue_outbound; keys the [latrec] L-stage records.
E3AP Protocol Types - Vendor-neutral type definitions.