octeon: add clear counters for port and queues
[vpp.git] / src / vppinfra / unix-formats.c
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16   Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
17
18   Permission is hereby granted, free of charge, to any person obtaining
19   a copy of this software and associated documentation files (the
20   "Software"), to deal in the Software without restriction, including
21   without limitation the rights to use, copy, modify, merge, publish,
22   distribute, sublicense, and/or sell copies of the Software, and to
23   permit persons to whom the Software is furnished to do so, subject to
24   the following conditions:
25
26   The above copyright notice and this permission notice shall be
27   included in all copies or substantial portions of the Software.
28
29   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 */
37
38 #ifdef __KERNEL__
39
40 #if __linux__
41 # include <linux/unistd.h>
42 # include <linux/signal.h>
43 #endif
44
45 #else /* ! __KERNEL__ */
46
47 #ifdef __APPLE__
48 #define _XOPEN_SOURCE
49 #endif
50
51 #define _GNU_SOURCE             /* to get REG_* in ucontext.h */
52 #include <ucontext.h>
53 #undef __USE_GNU
54
55 #include <unistd.h>
56 #include <signal.h>
57 #include <grp.h>
58
59 #include <time.h>
60 #include <sys/socket.h>
61 #include <netdb.h>
62 #include <math.h>
63
64 #include <vppinfra/time.h>
65 #if __linux__
66 #ifdef AF_NETLINK
67 #include <linux/types.h>
68 #include <linux/netlink.h>
69 #endif
70 #elif __FreeBSD__
71 #include <netlink/netlink.h>
72 #endif /* __linux__ */
73
74 #endif /* ! __KERNEL__ */
75
76
77 #ifdef __KERNEL__
78 # include <linux/socket.h>
79 # include <linux/in.h>
80 # include <linux/ip.h>
81 # include <linux/tcp.h>
82 # include <linux/udp.h>
83 # include <linux/icmp.h>
84 # include <linux/if_ether.h>
85 # include <linux/if_arp.h>
86 #else
87 # include <net/if.h>            /* struct ifnet may live here */
88 # include <netinet/in.h>
89 # include <netinet/ip.h>
90 # include <netinet/tcp.h>
91 # include <netinet/udp.h>
92 # include <netinet/ip_icmp.h>
93 # include <netinet/if_ether.h>
94 #endif /* __KERNEL__ */
95
96 #include <vppinfra/format.h>
97 #include <vppinfra/error.h>
98
99 /* Format unix network address family (e.g. AF_INET). */
100 u8 * format_address_family (u8 * s, va_list * va)
101 {
102   uword family = va_arg (*va, uword);
103   u8 * t = (u8 *) "UNKNOWN";
104   switch (family)
105     {
106 #define _(x) case PF_##x: t = (u8 *) #x; break
107       _ (UNSPEC);
108       _ (UNIX);                 /* Unix domain sockets          */
109       _ (INET);                 /* Internet IP Protocol         */
110 #ifdef PF_AX25
111       _ (AX25);                 /* Amateur Radio AX.25          */
112 #endif
113 #ifdef PF_IPX
114       _ (IPX);                  /* Novell IPX                   */
115 #endif
116 #ifdef PF_APPLETALK
117       _ (APPLETALK);            /* AppleTalk DDP                */
118 #endif
119 #ifdef PF_NETROM
120       _ (NETROM);               /* Amateur Radio NET/ROM        */
121 #endif
122 #ifdef PF_BRIDGE
123       _ (BRIDGE);               /* Multiprotocol bridge         */
124 #endif
125 #ifdef PF_ATMPVC
126       _ (ATMPVC);               /* ATM PVCs                     */
127 #endif
128 #ifdef PF_X25
129       _ (X25);                  /* Reserved for X.25 project    */
130 #endif
131 #ifdef PF_INET6
132       _ (INET6);                /* IP version 6                 */
133 #endif
134 #ifdef PF_ROSE
135       _ (ROSE);                 /* Amateur Radio X.25 PLP       */
136 #endif
137 #ifdef PF_DECnet
138       _ (DECnet);               /* Reserved for DECnet project  */
139 #endif
140 #ifdef PF_NETBEUI
141       _ (NETBEUI);              /* Reserved for 802.2LLC project*/
142 #endif
143 #ifdef PF_SECURITY
144       _ (SECURITY);             /* Security callback pseudo AF */
145 #endif
146 #ifdef PF_KEY
147       _ (KEY);                  /* PF_KEY key management API */
148 #endif
149 #ifdef PF_NETLINK
150       _ (NETLINK);
151 #endif
152 #ifdef PF_PACKET
153       _ (PACKET);               /* Packet family                */
154 #endif
155 #ifdef PF_ASH
156       _ (ASH);                  /* Ash                          */
157 #endif
158 #ifdef PF_ECONET
159       _ (ECONET);               /* Acorn Econet                 */
160 #endif
161 #ifdef PF_ATMSVC
162       _ (ATMSVC);               /* ATM SVCs                     */
163 #endif
164 #ifdef PF_SNA
165       _ (SNA);                  /* Linux SNA Project */
166 #endif
167 #ifdef PF_IRDA
168       _ (IRDA);                 /* IRDA sockets                 */
169 #endif
170 #undef _
171     }
172   vec_add (s, t, strlen ((char *) t));
173   return s;
174 }
175
176 u8 * format_network_protocol (u8 * s, va_list * args)
177 {
178   uword family = va_arg (*args, uword);
179   uword protocol = va_arg (*args, uword);
180
181 #ifndef __KERNEL__
182   struct protoent * p = getprotobynumber (protocol);
183
184   ASSERT (family == AF_INET);
185   if (p)
186     return format (s, "%s", p->p_name);
187   else
188     return format (s, "%d", protocol);
189 #else
190   return format (s, "%d/%d", family, protocol);
191 #endif
192 }
193
194 u8 * format_network_port (u8 * s, va_list * args)
195 {
196   uword proto = va_arg (*args, uword);
197   uword port = va_arg (*args, uword);
198
199 #ifndef __KERNEL__
200   struct servent * p = getservbyport (port, proto == IPPROTO_UDP ? "udp" : "tcp");
201
202   if (p)
203     return format (s, "%s", p->s_name);
204   else
205     return format (s, "%d", port);
206 #else
207   return format (s, "%s/%d", proto == IPPROTO_UDP ? "udp" : "tcp", port);
208 #endif
209 }
210
211 /* Format generic network address: takes two arguments family and address.
212    Assumes network byte order. */
213 u8 * format_network_address (u8 * s, va_list * args)
214 {
215   uword family = va_arg (*args, uword);
216   u8 * addr    = va_arg (*args, u8 *);
217
218   switch (family)
219     {
220     case AF_INET:
221       s = format (s, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
222       break;
223
224     case AF_UNSPEC:
225       /* We use AF_UNSPEC for ethernet addresses. */
226       s = format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
227                   addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
228       break;
229
230     default:
231       clib_error ("unsupported address family %d", family);
232     }
233
234   return s;
235 }
236
237 u8 * format_sockaddr (u8 * s, va_list * args)
238 {
239   void * v = va_arg (*args, void *);
240   struct sockaddr * sa = v;
241   static u32 local_counter;
242
243   switch (sa->sa_family)
244     {
245     case AF_INET:
246       {
247         struct sockaddr_in * i = v;
248         s = format (s, "%U:%U",
249                     format_network_address, AF_INET, &i->sin_addr.s_addr,
250                     format_network_port, IPPROTO_TCP, ntohs (i->sin_port));
251       }
252       break;
253
254     case AF_LOCAL:
255       {
256         /* 
257          * There isn't anything useful to print.
258          * The unix cli world uses the output to make a node name,
259          * so we need to return a unique name. 
260          */
261         s = format (s, "local:%u", local_counter++);
262       }
263       break;
264
265 #ifndef __KERNEL__
266 #ifdef AF_NETLINK
267     case AF_NETLINK:
268       {
269         struct sockaddr_nl * n = v;
270         s = format (s, "KERNEL-NETLINK");
271         if (n->nl_groups)
272           s = format (s, " (groups 0x%x)", n->nl_groups);
273         break;
274       }
275 #endif
276 #endif
277
278     default:
279       s = format (s, "sockaddr family %d", sa->sa_family);
280       break;
281     }
282
283   return s;
284 }
285
286 #ifndef __APPLE__
287
288 #ifndef __KERNEL__
289 u8 * format_timeval (u8 * s, va_list * args)
290 {
291   char * fmt = va_arg (*args, char *);
292   struct timeval * tv = va_arg (*args, struct timeval *);
293   struct tm * tm;
294   word msec;
295   char * f, c;
296
297   if (! fmt)
298     fmt = "y/m/d H:M:S:F";
299
300   if (! tv)
301     {
302       static struct timeval now;
303       gettimeofday (&now, 0);
304       tv = &now;
305     }
306
307   msec = flt_round_nearest (1e-3 * tv->tv_usec);
308   if (msec >= 1000)
309     { msec = 0; tv->tv_sec++; }
310
311   {
312     time_t t = tv->tv_sec;
313     tm = localtime (&t);
314   }
315
316   for (f = fmt; *f; f++)
317     {
318       uword what;
319       char * what_fmt = "%d";
320
321       switch (c = *f)
322         {
323         default:
324           vec_add1 (s, c);
325           continue;
326
327         case 'y':
328           what = 1900 + tm->tm_year;
329           what_fmt = "%4d";
330           break;
331         case 'm':
332           what = tm->tm_mon + 1;
333           what_fmt = "%02d";
334           break;
335         case 'd':
336           what = tm->tm_mday;
337           what_fmt = "%02d";
338           break;
339         case 'H':
340           what = tm->tm_hour;
341           what_fmt = "%02d";
342           break;
343         case 'M':
344           what = tm->tm_min;
345           what_fmt = "%02d";
346           break;
347         case 'S':
348           what = tm->tm_sec;
349           what_fmt = "%02d";
350           break;
351         case 'F':
352           what = msec;
353           what_fmt = "%03d";
354           break;
355         }
356
357       s = format (s, what_fmt, what);
358     }
359
360   return s;
361 }
362 #endif
363
364 u8 * format_time_float (u8 * s, va_list * args)
365 {
366   u8 * fmt = va_arg (*args, u8 *);
367   f64 t = va_arg (*args, f64);
368   struct timeval tv;
369   if (t <= 0)
370     t = unix_time_now ();
371   tv.tv_sec = t;
372   tv.tv_usec = 1e6*(t - tv.tv_sec);
373   return format (s, "%U", format_timeval, fmt, &tv);
374 }
375
376 u8 * format_signal (u8 * s, va_list * args)
377 {
378   uword signum = va_arg (*args, uword);
379   char * t = 0;
380   switch (signum)
381     {
382 #define _(x) case x: t = #x; break;
383       _ (SIGHUP);
384       _ (SIGINT);
385       _ (SIGQUIT);
386       _ (SIGILL);
387       _ (SIGTRAP);
388       _ (SIGABRT);
389       _ (SIGBUS);
390       _ (SIGFPE);
391       _ (SIGKILL);
392       _ (SIGUSR1);
393       _ (SIGSEGV);
394       _ (SIGUSR2);
395       _ (SIGPIPE);
396       _ (SIGALRM);
397       _ (SIGTERM);
398 #ifdef SIGSTKFLT
399       _ (SIGSTKFLT);
400 #endif
401       _ (SIGCHLD);
402       _ (SIGCONT);
403       _ (SIGSTOP);
404       _ (SIGTSTP);
405       _ (SIGTTIN);
406       _ (SIGTTOU);
407       _ (SIGURG);
408       _ (SIGXCPU);
409       _ (SIGXFSZ);
410       _ (SIGVTALRM);
411       _ (SIGPROF);
412       _ (SIGWINCH);
413       _ (SIGIO);
414 #ifdef __linux__
415       _ (SIGPWR);
416 #endif /* __linux */
417 #ifdef SIGSYS
418       _ (SIGSYS);
419 #endif
420 #undef _
421     default:
422       return format (s, "unknown %d", signum);
423     }
424
425   vec_add (s, t, strlen (t));
426   return s;
427 }
428
429 u8 * format_ucontext_pc (u8 * s, va_list * args)
430 {
431   ucontext_t * uc __attribute__((unused));
432   unsigned long * regs = 0;
433   uword reg_no = 0;
434
435   uc = va_arg (*args, ucontext_t *);
436
437 #ifdef __linux__
438 #if defined (powerpc)
439   regs = &uc->uc_mcontext.uc_regs->gregs[0];
440 #elif defined (powerpc64)
441   regs = &uc->uc_mcontext.uc_regs->gp_regs[0];
442 #elif defined (i386) || defined (__x86_64__)
443   regs = (void *) &uc->uc_mcontext.gregs[0];
444 #elif defined(__aarch64__)
445   regs = (void *) &uc->uc_mcontext.pc;
446 #endif
447
448 #if defined (powerpc) || defined (powerpc64)
449   reg_no = PT_NIP;
450 #elif defined (i386)
451   reg_no = REG_EIP;
452 #elif defined (__x86_64__)
453   reg_no = REG_RIP;
454 #elif defined(__aarch64__)
455   reg_no = 0;
456 #else
457   reg_no = 0;
458   regs = 0;
459 #endif
460 #elif __FreeBSD__
461 #if defined(__amd64__)
462   reg_no = 0;
463   regs = (void *) &uc->uc_mcontext.mc_rip;
464 #else
465 #endif /* __amd64__ */
466 #endif /* __linux__ */
467
468   if (! regs)
469     return format (s, "unsupported");
470   else
471     return format (s, "%p", regs[reg_no]);
472 }
473
474 __clib_export uword
475 unformat_unix_gid (unformat_input_t * input, va_list * args)
476 {
477   gid_t *gid = va_arg (*args, gid_t *);
478   struct group *grp = 0;
479   int r;
480   u8 *s;
481
482   if (unformat (input, "%d", &r))
483     {
484       grp = getgrgid (r);
485     }
486   else if (unformat (input, "%s", &s))
487     {
488       grp = getgrnam ((char *) s);
489       vec_free (s);
490     }
491   if (grp)
492     {
493       *gid = grp->gr_gid;
494       return 1;
495     }
496   return 0;
497 }
498
499 #endif /* __KERNEL__ */