845399e3f3ec227b2b48d6bcfb5f7f56224479ab
[samplevnf.git] / VNFs / DPPD-PROX / stats_core.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 <rte_lcore.h>
18
19 #include "prox_malloc.h"
20 #include "stats_core.h"
21 #include "cqm.h"
22 #include "log.h"
23 #include "msr.h"
24 #include "parse_utils.h"
25 #include "prox_cfg.h"
26 #include "lconf.h"
27
28 struct stats_core_manager {
29         struct rdt_features rdt_features;
30         int                msr_support;
31         int                max_core_id;
32         uint16_t           n_lcore_stats;
33         int cache_size[RTE_MAX_LCORE];
34         struct lcore_stats lcore_stats_set[0];
35 };
36
37 static struct stats_core_manager *scm;
38 extern int last_stat;
39
40 static int get_L3_size(void)
41 {
42         char buf[1024]= "/proc/cpuinfo";
43         FILE* fd = fopen(buf, "r");
44         if (fd == NULL) {
45                 plogx_err("Could not open %s", buf);
46                 return -1;
47         }
48         int lcore = -1, val = 0, size = 0;
49         while (fgets(buf, sizeof(buf), fd) != NULL) {
50                 if (sscanf(buf, "processor : %u", &val) == 1) {
51                         lcore = val;
52                         scm->max_core_id = lcore;
53                 }
54                 if (sscanf(buf, "cache size : %u", &val) == 1) {
55                         size = val;
56                         if ((lcore != -1) && (lcore < RTE_MAX_LCORE)) {
57                                 scm->cache_size[lcore] = size * 1024;
58                         }
59                 }
60         }
61         fclose(fd);
62         plog_info("\tMaximum core_id = %d\n", scm->max_core_id);
63         return 0;
64 }
65
66 int stats_get_n_lcore_stats(void)
67 {
68         return scm->n_lcore_stats;
69 }
70
71 int stats_cpu_freq_enabled(void)
72 {
73         return scm->msr_support;
74 }
75
76 int stats_cmt_enabled(void)
77 {
78         return cmt_is_supported();
79 }
80
81 int stats_cat_enabled(void)
82 {
83         return cat_is_supported();
84 }
85
86 int stats_mbm_enabled(void)
87 {
88         return mbm_is_supported();
89 }
90
91 uint32_t stats_lcore_find_stat_id(uint32_t lcore_id)
92 {
93         for (int i = 0; i < scm->n_lcore_stats; ++i)
94                 if (scm->lcore_stats_set[i].lcore_id == lcore_id)
95                         return i;
96         return 0;
97 }
98
99 struct lcore_stats_sample *stats_get_lcore_stats_sample(uint32_t stat_id, int l)
100 {
101         return &scm->lcore_stats_set[stat_id].sample[l == last_stat];
102 }
103
104 struct lcore_stats *stats_get_lcore_stats(uint32_t stat_id)
105 {
106         return &scm->lcore_stats_set[stat_id];
107 }
108
109 static struct stats_core_manager *alloc_stats_core_manager(void)
110 {
111         const int socket_id = rte_lcore_to_socket_id(rte_lcore_id());
112         uint32_t n_lcore_stats = 0;
113         uint32_t lcore_id;
114         size_t mem_size;
115
116         lcore_id = -1;
117         while (prox_core_next(&lcore_id, 0) == 0)
118                 n_lcore_stats++;
119         mem_size = sizeof(struct stats_core_manager) + sizeof(struct lcore_stats) * n_lcore_stats;
120         return prox_zmalloc(mem_size, socket_id);
121 }
122
123 void stats_lcore_init(void)
124 {
125         struct lcore_cfg *lconf;
126         uint32_t lcore_id;
127         int j = 0;
128
129         scm = alloc_stats_core_manager();
130
131         if (is_virtualized()) {
132                 plog_info("Not initializing msr as running in a VM\n");
133                 scm->msr_support = 0;
134         } else if ((scm->msr_support = !msr_init()) == 0) {
135                 plog_warn("Failed to open msr pseudo-file (missing msr kernel module?)\n");
136         }
137
138         scm->n_lcore_stats = 0;
139         lcore_id = -1;
140         get_L3_size();
141         while (prox_core_next(&lcore_id, 0) == 0) {
142                 scm->lcore_stats_set[scm->n_lcore_stats++].lcore_id = lcore_id;
143         }
144         if (!rdt_is_supported())
145                 return;
146
147         if (!scm->msr_support) {
148                 plog_warn("CPU supports RDT but msr module not loaded. Disabling RDT stats.\n");
149                 return;
150         }
151
152         if (0 != rdt_get_features(&scm->rdt_features)) {
153                 plog_warn("Failed to get RDT features\n");
154                 return;
155         }
156         else {
157                 rdt_init_stat_core(rte_lcore_id());
158         }
159
160         /* Start using last rmid, to keep first rmid for technologies (like cat) where there are less rmid */
161         uint32_t last_rmid = scm->rdt_features.cmt_max_rmid;
162         for (uint32_t i = 0; i < scm->n_lcore_stats; ++i) {
163                 scm->lcore_stats_set[i].rmid = last_rmid; // cmt_max_rmid is used by non-monitored cores
164                 last_rmid--;
165         }
166
167         uint64_t cache_set;
168         for (uint32_t i = 0; i < scm->n_lcore_stats; ++i) {
169                 plog_info("\tAssociating core %u to rmid %lu (associating each core used by prox to a different rmid)\n", scm->lcore_stats_set[i].lcore_id, scm->lcore_stats_set[i].rmid);
170                 cqm_assoc(scm->lcore_stats_set[i].lcore_id, scm->lcore_stats_set[i].rmid);
171                 uint32_t lcore_id = scm->lcore_stats_set[i].lcore_id;
172                 lconf = &lcore_cfg[lcore_id];
173                 cache_set = lconf->cache_set;
174                 if ((cache_set) && (cache_set < PROX_MAX_CACHE_SET)) {
175                         scm->lcore_stats_set[i].class = cache_set;
176                         scm->lcore_stats_set[i].cat_mask = prox_cache_set_cfg[cache_set].mask;
177                         if (prox_cache_set_cfg[cache_set].socket_id == -1) {
178                                 prox_cache_set_cfg[cache_set].socket_id = scm->lcore_stats_set[i].socket_id;
179                                 prox_cache_set_cfg[cache_set].lcore_id = lcore_id;
180                         } else if (prox_cache_set_cfg[cache_set].socket_id != (int32_t)scm->lcore_stats_set[i].socket_id) {
181                                 plog_err("Unsupported config: Using same cache set on two different socket\n");
182                         }
183                 } else {
184                         scm->lcore_stats_set[i].class = 0;
185                         scm->lcore_stats_set[i].cat_mask = (1 << cat_get_num_ways()) -1;
186                 }
187         }
188         cat_log_init(0);
189         last_rmid = scm->rdt_features.cat_max_rmid;
190         for (int i = 0; i < PROX_MAX_CACHE_SET; i++) {
191                 if (prox_cache_set_cfg[i].mask) {
192                         plog_info("\tSetting cache set %d to %x\n", i, prox_cache_set_cfg[i].mask);
193                         cat_set_class_mask(prox_cache_set_cfg[i].lcore_id, i, prox_cache_set_cfg[i].mask);
194                 }
195         }
196         for (uint32_t i = 0; i < scm->n_lcore_stats; ++i) {
197                 uint32_t lcore_id = scm->lcore_stats_set[i].lcore_id;
198                 lconf = &lcore_cfg[lcore_id];
199                 cache_set = lconf->cache_set;
200                 if (cache_set) {
201                         if (prox_cache_set_cfg[cache_set].mask) {
202                                 scm->lcore_stats_set[i].rmid = (scm->lcore_stats_set[i].rmid) | (cache_set << 32);
203                                 plog_info("\tCache set = %ld for core %d\n", cache_set, lcore_id);
204                                 cqm_assoc(lcore_id, scm->lcore_stats_set[i].rmid);
205                         } else {
206                                 plog_err("\tUndefined Cache set = %ld for core %d\n", cache_set, lcore_id);
207                         }
208                 } else {
209                         if (prox_cache_set_cfg[cache_set].mask) {
210                                 scm->lcore_stats_set[i].rmid = (scm->lcore_stats_set[i].rmid);
211                                 plog_info("\tUsing default cache set for core %d\n", lcore_id);
212                                 cqm_assoc(lcore_id, scm->lcore_stats_set[i].rmid);
213                         } else {
214                                 plog_info("\tNo default cache set for core %d\n", lcore_id);
215                         }
216                 }
217         }
218 }
219
220 static void stats_lcore_update_freq(void)
221 {
222         for (uint8_t i = 0; i < scm->n_lcore_stats; ++i) {
223                 struct lcore_stats *ls = &scm->lcore_stats_set[i];
224                 struct lcore_stats_sample *lss = &ls->sample[last_stat];
225
226                 msr_read(&lss->afreq, ls->lcore_id, 0xe8);
227                 msr_read(&lss->mfreq, ls->lcore_id, 0xe7);
228         }
229 }
230 void stats_update_cache_mask(uint32_t lcore_id, uint32_t mask)
231 {
232         for (uint8_t i = 0; i < scm->n_lcore_stats; ++i) {
233                 struct lcore_stats *ls = &scm->lcore_stats_set[i];
234                 if (ls->lcore_id == lcore_id) {
235                         plog_info("Updating  core %d stats %d to mask %x\n", lcore_id, i, mask);
236                         scm->lcore_stats_set[i].cat_mask = mask;
237                 }
238         }
239 }
240
241 static void stats_lcore_update_rdt(void)
242 {
243         for (uint8_t i = 0; i < scm->n_lcore_stats; ++i) {
244                 struct lcore_stats *ls = &scm->lcore_stats_set[i];
245
246                 if (ls->rmid) {
247                         cmt_read_ctr(&ls->cmt_data, ls->rmid, ls->lcore_id);
248                         mbm_read_tot_bdw(&ls->mbm_tot, ls->rmid, ls->lcore_id);
249                         mbm_read_loc_bdw(&ls->mbm_loc, ls->rmid, ls->lcore_id);
250                 }
251         }
252 }
253
254 void stats_lcore_post_proc(void)
255 {
256         /* update CQM stats (calculate fraction and bytes reported) */
257         for (uint8_t i = 0; i < scm->n_lcore_stats; ++i) {
258                 struct lcore_stats *ls = &scm->lcore_stats_set[i];
259                 struct lcore_stats_sample *lss = &ls->sample[last_stat];
260
261                 if (ls->rmid) {
262                         ls->cmt_bytes = ls->cmt_data * scm->rdt_features.upscaling_factor;
263                         lss->mbm_tot_bytes = ls->mbm_tot * scm->rdt_features.upscaling_factor;
264                         lss->mbm_loc_bytes = ls->mbm_loc * scm->rdt_features.upscaling_factor;
265                         plogx_dbg("cache[core %d] = %ld\n", ls->lcore_id, ls->cmt_bytes);
266                 }
267         }
268         for (uint8_t i = 0; i < scm->n_lcore_stats; ++i) {
269                 struct lcore_stats *ls = &scm->lcore_stats_set[i];
270
271                 if (ls->rmid && scm->cache_size[ls->lcore_id])
272                         ls->cmt_fraction = ls->cmt_bytes * 10000 / scm->cache_size[ls->lcore_id];
273                 else
274                         ls->cmt_fraction = 0;
275         }
276 }
277
278 void stats_lcore_update(void)
279 {
280         if (scm->msr_support)
281                 stats_lcore_update_freq();
282         if (rdt_is_supported())
283                 stats_lcore_update_rdt();
284 }
285
286 void stats_lcore_assoc_rmid(void)
287 {
288         for (uint32_t i = 0; i < scm->n_lcore_stats; ++i) {
289                 uint32_t lcore_id = scm->lcore_stats_set[i].lcore_id;
290                 scm->lcore_stats_set[i].rmid = scm->lcore_stats_set[i].rmid & 0xffffffff;
291                 cqm_assoc(lcore_id, scm->lcore_stats_set[i].rmid);
292         }
293 }