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