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