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