Do not create (empty) latency loss file if disabled
[samplevnf.git] / VNFs / DPPD-PROX / log.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 <sys/types.h>
18 #include <unistd.h>
19 #include <pthread.h>
20 #include <string.h>
21 #include <rte_cycles.h>
22 #include <rte_lcore.h>
23 #include <rte_ether.h>
24 #include <rte_ip.h>
25 #include <rte_mbuf.h>
26
27 #include "log.h"
28 #include "quit.h"
29 #include "display.h"
30 #include "defaults.h"
31 #include "etypes.h"
32 #include "prox_cfg.h"
33 #include "prox_compat.h"
34
35 static pthread_mutex_t file_mtx = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
36 int log_lvl = PROX_MAX_LOG_LVL;
37 static uint64_t tsc_off;
38 static FILE *fp;
39 static int n_warnings = 0;
40 char last_warn[5][1024];
41 int get_n_warnings(void)
42 {
43 #if PROX_MAX_LOG_LVL < PROX_LOG_WARN
44         return -1;
45 #endif
46         return n_warnings;
47 }
48
49 const char *get_warning(int i)
50 {
51 #if PROX_MAX_LOG_LVL < PROX_LOG_WARN
52         return NULL;
53 #endif
54         if (i > 0 || i < -4)
55                 return NULL;
56         return last_warn[(n_warnings - 1 + i + 5) % 5];
57 }
58
59 static void store_warning(const char *warning)
60 {
61         prox_strncpy(last_warn[n_warnings % 5], warning, sizeof(last_warn[0]));
62         n_warnings++;
63 }
64
65 void plog_init(const char *log_name, int log_name_pid)
66 {
67         pid_t pid;
68         char buf[128];
69
70         if (*log_name == 0) {
71                 if (log_name_pid)
72                         snprintf(buf, sizeof(buf), "%s-%u.log", "prox", getpid());
73                 else
74                         prox_strncpy(buf, "prox.log", sizeof(buf));
75         }
76         else {
77                 prox_strncpy(buf, log_name, sizeof(buf));
78         }
79
80         fp = fopen(buf, "w");
81
82         tsc_off = rte_rdtsc() + 2500000000;
83 }
84
85 void plog_end(void)
86 {
87         if (fp)
88                 fclose(fp);
89         fp = NULL;
90 }
91
92 int plog_set_lvl(int lvl)
93 {
94         if (lvl <= PROX_MAX_LOG_LVL) {
95                 log_lvl = lvl;
96                 return 0;
97         }
98
99         return -1;
100 }
101
102 static void file_lock(void)
103 {
104         pthread_mutex_lock(&file_mtx);
105 }
106
107 static void file_unlock(void)
108 {
109         pthread_mutex_unlock(&file_mtx);
110 }
111
112 void file_print(const char *str)
113 {
114         file_lock();
115         if (fp != NULL) {
116                 fputs(str, fp);
117                 fflush(fp);
118         }
119         file_unlock();
120 }
121 static void plog_buf(const char* buf)
122 {
123         if (prox_cfg.logbuf) {
124                 file_lock();
125                 if (prox_cfg.logbuf_pos + strlen(buf) + 1 < prox_cfg.logbuf_size) {
126                         memcpy(prox_cfg.logbuf + prox_cfg.logbuf_pos, buf, strlen(buf));
127                         prox_cfg.logbuf_pos += strlen(buf);
128                 }
129                 file_unlock();
130         } else {
131                 file_print(buf);
132 #ifdef PROX_STATS
133                 display_print(buf);
134 #else
135         /* ncurses never initialized */
136                 fputs(buf, stdout);
137                 fflush(stdout);
138 #endif
139         }
140 }
141
142 static const char* lvl_to_str(int lvl, int always)
143 {
144         switch (lvl) {
145         case PROX_LOG_ERR:  return "error ";
146         case PROX_LOG_WARN: return "warn ";
147         case PROX_LOG_INFO: return always? "info " : "";
148         case PROX_LOG_DBG:  return "debug ";
149         default: return "?";
150         }
151 }
152
153 static  int dump_pkt(char *dst, size_t dst_size, const struct rte_mbuf *mbuf)
154 {
155         const prox_rte_ether_hdr *peth = rte_pktmbuf_mtod(mbuf, const prox_rte_ether_hdr *);
156         const prox_rte_ipv4_hdr *dpip = (const prox_rte_ipv4_hdr *)(peth + 1);
157         const uint8_t *pkt_bytes = (const uint8_t *)peth;
158         const uint16_t len = rte_pktmbuf_pkt_len(mbuf);
159         size_t str_len = 0;
160
161         if (peth->ether_type == ETYPE_IPv4)
162                 str_len = snprintf(dst, dst_size, "pkt_len=%u, Eth=%x, Proto=%#06x",
163                                 len, peth->ether_type, dpip->next_proto_id);
164         else
165                 str_len = snprintf(dst, dst_size, "pkt_len=%u, Eth=%x",
166                                 len, peth->ether_type);
167
168         for (uint16_t i = 0; i < len && i < DUMP_PKT_LEN && str_len < dst_size; ++i) {
169                 if (i % 16 == 0) {
170                         str_len += snprintf(dst + str_len, dst_size - str_len, "\n%04x  ", i);
171                 }
172                 else if (i % 8 == 0) {
173                         str_len += snprintf(dst + str_len, dst_size - str_len, " ");
174                 }
175                 str_len += snprintf(dst + str_len, dst_size - str_len, "%02x ", pkt_bytes[i]);
176         }
177         if (str_len < dst_size)
178                 snprintf(dst + str_len, dst_size - str_len, "\n");
179         return str_len + 1;
180 }
181
182 static int vplog(int lvl, const char *format, va_list ap, const struct rte_mbuf *mbuf, int extended)
183 {
184         char buf[32768];
185         uint64_t hz, rtime_tsc, rtime_sec, rtime_usec;
186         int ret = 0;
187
188         if (lvl > log_lvl)
189                 return ret;
190
191         if (format == NULL && mbuf == NULL)
192                 return ret;
193
194         *buf = 0;
195         if (extended) {
196                 hz = rte_get_tsc_hz();
197                 rtime_tsc = rte_rdtsc() - tsc_off;
198                 rtime_sec = rtime_tsc / hz;
199                 rtime_usec = (rtime_tsc - rtime_sec * hz) / (hz / 1000000);
200                 ret += snprintf(buf, sizeof(buf) - ret, "%2"PRIu64".%06"PRIu64" C%u %s%s",
201                                 rtime_sec, rtime_usec, rte_lcore_id(), lvl_to_str(lvl, 1), format? " " : "");
202         }
203         else {
204                 ret += snprintf(buf, sizeof(buf) - ret, "%s%s", lvl_to_str(lvl, 0), format? " " : "");
205         }
206
207         if (format) {
208                 ret--;
209                 ret += vsnprintf(buf + ret, sizeof(buf) - ret, format, ap);
210         }
211
212         if (mbuf) {
213                 ret--;
214                 ret += dump_pkt(buf + ret, sizeof(buf) - ret, mbuf);
215         }
216
217         if (lvl == PROX_LOG_PANIC)
218                 PROX_PANIC(1, "%s", buf);
219
220         plog_buf(buf);
221
222         if (lvl == PROX_LOG_WARN) {
223                 store_warning(buf);
224         }
225         return ret;
226 }
227
228 #if PROX_MAX_LOG_LVL >= PROX_LOG_INFO
229 int plog_info(const char *fmt, ...)
230 {
231         va_list ap;
232         int ret;
233
234         va_start(ap, fmt);
235         ret = vplog(PROX_LOG_INFO, fmt, ap, NULL, 0);
236         va_end(ap);
237         return ret;
238 }
239
240 int plogx_info(const char *fmt, ...)
241 {
242         va_list ap;
243         int ret;
244
245         va_start(ap, fmt);
246         ret = vplog(PROX_LOG_INFO, fmt, ap, NULL, 1);
247         va_end(ap);
248         return ret;
249 }
250
251 int plogd_info(const struct rte_mbuf *mbuf, const char *fmt, ...)
252 {
253         va_list ap;
254         int ret;
255
256         va_start(ap, fmt);
257         ret = vplog(PROX_LOG_INFO, fmt, ap, mbuf, 0);
258         va_end(ap);
259         return ret;
260 }
261
262 int plogdx_info(const struct rte_mbuf *mbuf, const char *fmt, ...)
263 {
264         va_list ap;
265         int ret;
266
267         va_start(ap, fmt);
268         ret = vplog(PROX_LOG_INFO, fmt, ap, mbuf, 1);
269         va_end(ap);
270         return ret;
271 }
272 #endif
273
274 #if PROX_MAX_LOG_LVL >= PROX_LOG_ERR
275 int plog_err(const char *fmt, ...)
276 {
277         va_list ap;
278         int ret;
279
280         va_start(ap, fmt);
281         ret = vplog(PROX_LOG_ERR, fmt, ap, NULL, 0);
282         va_end(ap);
283         return ret;
284 }
285
286 int plog_err_or_panic(int do_panic, const char *fmt, ...)
287 {
288         va_list ap;
289         int ret;
290
291         va_start(ap, fmt);
292         if (do_panic) {
293                 ret = vplog(PROX_LOG_PANIC, fmt, ap, NULL, 0);
294                 va_end(ap);
295                 return ret;
296         } else {
297                 ret = vplog(PROX_LOG_ERR, fmt, ap, NULL, 0);
298                 va_end(ap);
299                 return ret;
300         }
301 }
302
303 int plogx_err(const char *fmt, ...)
304 {
305         va_list ap;
306         int ret;
307
308         va_start(ap, fmt);
309         ret = vplog(PROX_LOG_ERR, fmt, ap, NULL, 1);
310         va_end(ap);
311         return ret;
312 }
313
314 int plogd_err(const struct rte_mbuf *mbuf, const char *fmt, ...)
315 {
316         va_list ap;
317         int ret;
318
319         va_start(ap, fmt);
320         ret = vplog(PROX_LOG_ERR, fmt, ap, mbuf, 1);
321         va_end(ap);
322         return ret;
323 }
324
325 int plogdx_err(const struct rte_mbuf *mbuf, const char *fmt, ...)
326 {
327         va_list ap;
328         int ret;
329
330         va_start(ap, fmt);
331         ret = vplog(PROX_LOG_ERR, fmt, ap, mbuf, 1);
332         va_end(ap);
333
334         return ret;
335 }
336 #endif
337
338 #if PROX_MAX_LOG_LVL >= PROX_LOG_WARN
339 int plog_warn(const char *fmt, ...)
340 {
341         va_list ap;
342         int ret;
343
344         va_start(ap, fmt);
345         ret = vplog(PROX_LOG_WARN, fmt, ap, NULL, 0);
346         va_end(ap);
347         return ret;
348 }
349
350 int plogx_warn(const char *fmt, ...)
351 {
352         va_list ap;
353         int ret;
354
355         va_start(ap, fmt);
356         ret = vplog(PROX_LOG_WARN, fmt, ap, NULL, 1);
357         va_end(ap);
358         return ret;
359 }
360
361 int plogd_warn(const struct rte_mbuf *mbuf, const char *fmt, ...)
362 {
363         va_list ap;
364         int ret;
365
366         va_start(ap, fmt);
367         ret = vplog(PROX_LOG_WARN, fmt, ap, mbuf, 0);
368         va_end(ap);
369         return ret;
370 }
371
372 int plogdx_warn(const struct rte_mbuf *mbuf, const char *fmt, ...)
373 {
374         va_list ap;
375         int ret;
376
377         va_start(ap, fmt);
378         ret = vplog(PROX_LOG_WARN, fmt, ap, mbuf, 1);
379         va_end(ap);
380         return ret;
381 }
382 #endif
383
384 #if PROX_MAX_LOG_LVL >= PROX_LOG_DBG
385 int plog_dbg(const char *fmt, ...)
386 {
387         va_list ap;
388         int ret;
389
390         va_start(ap, fmt);
391         ret = vplog(PROX_LOG_DBG, fmt, ap, NULL, 0);
392         va_end(ap);
393         return ret;
394 }
395
396 int plogx_dbg(const char *fmt, ...)
397 {
398         va_list ap;
399         int ret;
400
401         va_start(ap, fmt);
402         ret = vplog(PROX_LOG_DBG, fmt, ap, NULL, 1);
403         va_end(ap);
404         return ret;
405 }
406
407 int plogd_dbg(const struct rte_mbuf *mbuf, const char *fmt, ...)
408 {
409         va_list ap;
410         int ret;
411
412         va_start(ap, fmt);
413         ret = vplog(PROX_LOG_DBG, fmt, ap, mbuf, 0);
414         va_end(ap);
415         return ret;
416 }
417
418 int plogdx_dbg(const struct rte_mbuf *mbuf, const char *fmt, ...)
419 {
420         va_list ap;
421         int ret;
422
423         va_start(ap, fmt);
424         ret = vplog(PROX_LOG_DBG, fmt, ap, mbuf, 1);
425         va_end(ap);
426         return ret;
427 }
428 #endif