From ac53fef21cad5adfb1efc51a24e20b993047547b Mon Sep 17 00:00:00 2001 From: Kirill Faizullin Date: Fri, 24 Apr 2026 15:54:37 +0300 Subject: [PATCH 01/10] feat(nic-stats): added NIC statistics in shared memory with FFI and RPC --- api/counter.h | 6 ++ controlplane/ffi/shm.go | 13 +++ controlplane/ynpb/counters.proto | 4 + dataplane/dataplane.c | 46 +++++----- dataplane/worker.c | 151 ++++++++++++++++++++----------- lib/controlplane/agent/agent.c | 68 ++++++++++++++ lib/controlplane/config/zone.h | 7 ++ lib/dataplane/config/zone.h | 15 +++ 8 files changed, 233 insertions(+), 77 deletions(-) diff --git a/api/counter.h b/api/counter.h index debcaace1..f4a0f3616 100644 --- a/api/counter.h +++ b/api/counter.h @@ -49,6 +49,12 @@ yanet_get_chain_counters( const char *chain_name ); +struct counter_handle_list * +yanet_get_nic_counters( + struct dp_config *dp_config, + const char *device_name +); + // Get module counters, optionally filtered by name. struct counter_handle_list * yanet_get_module_counters( diff --git a/controlplane/ffi/shm.go b/controlplane/ffi/shm.go index 15a3dc799..a5b73d32a 100644 --- a/controlplane/ffi/shm.go +++ b/controlplane/ffi/shm.go @@ -755,6 +755,19 @@ func (m *DPConfig) PerformanceCounters( return result, nil } +func (m *DPConfig) NicCounters(deviceName string) []CounterInfo { + cDeviceName := C.CString(deviceName) + defer C.free(unsafe.Pointer(cDeviceName)) + counters := C.yanet_get_nic_counters(m.ptr, cDeviceName) + defer C.yanet_counter_handle_list_free(counters) + + if counters == nil { + return nil + } + + return m.encodeCounters(counters) +} + type ModuleReference struct { Device string Pipeline string diff --git a/controlplane/ynpb/counters.proto b/controlplane/ynpb/counters.proto index 97c8cd365..153717201 100644 --- a/controlplane/ynpb/counters.proto +++ b/controlplane/ynpb/counters.proto @@ -11,11 +11,15 @@ service CountersService { rpc Function(FunctionCountersRequest) returns (CountersResponse) {} rpc Chain(ChainCountersRequest) returns (CountersResponse) {} rpc Module(ModuleCountersRequest) returns (CountersResponse) {} + rpc Nic(NicCounterRequest) returns (CountersResponse) {} rpc Perf(PerfCountersRequest) returns (PerfCountersResponse) {} } message DeviceCountersRequest { string device = 1; } +message NicCounterRequest { string device = 1; } + + message PipelineCountersRequest { string device = 1; string pipeline = 2; diff --git a/dataplane/dataplane.c b/dataplane/dataplane.c index 14d3b4e80..ef5c07830 100644 --- a/dataplane/dataplane.c +++ b/dataplane/dataplane.c @@ -617,11 +617,11 @@ stat_thread(void *arg) { struct rte_eth_xstat_name names[4096]; struct rte_eth_xstat xstats0[dataplane->device_count][4096]; - struct rte_eth_stats stats0[dataplane->device_count]; + // struct rte_eth_stats stats0[dataplane->device_count]; for (uint16_t idx = 0; idx < dataplane->device_count; ++idx) { - rte_eth_stats_get( - dataplane->devices[idx].port_id, &stats0[idx] - ); + // rte_eth_stats_get( + // dataplane->devices[idx].port_id, &stats0[idx] + // ); rte_eth_xstats_get( dataplane->devices[idx].port_id, xstats0[idx], 4096 ); @@ -631,25 +631,25 @@ stat_thread(void *arg) { sleep(1); for (uint16_t idx = 0; idx < dataplane->device_count; ++idx) { - struct rte_eth_stats stats1; - rte_eth_stats_get( - dataplane->devices[idx].port_id, &stats1 - ); - fprintf(log, - "dev %u ib %li ob %li ip %li op %li ie %li oe " - "%li\n", - idx, - (int64_t)(stats1.ibytes - stats0[idx].ibytes), - (int64_t)(stats1.obytes - stats0[idx].obytes), - (int64_t)(stats1.ipackets - stats0[idx].ipackets - ), - (int64_t)(stats1.opackets - stats0[idx].opackets - ), - (int64_t)(stats1.ierrors - stats0[idx].ierrors), - (int64_t)(stats1.oerrors - stats0[idx].oerrors) - ); - - memcpy(&stats0[idx], &stats1, sizeof(stats1)); + // struct rte_eth_stats stats1; + // rte_eth_stats_get( + // dataplane->devices[idx].port_id, &stats1 + // ); + // fprintf(log, + // "dev %u ib %li ob %li ip %li op %li ie %li oe " + // "%li\n", + // idx, + // (int64_t)(stats1.ibytes - stats0[idx].ibytes), + // (int64_t)(stats1.obytes - stats0[idx].obytes), + // (int64_t)(stats1.ipackets - stats0[idx].ipackets + // ), + // (int64_t)(stats1.opackets - stats0[idx].opackets + // ), + // (int64_t)(stats1.ierrors - stats0[idx].ierrors), + // (int64_t)(stats1.oerrors - stats0[idx].oerrors) + // ); + + // memcpy(&stats0[idx], &stats1, sizeof(stats1)); struct rte_eth_xstat xstats1[4096]; rte_eth_xstats_get_names( diff --git a/dataplane/worker.c b/dataplane/worker.c index 60cc8c7cf..5724cdcfd 100644 --- a/dataplane/worker.c +++ b/dataplane/worker.c @@ -55,6 +55,8 @@ #include +#define NIC_STATS_FREAQUENCY 1000 + static void worker_read(struct dataplane_worker *worker, struct packet_list *packets) { struct worker_read_ctx *ctx = &worker->read_ctx; @@ -271,6 +273,52 @@ worker_write(struct dataplane_worker *worker, struct packet_list *packets) { } } +struct nic_stat { + uint64_t ibytes; + uint64_t obytes; + uint64_t ipackets; + uint64_t opackets; + uint64_t ierrors; + uint64_t oerrors; + uint64_t rx_nombuf; +}; + +void worker_unload_nic_stats(struct dataplane_worker *worker) { + struct rte_eth_stats stats1; + struct dp_worker *dp_worker = worker->dp_worker; + + // const struct nic_stat stats0 = { + // .ibytes = *dp_worker->nic_rx_bytes, + // .obytes = *dp_worker->nic_tx_bytes, + // .ipackets = *dp_worker->nic_rx_packets, + // .opackets = *dp_worker->nic_tx_packets, + // .ierrors = *dp_worker->nic_rx_errors, + // .oerrors = *dp_worker->nic_tx_errors, + // .rx_nombuf = *dp_worker->nic_rx_nombuf + // }; + + + rte_eth_stats_get(worker->port_id, &stats1); + + // struct nic_stat diff = { + // .ibytes = stats1.ibytes - stats0.ibytes, + // .obytes = stats1.obytes - stats0.obytes, + // .ipackets = stats1.ipackets - stats0.ipackets, + // .opackets = stats1.opackets - stats0.opackets, + // .ierrors = stats1.ierrors - stats0.ierrors, + // .oerrors = stats1.oerrors - stats0.oerrors, + // .rx_nombuf = stats1.rx_nombuf - stats0.rx_nombuf + // }; + + *dp_worker->nic_rx_bytes = stats1.ibytes; + *dp_worker->nic_tx_bytes = stats1.obytes; + *dp_worker->nic_rx_packets = stats1.ipackets; + *dp_worker->nic_tx_packets = stats1.opackets; + *dp_worker->nic_rx_errors = stats1.ierrors; + *dp_worker->nic_tx_errors = stats1.oerrors; + *dp_worker->nic_rx_nombuf = stats1.rx_nombuf; +} + static void worker_loop_round(struct dataplane_worker *worker) { // Initialize current worker time @@ -312,7 +360,11 @@ worker_loop_round(struct dataplane_worker *worker) { uint64_t device_count = cp_config_gen->device_registry.registry.capacity; + uint64_t iterations = 0; + while (1) { + iterations = (iterations + 1) % NIC_STATS_FREAQUENCY; + if (iterations == 0) worker_unload_nic_stats(worker); struct packet_front schedule_input[device_count]; for (uint64_t idx = 0; idx < device_count; ++idx) @@ -406,6 +458,32 @@ worker_thread_start(void *arg) { return NULL; } +static const struct { + const char *name; + uint64_t size; + const size_t *offset; +} worker_counter_info[] = { + {"iterations", 1, (const size_t[]){offsetof(struct dp_worker, iterations)}}, + {"rx", 2, (const size_t[]){offsetof(struct dp_worker, rx_count), offsetof(struct dp_worker, rx_size)}}, + {"tx", 2, (const size_t[]){offsetof(struct dp_worker, tx_count), offsetof(struct dp_worker, tx_size)}}, + {"remote_rx", 1, (const size_t[]){offsetof(struct dp_worker, remote_rx_count)}}, + {"remote_tx", 1, (const size_t[]){offsetof(struct dp_worker, remote_tx_count)},}, + {"nic_rx", 2, (const size_t[]){offsetof(struct dp_worker, nic_rx_packets), offsetof(struct dp_worker, nic_rx_bytes)}}, + {"nic_tx", 2, (const size_t[]){offsetof(struct dp_worker, nic_tx_packets), offsetof(struct dp_worker, nic_tx_bytes)}}, + {"nic_rx_tx_errors", 2, (const size_t[]){offsetof(struct dp_worker, nic_rx_errors), offsetof(struct dp_worker, nic_tx_errors)}}, + {"nic_rx_nombuf", 1, (const size_t[]){offsetof(struct dp_worker, nic_rx_nombuf)}}, +}; + +uint64_t** +get_worker_field_ptr(struct dp_worker *worker, int info_index, int offset_index) { + return (uint64_t**)((char*)worker + worker_counter_info[info_index].offset[offset_index]); +} + +#define ARRAY_SIZE(arr) (size_t)(sizeof(arr) / sizeof((arr)[0])) + +static uint64_t +worker_counter_ids[ARRAY_SIZE(worker_counter_info)]; + int dataplane_worker_init( struct dataplane *dataplane, @@ -551,14 +629,14 @@ dataplane_worker_init( counter_registry_init( &dp_config->worker_counters, &dp_config->memory_context, 0 ); - - counter_registry_register(&dp_config->worker_counters, "iterations", 1); - - counter_registry_register(&dp_config->worker_counters, "rx", 2); - counter_registry_register(&dp_config->worker_counters, "tx", 2); - counter_registry_register(&dp_config->worker_counters, "remote_rx", 2); - - counter_registry_register(&dp_config->worker_counters, "remote_tx", 2); + + for (size_t i = 0; i < ARRAY_SIZE(worker_counter_info); ++i) { + worker_counter_ids[i] = counter_registry_register( + &dp_config->worker_counters, + worker_counter_info[i].name, + worker_counter_info[i].size + ); + } return 0; @@ -574,53 +652,18 @@ dataplane_worker_start(struct dataplane_worker *worker) { struct dp_worker *dp_worker = worker->dp_worker; struct dp_config *dp_config = worker->instance->dp_config; // FIXME: do not use hard-coded counter identifiers - dp_worker->iterations = counter_get_address( - 0, dp_worker->idx, ADDR_OF(&dp_config->worker_counter_storage) - ); - dp_worker->rx_count = - counter_get_address( - 1, - dp_worker->idx, - ADDR_OF(&dp_config->worker_counter_storage) - ) + - 0; - dp_worker->rx_size = counter_get_address( - 1, - dp_worker->idx, - ADDR_OF(&dp_config->worker_counter_storage) - ) + - 1; - - dp_worker->tx_count = - counter_get_address( - 2, - dp_worker->idx, - ADDR_OF(&dp_config->worker_counter_storage) - ) + - 0; - dp_worker->tx_size = counter_get_address( - 2, - dp_worker->idx, - ADDR_OF(&dp_config->worker_counter_storage) - ) + - 1; - - dp_worker->remote_rx_count = - counter_get_address( - 3, - dp_worker->idx, - ADDR_OF(&dp_config->worker_counter_storage) - ) + - 0; - - dp_worker->remote_tx_count = - counter_get_address( - 4, - dp_worker->idx, - ADDR_OF(&dp_config->worker_counter_storage) - ) + - 0; + for (size_t i = 0; i < ARRAY_SIZE(worker_counter_info); ++i) { + for (size_t j = 0; j < worker_counter_info[i].size; ++j) { + uint64_t **field_ptr = get_worker_field_ptr(dp_worker, i, j); + *field_ptr = counter_get_address( + worker_counter_ids[i], + dp_worker->idx, + ADDR_OF(&dp_config->worker_counter_storage) + ) + j; + } + } + pthread_attr_t wrk_th_attr; pthread_attr_init(&wrk_th_attr); diff --git a/lib/controlplane/agent/agent.c b/lib/controlplane/agent/agent.c index cbe065c04..329d1f2bf 100644 --- a/lib/controlplane/agent/agent.c +++ b/lib/controlplane/agent/agent.c @@ -1648,6 +1648,74 @@ yanet_get_device_counters( return list; } +struct counter_handle_list * +yanet_get_nic_counters( + struct dp_config *dp_config, + const char *device_name +) { + const char* query[] = { + "nic_rx", + "nic_tx", + "nic_rx_tx_errors", + "nic_rx_nombuf", + }; + int query_count = 4; + + struct cp_config *cp_config = ADDR_OF(&dp_config->cp_config); + cp_config_lock(cp_config); + struct cp_config_gen *cp_config_gen = + ADDR_OF(&cp_config->cp_config_gen); + + struct counter_registry *counter_registry; + struct counter_storage *counter_storage; + + struct counter_storage *cs = cp_config_gen_get_nic_counter_storage( + cp_config_gen, device_name + ); + + if (cs == NULL) { + cp_config_unlock(cp_config); + return NULL; + } + counter_storage = cs; + counter_registry = ADDR_OF(&counter_storage->registry); + + uint64_t count = counter_registry->count; + struct counter *names = ADDR_OF(&counter_registry->names); + + // FIXME: unlock is correct + cp_config_unlock(cp_config); + + struct counter_handle_list *list = (struct counter_handle_list *)malloc( + sizeof(struct counter_handle_list) + + sizeof(struct counter_handle) * count + ); + + if (list == NULL) + return NULL; + list->instance_count = + ADDR_OF(&counter_storage->allocator)->instance_count; + list->count = count; + struct counter_handle *handlers = list->counters; + + uint64_t out_idx = 0; + for (uint64_t idx = 0; idx < count; ++idx) { + if (!counter_name_matches_query( + names[idx].name, query, query_count + )) { + continue; + } + strtcpy(handlers[out_idx].name, names[idx].name, 60); + handlers[out_idx].size = names[idx].size; + handlers[out_idx].gen = names[idx].gen; + handlers[out_idx].value_handle = + counter_get_value_handle(idx, counter_storage); + out_idx++; + } + + return list; +} + struct counter_handle * yanet_get_counter(struct counter_handle_list *counters, uint64_t idx) { if (idx >= counters->count) diff --git a/lib/controlplane/config/zone.h b/lib/controlplane/config/zone.h index 379f3d54f..6fd3eb4dd 100644 --- a/lib/controlplane/config/zone.h +++ b/lib/controlplane/config/zone.h @@ -279,6 +279,13 @@ cp_config_gen_get_device_counter_storage( ); } +static inline struct counter_storage * +cp_config_gen_get_nic_counter_storage( + struct cp_config_gen *config_gen, const char *device_name +) { + return cp_config_gen_get_device_counter_storage(config_gen, device_name); +} + struct cp_module * cp_config_gen_lookup_module( struct cp_config_gen *config_gen, const char *type, const char *name diff --git a/lib/dataplane/config/zone.h b/lib/dataplane/config/zone.h index 1c6643145..a245505ae 100644 --- a/lib/dataplane/config/zone.h +++ b/lib/dataplane/config/zone.h @@ -62,6 +62,21 @@ struct dp_worker { struct rte_mempool *rx_mempool; uint8_t pad[24]; + + // trade-off: nic stats unload not often + // bcs put it in second cache line + uint64_t *nic_rx_packets; + uint64_t *nic_rx_bytes; + + uint64_t *nic_tx_packets; + uint64_t *nic_tx_bytes; + + uint64_t *nic_rx_errors; + uint64_t *nic_tx_errors; + + uint64_t *nic_rx_nombuf; + + uint8_t pad2[8]; }; struct dp_config { uint32_t instance_count; From 5a82397384d57bc6dc7d0a568eae4dd487663710 Mon Sep 17 00:00:00 2001 From: Kirill Faizullin Date: Tue, 28 Apr 2026 10:57:08 +0300 Subject: [PATCH 02/10] feat: impl collect per-rule metrics --- modules/forward/controlplane/backend.go | 4 + .../controlplane/forwardpb/forward.proto | 5 ++ modules/forward/controlplane/metrics.go | 87 +++++++++++++++++++ modules/forward/controlplane/service.go | 61 +++++++++++++ modules/forward/controlplane/service_test.go | 4 + 5 files changed, 161 insertions(+) create mode 100644 modules/forward/controlplane/metrics.go diff --git a/modules/forward/controlplane/backend.go b/modules/forward/controlplane/backend.go index f7d72c455..e116cd935 100644 --- a/modules/forward/controlplane/backend.go +++ b/modules/forward/controlplane/backend.go @@ -41,3 +41,7 @@ func (m *backend) UpdateModule(name string, rules []cforward.ForwardRule) (Modul func (m *backend) DeleteModule(name string) error { return m.agent.DeleteModuleConfig(name) } + +func (m *backend) Agent() FFIAgent { + return m.agent +} diff --git a/modules/forward/controlplane/forwardpb/forward.proto b/modules/forward/controlplane/forwardpb/forward.proto index e70d6574c..d28442a36 100644 --- a/modules/forward/controlplane/forwardpb/forward.proto +++ b/modules/forward/controlplane/forwardpb/forward.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package forwardpb; import "common/filterpb/filter.proto"; +import "common/commonpb/metric.proto"; option go_package = "github.com/yanet-platform/yanet2/modules/forward/controlplane/forwardpb;forwardpb"; @@ -77,3 +78,7 @@ message DeleteConfigRequest { } message DeleteConfigResponse { bool deleted = 1; } + +message GetMetricsRequest {} + +message GetMetricsResponse { repeated commonpb.Metric metrics = 1; } diff --git a/modules/forward/controlplane/metrics.go b/modules/forward/controlplane/metrics.go new file mode 100644 index 000000000..c577f8648 --- /dev/null +++ b/modules/forward/controlplane/metrics.go @@ -0,0 +1,87 @@ +package forward + +import ( + "github.com/yanet-platform/yanet2/common/commonpb" +) + +func (m *ForwardService) Metrics() ([]*commonpb.Metric, error) { + m.mu.Lock() + defer m.mu.Unlock() + return m.collectMetrics() +} + +func makeGauge(name string, value float64, labels ...*commonpb.Label) *commonpb.Metric { + return &commonpb.Metric{ + Name: name, + Labels: labels, + Value: &commonpb.Metric_Gauge{Gauge: value}, + } +} + +func makeCounter(name string, value uint64, labels ...*commonpb.Label) *commonpb.Metric { + return &commonpb.Metric{ + Name: name, + Labels: labels, + Value: &commonpb.Metric_Counter{Counter: value}, + } +} + +func (m *ForwardService) collectMetrics() ([]*commonpb.Metric, error) { + dpConfig := m.backend.Agent().DPConfig() + positions := dpConfig.AllModulePositions("acl") + + setCountersNames := make(map[string]struct{}, 0) + for _, config := range m.configs { + for _, rule := range config.rules { + setCountersNames[rule.Action.Counter] = struct{}{} + } + } + + result := make([]*commonpb.Metric, 0) + for _, pos := range positions { + configName := pos.ModuleName + + baseLabels := []*commonpb.Label{ + {Name: "config", Value: configName}, + {Name: "device", Value: pos.Device}, + {Name: "pipeline", Value: pos.Pipeline}, + {Name: "function", Value: pos.Function}, + {Name: "chain", Value: pos.Chain}, + } + + counters := dpConfig.ModuleCounters( + pos.Device, + pos.Pipeline, + pos.Function, + pos.Chain, + "acl", + configName, + nil, + ) + + for _, counter := range counters { + // Sum values across all workers + var cntPackets, bytes uint64 + for _, workerVals := range counter.Values { + if len(workerVals) > 0 { + cntPackets += workerVals[0] + } + if len(workerVals) > 1 { + bytes += workerVals[1] + } + } + + if cntPackets == 0 && bytes == 0 { + continue + } + + result = append(result, + makeCounter(counter.Name+"_packets", cntPackets, baseLabels...), + makeCounter(counter.Name+"_bytes", bytes, baseLabels...), + ) + + } + } + + return result, nil +} diff --git a/modules/forward/controlplane/service.go b/modules/forward/controlplane/service.go index 2eb8b9b03..225b71558 100644 --- a/modules/forward/controlplane/service.go +++ b/modules/forward/controlplane/service.go @@ -9,6 +9,7 @@ import ( "google.golang.org/grpc/status" "github.com/yanet-platform/yanet2/common/filterpb" + "github.com/yanet-platform/yanet2/controlplane/ffi" "github.com/yanet-platform/yanet2/modules/forward/bindings/go/cforward" "github.com/yanet-platform/yanet2/modules/forward/controlplane/forwardpb" ) @@ -25,6 +26,49 @@ type Backend interface { UpdateModule(name string, rules []cforward.ForwardRule) (ModuleHandle, error) // DeleteModule removes a module config. DeleteModule(name string) error + // Agent returns the FFI agent. + Agent() FFIAgent +} + +// TODO: delete dependence from ffi to interfaces +type ModuleAgent interface { + DeleteModuleConfig(configName string) error + UpdateModules(modules []ffi.ModuleConfig) error +} + +type PipelineAgent interface { + DeletePipeline(name string) error + UpdatePipeline(pipelineConfig ffi.PipelineConfig) error +} + +type FunctionAgent interface { + DeleteFunction(name string) error + UpdateFunction(functionConfig ffi.FunctionConfig) error +} + +type DeviceAgent interface { + UpdateDevices(devices []ffi.ShmDeviceConfig) error + UpdatePlainDevices(devices []ffi.DeviceConfig) error +} + +type FFIAgent interface { + DPAgent + CountersProvider +} + +type DPAgent interface { + ModuleAgent + PipelineAgent + FunctionAgent + DeviceAgent + TakeError() error + CleanError() + CleanUp() error + Close() error +} + +type CountersProvider interface { + DPConfig() *ffi.DPConfig } type forwardConfig struct { @@ -191,3 +235,20 @@ func (m *ForwardService) DeleteConfig(ctx context.Context, req *forwardpb.Delete return &forwardpb.DeleteConfigResponse{Deleted: true}, nil } + +func (m *ForwardService) GetMetrics( + ctx context.Context, + req *forwardpb.GetMetricsRequest, +) (*forwardpb.GetMetricsResponse, error) { + m.mu.Lock() + defer m.mu.Unlock() + + metrics, err := m.collectMetrics() + if err != nil { + return nil, err + } + + return &forwardpb.GetMetricsResponse{ + Metrics: metrics, + }, nil +} diff --git a/modules/forward/controlplane/service_test.go b/modules/forward/controlplane/service_test.go index 6669c0f5a..e86eef361 100644 --- a/modules/forward/controlplane/service_test.go +++ b/modules/forward/controlplane/service_test.go @@ -27,6 +27,10 @@ func (m *mockBackend) DeleteModule(name string) error { return nil } +func (m *mockBackend) Agent() forward.FFIAgent { + return nil +} + // Run with: go test -race func TestForwardServiceConcurrentAccess(t *testing.T) { svc := forward.NewForwardService(&mockBackend{}) From 9b6394aadc86e408e76c1a7a22231beb6509c8a6 Mon Sep 17 00:00:00 2001 From: Kirill Faizullin Date: Wed, 29 Apr 2026 10:17:11 +0300 Subject: [PATCH 03/10] feat: add new rpc method for metrics --- modules/forward/controlplane/forwardpb/forward.proto | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/forward/controlplane/forwardpb/forward.proto b/modules/forward/controlplane/forwardpb/forward.proto index d28442a36..c5272f99a 100644 --- a/modules/forward/controlplane/forwardpb/forward.proto +++ b/modules/forward/controlplane/forwardpb/forward.proto @@ -21,6 +21,8 @@ service ForwardService { // Allows to delete forward config if it is not referenced // by any pipeline. rpc DeleteConfig(DeleteConfigRequest) returns (DeleteConfigResponse); + + rpc GetMetrics(GetMetricsRequest) returns (GetMetricsResponse); } message Config { From 06891ebd978953709c1fc741c9198790e97a5310 Mon Sep 17 00:00:00 2001 From: Kirill Faizullin Date: Wed, 29 Apr 2026 10:18:17 +0300 Subject: [PATCH 04/10] expand backend api --- modules/forward/controlplane/service.go | 43 +------------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/modules/forward/controlplane/service.go b/modules/forward/controlplane/service.go index 225b71558..bdc50586a 100644 --- a/modules/forward/controlplane/service.go +++ b/modules/forward/controlplane/service.go @@ -27,48 +27,7 @@ type Backend interface { // DeleteModule removes a module config. DeleteModule(name string) error // Agent returns the FFI agent. - Agent() FFIAgent -} - -// TODO: delete dependence from ffi to interfaces -type ModuleAgent interface { - DeleteModuleConfig(configName string) error - UpdateModules(modules []ffi.ModuleConfig) error -} - -type PipelineAgent interface { - DeletePipeline(name string) error - UpdatePipeline(pipelineConfig ffi.PipelineConfig) error -} - -type FunctionAgent interface { - DeleteFunction(name string) error - UpdateFunction(functionConfig ffi.FunctionConfig) error -} - -type DeviceAgent interface { - UpdateDevices(devices []ffi.ShmDeviceConfig) error - UpdatePlainDevices(devices []ffi.DeviceConfig) error -} - -type FFIAgent interface { - DPAgent - CountersProvider -} - -type DPAgent interface { - ModuleAgent - PipelineAgent - FunctionAgent - DeviceAgent - TakeError() error - CleanError() - CleanUp() error - Close() error -} - -type CountersProvider interface { - DPConfig() *ffi.DPConfig + Agent() ffi.FFIAgent } type forwardConfig struct { From 9ce5297d1929fd5e1ca7e8b372e765a3aec8dd40 Mon Sep 17 00:00:00 2001 From: Kirill Faizullin Date: Wed, 29 Apr 2026 10:20:04 +0300 Subject: [PATCH 05/10] added interfaces for agent and partition api --- controlplane/ffi/agent.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/controlplane/ffi/agent.go b/controlplane/ffi/agent.go index b0ffb8b0b..c41689b0a 100644 --- a/controlplane/ffi/agent.go +++ b/controlplane/ffi/agent.go @@ -77,6 +77,42 @@ func (m ShmDeviceConfig) AsRawPtr() unsafe.Pointer { return unsafe.Pointer(m.ptr) } +type FFIAgent interface { + DPAgent + CountersProvider +} + +type DPAgent interface { + ModuleAgent + FunctionAgent + PipelineAgent + DeviceAgent + TakeError() error + CleanError() + CleanUp() error + Close() error +} + +type ModuleAgent interface { + UpdateModules(modules []ModuleConfig) error + DeleteModuleConfig(configName string) error +} + +type FunctionAgent interface { + UpdateFunction(functionConfig FunctionConfig) error + DeleteFunction(name string) error +} + +type PipelineAgent interface { + UpdatePipeline(pipelineConfig PipelineConfig) error + DeletePipeline(name string) error +} + +type DeviceAgent interface { + UpdatePlainDevices(devices []DeviceConfig) error + UpdateDevices(devices []ShmDeviceConfig) error +} + type Agent struct { name string ptr *C.struct_agent From 620ac9fe6188183222c3c2639f2852e2f809513f Mon Sep 17 00:00:00 2001 From: Kirill Faizullin Date: Wed, 29 Apr 2026 10:53:29 +0300 Subject: [PATCH 06/10] added some interfaces --- controlplane/ffi/agent.go | 2 +- controlplane/ffi/shm.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/controlplane/ffi/agent.go b/controlplane/ffi/agent.go index c41689b0a..d60c509fe 100644 --- a/controlplane/ffi/agent.go +++ b/controlplane/ffi/agent.go @@ -79,7 +79,7 @@ func (m ShmDeviceConfig) AsRawPtr() unsafe.Pointer { type FFIAgent interface { DPAgent - CountersProvider + DPDataProvider } type DPAgent interface { diff --git a/controlplane/ffi/shm.go b/controlplane/ffi/shm.go index a5b73d32a..121a6b597 100644 --- a/controlplane/ffi/shm.go +++ b/controlplane/ffi/shm.go @@ -18,6 +18,37 @@ import ( "github.com/c2h5oh/datasize" ) +type DPDataProvider interface { + DPConfig() DPConfig +} + +type DPConfig interface { + DPObserver + CounterAggregator + AllModulePositions() +} + +type DPObserver interface { + NumaIdx() uint32 + WorkerCount() uint32 + Modules() []DPModule + CPConfigs() []CPConfig + Functions() []Function + Pipelines() []Pipeline + Agents() []Agent + Devices() []DeviceInfo +} + +type CounterAggregator interface { + DeviceCounters() + PipelineCounters() + FunctionCounters() + ChainCounters() + ModuleCounters() + PerformanceCounters() + NicCounters() +} + // SharedMemory represents a handle to YANET shared memory segment. type SharedMemory struct { ptr *C.struct_yanet_shm From 9396b7b3147824bba79403644de2e295a029bbae Mon Sep 17 00:00:00 2001 From: Kirill Faizullin Date: Wed, 29 Apr 2026 11:05:51 +0300 Subject: [PATCH 07/10] fix interface and refactor for using impl --- controlplane/ffi/agent.go | 4 +- controlplane/ffi/shm.go | 62 +++++++++---------- .../internal/gateway/inspect_service.go | 14 ++--- modules/balancer/agent/go/agent.go | 4 +- modules/balancer/agent/go/ffi/agent.go | 2 +- 5 files changed, 43 insertions(+), 43 deletions(-) diff --git a/controlplane/ffi/agent.go b/controlplane/ffi/agent.go index d60c509fe..e52e7621b 100644 --- a/controlplane/ffi/agent.go +++ b/controlplane/ffi/agent.go @@ -206,8 +206,8 @@ func (m *Agent) UpdateModules(modules []ModuleConfig) error { return nil } -func (m *Agent) DPConfig() *DPConfig { - return &DPConfig{ +func (m *Agent) DPConfig() DPConfig { + return &DPConfigImpl{ ptr: C.agent_dp_config(m.ptr), } } diff --git a/controlplane/ffi/shm.go b/controlplane/ffi/shm.go index 121a6b597..4af1a273b 100644 --- a/controlplane/ffi/shm.go +++ b/controlplane/ffi/shm.go @@ -25,7 +25,7 @@ type DPDataProvider interface { type DPConfig interface { DPObserver CounterAggregator - AllModulePositions() + AllModulePositions(string) []ModuleReference } type DPObserver interface { @@ -35,18 +35,18 @@ type DPObserver interface { CPConfigs() []CPConfig Functions() []Function Pipelines() []Pipeline - Agents() []Agent + Agents() []AgentInfo Devices() []DeviceInfo } type CounterAggregator interface { - DeviceCounters() - PipelineCounters() - FunctionCounters() - ChainCounters() - ModuleCounters() - PerformanceCounters() - NicCounters() + DeviceCounters(deviceName string) []CounterInfo + PipelineCounters(deviceName string, pipelineName string) []CounterInfo + FunctionCounters(deviceName string, pipelineName string, functionName string) []CounterInfo + ChainCounters(deviceName string, pipelineName string, functionName string, chainName string) []CounterInfo + ModuleCounters(deviceName string, pipelineName string, functionName string, chainName string, moduleType string, moduleName string, counterQuery []string) []CounterInfo + PerformanceCounters(deviceName string, pipelineName string, functionName string, chainName string, moduleType string, moduleName string) (*PerformanceCounters, error) + NicCounters(deivceName string) []CounterInfo } // SharedMemory represents a handle to YANET shared memory segment. @@ -93,10 +93,10 @@ func (m *SharedMemory) AsRawPtr() unsafe.Pointer { } // DPConfig gets configuration of the dataplane instance from shared memory. -func (m *SharedMemory) DPConfig(instanceIdx uint32) *DPConfig { +func (m *SharedMemory) DPConfig(instanceIdx uint32) DPConfig { ptr := C.yanet_shm_dp_config(m.ptr, C.uint32_t(instanceIdx)) - return &DPConfig{ptr: ptr} + return &DPConfigImpl{ptr: ptr} } // AgentAttach attaches a module agent to shared memory on the dataplane instance. @@ -162,24 +162,24 @@ func (m *SharedMemory) AgentsAttach( } // DPConfig represents a handle to dataplane configuration. -type DPConfig struct { +type DPConfigImpl struct { ptr *C.struct_dp_config } -func NewDPConfigFromRaw(ptr unsafe.Pointer) *DPConfig { - return &DPConfig{ptr: (*C.struct_dp_config)(ptr)} +func NewDPConfigFromRaw(ptr unsafe.Pointer) *DPConfigImpl { + return &DPConfigImpl{ptr: (*C.struct_dp_config)(ptr)} } -func (m *DPConfig) NumaIdx() uint32 { +func (m *DPConfigImpl) NumaIdx() uint32 { return uint32(C.dataplane_instance_numa_idx(m.ptr)) } -func (m *DPConfig) WorkerCount() uint32 { +func (m *DPConfigImpl) WorkerCount() uint32 { return uint32(C.dataplane_instance_worker_count(m.ptr)) } // Modules returns a list of dataplane modules available. -func (m *DPConfig) Modules() []DPModule { +func (m *DPConfigImpl) Modules() []DPModule { ptr := C.yanet_get_dp_module_list_info(m.ptr) defer C.dp_module_list_info_free(ptr) @@ -200,7 +200,7 @@ func (m *DPConfig) Modules() []DPModule { return out } -func (m *DPConfig) CPConfigs() []CPConfig { +func (m *DPConfigImpl) CPConfigs() []CPConfig { cpModulesListInfo := C.yanet_get_cp_module_list_info(m.ptr) defer C.cp_module_list_info_free(cpModulesListInfo) @@ -236,7 +236,7 @@ type Function struct { } // Functions returns all functions configurations from the dataplane. -func (m *DPConfig) Functions() []Function { +func (m *DPConfigImpl) Functions() []Function { functionListInfo := C.yanet_get_cp_function_list_info(m.ptr) defer C.cp_function_list_info_free(functionListInfo) @@ -277,7 +277,7 @@ func (m *DPConfig) Functions() []Function { } // Pipelines returns all pipeline configurations from the dataplane. -func (m *DPConfig) Pipelines() []Pipeline { +func (m *DPConfigImpl) Pipelines() []Pipeline { pipelineListInfo := C.yanet_get_cp_pipeline_list_info(m.ptr) defer C.cp_pipeline_list_info_free(pipelineListInfo) @@ -304,7 +304,7 @@ func (m *DPConfig) Pipelines() []Pipeline { } // Agents returns all agent information from the dataplane. -func (m *DPConfig) Agents() []AgentInfo { +func (m *DPConfigImpl) Agents() []AgentInfo { agentListInfo := C.yanet_get_cp_agent_list_info(m.ptr) defer C.cp_agent_list_info_free(agentListInfo) @@ -410,7 +410,7 @@ type DeviceInfo struct { } // Devices returns all device information from the dataplane. -func (m *DPConfig) Devices() []DeviceInfo { +func (m *DPConfigImpl) Devices() []DeviceInfo { deviceListInfo := C.yanet_get_cp_device_list_info(m.ptr) if deviceListInfo == nil { return nil @@ -472,7 +472,7 @@ type CounterInfo struct { Values [][]uint64 } -func (m *DPConfig) encodeCounters( +func (m *DPConfigImpl) encodeCounters( counters *C.struct_counter_handle_list, ) []CounterInfo { res := make([]CounterInfo, 0) @@ -507,7 +507,7 @@ func (m *DPConfig) encodeCounters( return res } -func (m *DPConfig) DeviceCounters( +func (m *DPConfigImpl) DeviceCounters( deviceName string, ) []CounterInfo { cDeviceName := C.CString(deviceName) @@ -523,7 +523,7 @@ func (m *DPConfig) DeviceCounters( } // PipelineCounters returns pipeline counters -func (m *DPConfig) PipelineCounters( +func (m *DPConfigImpl) PipelineCounters( deviceName string, pipelineName string, ) []CounterInfo { @@ -541,7 +541,7 @@ func (m *DPConfig) PipelineCounters( return m.encodeCounters(counters) } -func (m *DPConfig) FunctionCounters( +func (m *DPConfigImpl) FunctionCounters( deviceName string, pipelineName string, functionName string, @@ -567,7 +567,7 @@ func (m *DPConfig) FunctionCounters( return m.encodeCounters(counters) } -func (m *DPConfig) ChainCounters( +func (m *DPConfigImpl) ChainCounters( deviceName string, pipelineName string, functionName string, @@ -600,7 +600,7 @@ func (m *DPConfig) ChainCounters( // ModuleCounters returns module counters, optionally filtered by name. // // If counterQuery is nil or empty, returns all counters. -func (m *DPConfig) ModuleCounters( +func (m *DPConfigImpl) ModuleCounters( deviceName string, pipelineName string, functionName string, @@ -687,7 +687,7 @@ type PerformanceCounters struct { // Performance counters provide detailed timing and batch processing statistics // for module execution, including mean latency and latency distribution across // different batch sizes, as well as tx/rx packet and byte counters. -func (m *DPConfig) PerformanceCounters( +func (m *DPConfigImpl) PerformanceCounters( deviceName string, pipelineName string, functionName string, @@ -786,7 +786,7 @@ func (m *DPConfig) PerformanceCounters( return result, nil } -func (m *DPConfig) NicCounters(deviceName string) []CounterInfo { +func (m *DPConfigImpl) NicCounters(deivceName string) []CounterInfo { cDeviceName := C.CString(deviceName) defer C.free(unsafe.Pointer(cDeviceName)) counters := C.yanet_get_nic_counters(m.ptr, cDeviceName) @@ -808,7 +808,7 @@ type ModuleReference struct { ModuleName string } -func (m *DPConfig) AllModulePositions(moduleType string) []ModuleReference { +func (m *DPConfigImpl) AllModulePositions(moduleType string) []ModuleReference { deviceList := m.Devices() pipelineList := m.Pipelines() diff --git a/controlplane/internal/gateway/inspect_service.go b/controlplane/internal/gateway/inspect_service.go index efb116dfc..0e2fbc371 100644 --- a/controlplane/internal/gateway/inspect_service.go +++ b/controlplane/internal/gateway/inspect_service.go @@ -47,7 +47,7 @@ func (m *InspectService) Inspect( return response, nil } -func (m *InspectService) dpModules(dpConfig *ffi.DPConfig) []*ynpb.DPModuleInfo { +func (m *InspectService) dpModules(dpConfig ffi.DPConfig) []*ynpb.DPModuleInfo { modules := dpConfig.Modules() out := make([]*ynpb.DPModuleInfo, len(modules)) @@ -60,7 +60,7 @@ func (m *InspectService) dpModules(dpConfig *ffi.DPConfig) []*ynpb.DPModuleInfo return out } -func (m *InspectService) cpConfigs(dpConfig *ffi.DPConfig) []*ynpb.CPConfigInfo { +func (m *InspectService) cpConfigs(dpConfig ffi.DPConfig) []*ynpb.CPConfigInfo { configs := dpConfig.CPConfigs() out := make([]*ynpb.CPConfigInfo, len(configs)) @@ -75,7 +75,7 @@ func (m *InspectService) cpConfigs(dpConfig *ffi.DPConfig) []*ynpb.CPConfigInfo return out } -func (m *InspectService) functions(dpConfig *ffi.DPConfig) []*ynpb.FunctionInfo { +func (m *InspectService) functions(dpConfig ffi.DPConfig) []*ynpb.FunctionInfo { functions := dpConfig.Functions() if len(functions) == 0 { return nil @@ -109,7 +109,7 @@ func (m *InspectService) functions(dpConfig *ffi.DPConfig) []*ynpb.FunctionInfo return out } -func (m *InspectService) pipelines(dpConfig *ffi.DPConfig) []*ynpb.PipelineInfo { +func (m *InspectService) pipelines(dpConfig ffi.DPConfig) []*ynpb.PipelineInfo { pipelines := dpConfig.Pipelines() out := make([]*ynpb.PipelineInfo, len(pipelines)) @@ -128,7 +128,7 @@ func (m *InspectService) pipelines(dpConfig *ffi.DPConfig) []*ynpb.PipelineInfo return out } -func (m *InspectService) agents(dpConfig *ffi.DPConfig) []*ynpb.AgentInfo { +func (m *InspectService) agents(dpConfig ffi.DPConfig) []*ynpb.AgentInfo { agents := dpConfig.Agents() out := make([]*ynpb.AgentInfo, len(agents)) @@ -154,7 +154,7 @@ func (m *InspectService) agents(dpConfig *ffi.DPConfig) []*ynpb.AgentInfo { return out } -func (m *InspectService) devices(dpConfig *ffi.DPConfig) []*ynpb.DeviceInfo { +func (m *InspectService) devices(dpConfig ffi.DPConfig) []*ynpb.DeviceInfo { devices := dpConfig.Devices() if len(devices) == 0 { return nil @@ -189,6 +189,6 @@ func (m *InspectService) devices(dpConfig *ffi.DPConfig) []*ynpb.DeviceInfo { return out } -func (m *InspectService) numaIdx(dpConfig *ffi.DPConfig) uint32 { +func (m *InspectService) numaIdx(dpConfig ffi.DPConfig) uint32 { return dpConfig.NumaIdx() } diff --git a/modules/balancer/agent/go/agent.go b/modules/balancer/agent/go/agent.go index cb06d0673..25043f82f 100644 --- a/modules/balancer/agent/go/agent.go +++ b/modules/balancer/agent/go/agent.go @@ -143,7 +143,7 @@ func (a *BalancerAgent) Inspect() *balancerpb.AgentInspect { } func (a *BalancerAgent) Metrics() ([]*commonpb.Metric, error) { - dpConfig := a.handle.DPConfig() + dpConfig := *a.handle.DPConfig() positions := dpConfig.AllModulePositions("balancer") managers := make([]*BalancerManager, 0, len(positions)) @@ -207,7 +207,7 @@ func (a *BalancerAgent) StatsEntries( name *string, refFilter *balancerpb.PacketHandlerRef, ) ([]*balancerpb.StatsEntry, error) { - dpConfig := a.handle.DPConfig() + dpConfig := *a.handle.DPConfig() positions := dpConfig.AllModulePositions("balancer") // Snapshot managers under lock to avoid holding agent mutex during per-position stats reads. diff --git a/modules/balancer/agent/go/ffi/agent.go b/modules/balancer/agent/go/ffi/agent.go index 975940b04..4071b06a9 100644 --- a/modules/balancer/agent/go/ffi/agent.go +++ b/modules/balancer/agent/go/ffi/agent.go @@ -109,7 +109,7 @@ func (a *BalancerAgent) Inspect() *AgentInspect { return inspect } -func (a *BalancerAgent) DPConfig() *yanet.DPConfig { +func (a *BalancerAgent) DPConfig() yanet.DPConfig { dpConfig := C.balancer_agent_dp_config(a.handle) return yanet.NewDPConfigFromRaw(unsafe.Pointer(dpConfig)) } From b433d1546ba63f703ef0f72277a8284c943fb4f4 Mon Sep 17 00:00:00 2001 From: Kirill Faizullin Date: Wed, 29 Apr 2026 11:10:17 +0300 Subject: [PATCH 08/10] fix compilations problems --- controlplane/ffi/shm.go | 2 +- modules/balancer/agent/go/agent.go | 4 ++-- modules/forward/controlplane/backend.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/controlplane/ffi/shm.go b/controlplane/ffi/shm.go index 4af1a273b..095242874 100644 --- a/controlplane/ffi/shm.go +++ b/controlplane/ffi/shm.go @@ -786,7 +786,7 @@ func (m *DPConfigImpl) PerformanceCounters( return result, nil } -func (m *DPConfigImpl) NicCounters(deivceName string) []CounterInfo { +func (m *DPConfigImpl) NicCounters(deviceName string) []CounterInfo { cDeviceName := C.CString(deviceName) defer C.free(unsafe.Pointer(cDeviceName)) counters := C.yanet_get_nic_counters(m.ptr, cDeviceName) diff --git a/modules/balancer/agent/go/agent.go b/modules/balancer/agent/go/agent.go index 25043f82f..cb06d0673 100644 --- a/modules/balancer/agent/go/agent.go +++ b/modules/balancer/agent/go/agent.go @@ -143,7 +143,7 @@ func (a *BalancerAgent) Inspect() *balancerpb.AgentInspect { } func (a *BalancerAgent) Metrics() ([]*commonpb.Metric, error) { - dpConfig := *a.handle.DPConfig() + dpConfig := a.handle.DPConfig() positions := dpConfig.AllModulePositions("balancer") managers := make([]*BalancerManager, 0, len(positions)) @@ -207,7 +207,7 @@ func (a *BalancerAgent) StatsEntries( name *string, refFilter *balancerpb.PacketHandlerRef, ) ([]*balancerpb.StatsEntry, error) { - dpConfig := *a.handle.DPConfig() + dpConfig := a.handle.DPConfig() positions := dpConfig.AllModulePositions("balancer") // Snapshot managers under lock to avoid holding agent mutex during per-position stats reads. diff --git a/modules/forward/controlplane/backend.go b/modules/forward/controlplane/backend.go index e116cd935..64dc61d2e 100644 --- a/modules/forward/controlplane/backend.go +++ b/modules/forward/controlplane/backend.go @@ -42,6 +42,6 @@ func (m *backend) DeleteModule(name string) error { return m.agent.DeleteModuleConfig(name) } -func (m *backend) Agent() FFIAgent { +func (m *backend) Agent() ffi.FFIAgent { return m.agent } From 9ec1b69c72efe4be28e5ed1c46e531efeb35829a Mon Sep 17 00:00:00 2001 From: Kirill Faizullin Date: Wed, 29 Apr 2026 11:40:03 +0300 Subject: [PATCH 09/10] retract nic metrics changes from this branch --- controlplane/ffi/shm.go | 13 --- controlplane/ynpb/counters.proto | 4 - dataplane/dataplane.c | 46 +++++----- dataplane/worker.c | 151 +++++++++++-------------------- lib/controlplane/agent/agent.c | 68 -------------- lib/controlplane/config/zone.h | 7 -- lib/dataplane/config/zone.h | 15 --- 7 files changed, 77 insertions(+), 227 deletions(-) diff --git a/controlplane/ffi/shm.go b/controlplane/ffi/shm.go index 095242874..882b9aca0 100644 --- a/controlplane/ffi/shm.go +++ b/controlplane/ffi/shm.go @@ -786,19 +786,6 @@ func (m *DPConfigImpl) PerformanceCounters( return result, nil } -func (m *DPConfigImpl) NicCounters(deviceName string) []CounterInfo { - cDeviceName := C.CString(deviceName) - defer C.free(unsafe.Pointer(cDeviceName)) - counters := C.yanet_get_nic_counters(m.ptr, cDeviceName) - defer C.yanet_counter_handle_list_free(counters) - - if counters == nil { - return nil - } - - return m.encodeCounters(counters) -} - type ModuleReference struct { Device string Pipeline string diff --git a/controlplane/ynpb/counters.proto b/controlplane/ynpb/counters.proto index 153717201..97c8cd365 100644 --- a/controlplane/ynpb/counters.proto +++ b/controlplane/ynpb/counters.proto @@ -11,15 +11,11 @@ service CountersService { rpc Function(FunctionCountersRequest) returns (CountersResponse) {} rpc Chain(ChainCountersRequest) returns (CountersResponse) {} rpc Module(ModuleCountersRequest) returns (CountersResponse) {} - rpc Nic(NicCounterRequest) returns (CountersResponse) {} rpc Perf(PerfCountersRequest) returns (PerfCountersResponse) {} } message DeviceCountersRequest { string device = 1; } -message NicCounterRequest { string device = 1; } - - message PipelineCountersRequest { string device = 1; string pipeline = 2; diff --git a/dataplane/dataplane.c b/dataplane/dataplane.c index ef5c07830..14d3b4e80 100644 --- a/dataplane/dataplane.c +++ b/dataplane/dataplane.c @@ -617,11 +617,11 @@ stat_thread(void *arg) { struct rte_eth_xstat_name names[4096]; struct rte_eth_xstat xstats0[dataplane->device_count][4096]; - // struct rte_eth_stats stats0[dataplane->device_count]; + struct rte_eth_stats stats0[dataplane->device_count]; for (uint16_t idx = 0; idx < dataplane->device_count; ++idx) { - // rte_eth_stats_get( - // dataplane->devices[idx].port_id, &stats0[idx] - // ); + rte_eth_stats_get( + dataplane->devices[idx].port_id, &stats0[idx] + ); rte_eth_xstats_get( dataplane->devices[idx].port_id, xstats0[idx], 4096 ); @@ -631,25 +631,25 @@ stat_thread(void *arg) { sleep(1); for (uint16_t idx = 0; idx < dataplane->device_count; ++idx) { - // struct rte_eth_stats stats1; - // rte_eth_stats_get( - // dataplane->devices[idx].port_id, &stats1 - // ); - // fprintf(log, - // "dev %u ib %li ob %li ip %li op %li ie %li oe " - // "%li\n", - // idx, - // (int64_t)(stats1.ibytes - stats0[idx].ibytes), - // (int64_t)(stats1.obytes - stats0[idx].obytes), - // (int64_t)(stats1.ipackets - stats0[idx].ipackets - // ), - // (int64_t)(stats1.opackets - stats0[idx].opackets - // ), - // (int64_t)(stats1.ierrors - stats0[idx].ierrors), - // (int64_t)(stats1.oerrors - stats0[idx].oerrors) - // ); - - // memcpy(&stats0[idx], &stats1, sizeof(stats1)); + struct rte_eth_stats stats1; + rte_eth_stats_get( + dataplane->devices[idx].port_id, &stats1 + ); + fprintf(log, + "dev %u ib %li ob %li ip %li op %li ie %li oe " + "%li\n", + idx, + (int64_t)(stats1.ibytes - stats0[idx].ibytes), + (int64_t)(stats1.obytes - stats0[idx].obytes), + (int64_t)(stats1.ipackets - stats0[idx].ipackets + ), + (int64_t)(stats1.opackets - stats0[idx].opackets + ), + (int64_t)(stats1.ierrors - stats0[idx].ierrors), + (int64_t)(stats1.oerrors - stats0[idx].oerrors) + ); + + memcpy(&stats0[idx], &stats1, sizeof(stats1)); struct rte_eth_xstat xstats1[4096]; rte_eth_xstats_get_names( diff --git a/dataplane/worker.c b/dataplane/worker.c index 5724cdcfd..60cc8c7cf 100644 --- a/dataplane/worker.c +++ b/dataplane/worker.c @@ -55,8 +55,6 @@ #include -#define NIC_STATS_FREAQUENCY 1000 - static void worker_read(struct dataplane_worker *worker, struct packet_list *packets) { struct worker_read_ctx *ctx = &worker->read_ctx; @@ -273,52 +271,6 @@ worker_write(struct dataplane_worker *worker, struct packet_list *packets) { } } -struct nic_stat { - uint64_t ibytes; - uint64_t obytes; - uint64_t ipackets; - uint64_t opackets; - uint64_t ierrors; - uint64_t oerrors; - uint64_t rx_nombuf; -}; - -void worker_unload_nic_stats(struct dataplane_worker *worker) { - struct rte_eth_stats stats1; - struct dp_worker *dp_worker = worker->dp_worker; - - // const struct nic_stat stats0 = { - // .ibytes = *dp_worker->nic_rx_bytes, - // .obytes = *dp_worker->nic_tx_bytes, - // .ipackets = *dp_worker->nic_rx_packets, - // .opackets = *dp_worker->nic_tx_packets, - // .ierrors = *dp_worker->nic_rx_errors, - // .oerrors = *dp_worker->nic_tx_errors, - // .rx_nombuf = *dp_worker->nic_rx_nombuf - // }; - - - rte_eth_stats_get(worker->port_id, &stats1); - - // struct nic_stat diff = { - // .ibytes = stats1.ibytes - stats0.ibytes, - // .obytes = stats1.obytes - stats0.obytes, - // .ipackets = stats1.ipackets - stats0.ipackets, - // .opackets = stats1.opackets - stats0.opackets, - // .ierrors = stats1.ierrors - stats0.ierrors, - // .oerrors = stats1.oerrors - stats0.oerrors, - // .rx_nombuf = stats1.rx_nombuf - stats0.rx_nombuf - // }; - - *dp_worker->nic_rx_bytes = stats1.ibytes; - *dp_worker->nic_tx_bytes = stats1.obytes; - *dp_worker->nic_rx_packets = stats1.ipackets; - *dp_worker->nic_tx_packets = stats1.opackets; - *dp_worker->nic_rx_errors = stats1.ierrors; - *dp_worker->nic_tx_errors = stats1.oerrors; - *dp_worker->nic_rx_nombuf = stats1.rx_nombuf; -} - static void worker_loop_round(struct dataplane_worker *worker) { // Initialize current worker time @@ -360,11 +312,7 @@ worker_loop_round(struct dataplane_worker *worker) { uint64_t device_count = cp_config_gen->device_registry.registry.capacity; - uint64_t iterations = 0; - while (1) { - iterations = (iterations + 1) % NIC_STATS_FREAQUENCY; - if (iterations == 0) worker_unload_nic_stats(worker); struct packet_front schedule_input[device_count]; for (uint64_t idx = 0; idx < device_count; ++idx) @@ -458,32 +406,6 @@ worker_thread_start(void *arg) { return NULL; } -static const struct { - const char *name; - uint64_t size; - const size_t *offset; -} worker_counter_info[] = { - {"iterations", 1, (const size_t[]){offsetof(struct dp_worker, iterations)}}, - {"rx", 2, (const size_t[]){offsetof(struct dp_worker, rx_count), offsetof(struct dp_worker, rx_size)}}, - {"tx", 2, (const size_t[]){offsetof(struct dp_worker, tx_count), offsetof(struct dp_worker, tx_size)}}, - {"remote_rx", 1, (const size_t[]){offsetof(struct dp_worker, remote_rx_count)}}, - {"remote_tx", 1, (const size_t[]){offsetof(struct dp_worker, remote_tx_count)},}, - {"nic_rx", 2, (const size_t[]){offsetof(struct dp_worker, nic_rx_packets), offsetof(struct dp_worker, nic_rx_bytes)}}, - {"nic_tx", 2, (const size_t[]){offsetof(struct dp_worker, nic_tx_packets), offsetof(struct dp_worker, nic_tx_bytes)}}, - {"nic_rx_tx_errors", 2, (const size_t[]){offsetof(struct dp_worker, nic_rx_errors), offsetof(struct dp_worker, nic_tx_errors)}}, - {"nic_rx_nombuf", 1, (const size_t[]){offsetof(struct dp_worker, nic_rx_nombuf)}}, -}; - -uint64_t** -get_worker_field_ptr(struct dp_worker *worker, int info_index, int offset_index) { - return (uint64_t**)((char*)worker + worker_counter_info[info_index].offset[offset_index]); -} - -#define ARRAY_SIZE(arr) (size_t)(sizeof(arr) / sizeof((arr)[0])) - -static uint64_t -worker_counter_ids[ARRAY_SIZE(worker_counter_info)]; - int dataplane_worker_init( struct dataplane *dataplane, @@ -629,14 +551,14 @@ dataplane_worker_init( counter_registry_init( &dp_config->worker_counters, &dp_config->memory_context, 0 ); - - for (size_t i = 0; i < ARRAY_SIZE(worker_counter_info); ++i) { - worker_counter_ids[i] = counter_registry_register( - &dp_config->worker_counters, - worker_counter_info[i].name, - worker_counter_info[i].size - ); - } + + counter_registry_register(&dp_config->worker_counters, "iterations", 1); + + counter_registry_register(&dp_config->worker_counters, "rx", 2); + counter_registry_register(&dp_config->worker_counters, "tx", 2); + counter_registry_register(&dp_config->worker_counters, "remote_rx", 2); + + counter_registry_register(&dp_config->worker_counters, "remote_tx", 2); return 0; @@ -652,18 +574,53 @@ dataplane_worker_start(struct dataplane_worker *worker) { struct dp_worker *dp_worker = worker->dp_worker; struct dp_config *dp_config = worker->instance->dp_config; // FIXME: do not use hard-coded counter identifiers + dp_worker->iterations = counter_get_address( + 0, dp_worker->idx, ADDR_OF(&dp_config->worker_counter_storage) + ); - for (size_t i = 0; i < ARRAY_SIZE(worker_counter_info); ++i) { - for (size_t j = 0; j < worker_counter_info[i].size; ++j) { - uint64_t **field_ptr = get_worker_field_ptr(dp_worker, i, j); - *field_ptr = counter_get_address( - worker_counter_ids[i], - dp_worker->idx, - ADDR_OF(&dp_config->worker_counter_storage) - ) + j; - } - } - + dp_worker->rx_count = + counter_get_address( + 1, + dp_worker->idx, + ADDR_OF(&dp_config->worker_counter_storage) + ) + + 0; + dp_worker->rx_size = counter_get_address( + 1, + dp_worker->idx, + ADDR_OF(&dp_config->worker_counter_storage) + ) + + 1; + + dp_worker->tx_count = + counter_get_address( + 2, + dp_worker->idx, + ADDR_OF(&dp_config->worker_counter_storage) + ) + + 0; + dp_worker->tx_size = counter_get_address( + 2, + dp_worker->idx, + ADDR_OF(&dp_config->worker_counter_storage) + ) + + 1; + + dp_worker->remote_rx_count = + counter_get_address( + 3, + dp_worker->idx, + ADDR_OF(&dp_config->worker_counter_storage) + ) + + 0; + + dp_worker->remote_tx_count = + counter_get_address( + 4, + dp_worker->idx, + ADDR_OF(&dp_config->worker_counter_storage) + ) + + 0; pthread_attr_t wrk_th_attr; pthread_attr_init(&wrk_th_attr); diff --git a/lib/controlplane/agent/agent.c b/lib/controlplane/agent/agent.c index 329d1f2bf..cbe065c04 100644 --- a/lib/controlplane/agent/agent.c +++ b/lib/controlplane/agent/agent.c @@ -1648,74 +1648,6 @@ yanet_get_device_counters( return list; } -struct counter_handle_list * -yanet_get_nic_counters( - struct dp_config *dp_config, - const char *device_name -) { - const char* query[] = { - "nic_rx", - "nic_tx", - "nic_rx_tx_errors", - "nic_rx_nombuf", - }; - int query_count = 4; - - struct cp_config *cp_config = ADDR_OF(&dp_config->cp_config); - cp_config_lock(cp_config); - struct cp_config_gen *cp_config_gen = - ADDR_OF(&cp_config->cp_config_gen); - - struct counter_registry *counter_registry; - struct counter_storage *counter_storage; - - struct counter_storage *cs = cp_config_gen_get_nic_counter_storage( - cp_config_gen, device_name - ); - - if (cs == NULL) { - cp_config_unlock(cp_config); - return NULL; - } - counter_storage = cs; - counter_registry = ADDR_OF(&counter_storage->registry); - - uint64_t count = counter_registry->count; - struct counter *names = ADDR_OF(&counter_registry->names); - - // FIXME: unlock is correct - cp_config_unlock(cp_config); - - struct counter_handle_list *list = (struct counter_handle_list *)malloc( - sizeof(struct counter_handle_list) + - sizeof(struct counter_handle) * count - ); - - if (list == NULL) - return NULL; - list->instance_count = - ADDR_OF(&counter_storage->allocator)->instance_count; - list->count = count; - struct counter_handle *handlers = list->counters; - - uint64_t out_idx = 0; - for (uint64_t idx = 0; idx < count; ++idx) { - if (!counter_name_matches_query( - names[idx].name, query, query_count - )) { - continue; - } - strtcpy(handlers[out_idx].name, names[idx].name, 60); - handlers[out_idx].size = names[idx].size; - handlers[out_idx].gen = names[idx].gen; - handlers[out_idx].value_handle = - counter_get_value_handle(idx, counter_storage); - out_idx++; - } - - return list; -} - struct counter_handle * yanet_get_counter(struct counter_handle_list *counters, uint64_t idx) { if (idx >= counters->count) diff --git a/lib/controlplane/config/zone.h b/lib/controlplane/config/zone.h index 6fd3eb4dd..379f3d54f 100644 --- a/lib/controlplane/config/zone.h +++ b/lib/controlplane/config/zone.h @@ -279,13 +279,6 @@ cp_config_gen_get_device_counter_storage( ); } -static inline struct counter_storage * -cp_config_gen_get_nic_counter_storage( - struct cp_config_gen *config_gen, const char *device_name -) { - return cp_config_gen_get_device_counter_storage(config_gen, device_name); -} - struct cp_module * cp_config_gen_lookup_module( struct cp_config_gen *config_gen, const char *type, const char *name diff --git a/lib/dataplane/config/zone.h b/lib/dataplane/config/zone.h index a245505ae..1c6643145 100644 --- a/lib/dataplane/config/zone.h +++ b/lib/dataplane/config/zone.h @@ -62,21 +62,6 @@ struct dp_worker { struct rte_mempool *rx_mempool; uint8_t pad[24]; - - // trade-off: nic stats unload not often - // bcs put it in second cache line - uint64_t *nic_rx_packets; - uint64_t *nic_rx_bytes; - - uint64_t *nic_tx_packets; - uint64_t *nic_tx_bytes; - - uint64_t *nic_rx_errors; - uint64_t *nic_tx_errors; - - uint64_t *nic_rx_nombuf; - - uint8_t pad2[8]; }; struct dp_config { uint32_t instance_count; From 0ac64a9b5eb7a6ad7d38575998abb7e707c80ad2 Mon Sep 17 00:00:00 2001 From: Kirill Faizullin Date: Wed, 29 Apr 2026 11:45:44 +0300 Subject: [PATCH 10/10] retract changes from nic metrics branch --- api/counter.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/api/counter.h b/api/counter.h index f4a0f3616..debcaace1 100644 --- a/api/counter.h +++ b/api/counter.h @@ -49,12 +49,6 @@ yanet_get_chain_counters( const char *chain_name ); -struct counter_handle_list * -yanet_get_nic_counters( - struct dp_config *dp_config, - const char *device_name -); - // Get module counters, optionally filtered by name. struct counter_handle_list * yanet_get_module_counters(