Merge "Initial support for DPDK 18.05"
[samplevnf.git] / VNFs / DPPD-PROX / stats_ring.c
1 /*
2 // Copyright (c) 2010-2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #include <inttypes.h>
18 #include <rte_ring.h>
19 #include <rte_version.h>
20
21 #include "prox_malloc.h"
22 #include "stats_ring.h"
23 #include "prox_port_cfg.h"
24 #include "prox_cfg.h"
25 #include "lconf.h"
26 #include "log.h"
27 #include "quit.h"
28
29 struct stats_ring_manager {
30         uint16_t n_rings;
31         struct ring_stats ring_stats[0];
32 };
33
34 static struct stats_ring_manager *rsm;
35
36 int stats_get_n_rings(void)
37 {
38         return rsm->n_rings;
39 }
40
41 struct ring_stats *stats_get_ring_stats(uint32_t i)
42 {
43         return &rsm->ring_stats[i];
44 }
45
46 void stats_ring_update(void)
47 {
48         for (uint16_t r_id = 0; r_id < rsm->n_rings; ++r_id) {
49                 rsm->ring_stats[r_id].free = rte_ring_free_count(rsm->ring_stats[r_id].ring);
50         }
51 }
52
53 static struct ring_stats *init_rings_add(struct stats_ring_manager *rsm, struct rte_ring *ring)
54 {
55         for (uint16_t i = 0; i < rsm->n_rings; ++i) {
56                 if (strcmp(ring->name, rsm->ring_stats[i].ring->name) == 0)
57                         return &rsm->ring_stats[i];
58         }
59         rsm->ring_stats[rsm->n_rings++].ring = ring;
60         return &rsm->ring_stats[rsm->n_rings - 1];
61 }
62
63 static struct stats_ring_manager *alloc_stats_ring_manager(void)
64 {
65         const uint32_t socket_id = rte_lcore_to_socket_id(rte_lcore_id());
66         struct lcore_cfg *lconf;
67         uint32_t lcore_id = -1;
68         uint32_t n_rings = 0;
69         struct task_args *targ;
70
71         /* n_rings could be more than total number of rings since
72            rings could be referenced by multiple cores. */
73         while(prox_core_next(&lcore_id, 1) == 0) {
74                 lconf = &lcore_cfg[lcore_id];
75
76                 for(uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
77                         targ = &lconf->targs[task_id];
78
79                         for(uint32_t rxring_id = 0; rxring_id < targ->nb_rxrings; ++rxring_id) {
80                                 if (!targ->tx_opt_ring_task)
81                                         n_rings++;
82                         }
83                         for (uint32_t txring_id = 0; txring_id < targ->nb_txrings; ++txring_id) {
84                                 if (!targ->tx_opt_ring)
85                                         n_rings++;
86                         }
87                 }
88         }
89
90         for (uint8_t port_id = 0; port_id < PROX_MAX_PORTS; ++port_id) {
91                 if (!prox_port_cfg[port_id].active) {
92                         continue;
93                 }
94
95                 if (prox_port_cfg[port_id].rx_ring[0] != '\0')
96                         n_rings++;
97
98                 if (prox_port_cfg[port_id].tx_ring[0] != '\0')
99                         n_rings++;
100         }
101
102         size_t mem_size = sizeof(struct stats_ring_manager) +
103                 n_rings * sizeof(struct ring_stats);
104
105         return prox_zmalloc(mem_size, socket_id);
106 }
107
108 void stats_ring_init(void)
109 {
110         uint32_t lcore_id = -1;
111         struct lcore_cfg *lconf;
112         struct task_args *targ;
113
114         rsm = alloc_stats_ring_manager();
115         while(prox_core_next(&lcore_id, 1) == 0) {
116                 lconf = &lcore_cfg[lcore_id];
117
118                 for(uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
119                         targ = &lconf->targs[task_id];
120
121                         for(uint32_t rxring_id = 0; rxring_id < targ->nb_rxrings; ++rxring_id) {
122                                 if (!targ->tx_opt_ring_task)
123                                         init_rings_add(rsm, targ->rx_rings[rxring_id]);
124                         }
125
126                         for (uint32_t txring_id = 0; txring_id < targ->nb_txrings; ++txring_id) {
127                                 if (!targ->tx_opt_ring)
128                                         init_rings_add(rsm, targ->tx_rings[txring_id]);
129                         }
130                 }
131         }
132
133         struct ring_stats *stats = NULL;
134
135         for (uint8_t port_id = 0; port_id < PROX_MAX_PORTS; ++port_id) {
136                 if (!prox_port_cfg[port_id].active) {
137                         continue;
138                 }
139
140                 if (prox_port_cfg[port_id].rx_ring[0] != '\0') {
141                         stats = init_rings_add(rsm, rte_ring_lookup(prox_port_cfg[port_id].rx_ring));
142                         stats->port[stats->nb_ports++] = &prox_port_cfg[port_id];
143                 }
144
145                 if (prox_port_cfg[port_id].tx_ring[0] != '\0') {
146                         stats = init_rings_add(rsm, rte_ring_lookup(prox_port_cfg[port_id].tx_ring));
147                         stats->port[stats->nb_ports++] = &prox_port_cfg[port_id];
148                 }
149         }
150
151         /* The actual usable space for a ring is size - 1. There is at
152            most one free entry in the ring to distinguish between
153            full/empty. */
154         for (uint16_t ring_id = 0; ring_id < rsm->n_rings; ++ring_id)
155 #if RTE_VERSION < RTE_VERSION_NUM(17,5,0,1)
156                 rsm->ring_stats[ring_id].size = rsm->ring_stats[ring_id].ring->prod.size - 1;
157 #else
158                 rsm->ring_stats[ring_id].size = rsm->ring_stats[ring_id].ring->size - 1;
159 #endif
160 }