lib: Move compiler.h to <openvswitch/compiler.h>
[cascardo/ovs.git] / tests / test-sflow.c
index edb996c..0bd5570 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, 2013 Nicira, Inc.
+ * Copyright (c) 2011, 2012, 2013, 2014 Nicira, Inc.
  * Copyright (c) 2013 InMon Corp.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  */
 
 #include <config.h>
-
+#undef NDEBUG
+#include "netflow.h"
+#include <arpa/inet.h>
 #include <errno.h>
 #include <getopt.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <setjmp.h>
-
 #include "command-line.h"
 #include "daemon.h"
 #include "dynamic-string.h"
-#include "netflow.h"
 #include "ofpbuf.h"
+#include "ovstest.h"
 #include "packets.h"
 #include "poll-loop.h"
 #include "socket-util.h"
@@ -36,7 +37,7 @@
 #include "util.h"
 #include "vlog.h"
 
-static void usage(void) NO_RETURN;
+OVS_NO_RETURN static void usage(void);
 static void parse_options(int argc, char *argv[]);
 
 static unixctl_cb_func test_sflow_exit;
@@ -44,7 +45,6 @@ static unixctl_cb_func test_sflow_exit;
 /* Datagram. */
 #define SFLOW_VERSION_5 5
 #define SFLOW_MIN_LEN 36
-#define SFLOW_MAX_AGENTIP_STRLEN 64
 
 /* Sample tag numbers. */
 #define SFLOW_FLOW_SAMPLE 1
@@ -54,8 +54,18 @@ static unixctl_cb_func test_sflow_exit;
 
 /* Structure element tag numbers. */
 #define SFLOW_TAG_CTR_IFCOUNTERS 1
+#define SFLOW_TAG_CTR_LACPCOUNTERS 7
+#define SFLOW_TAG_CTR_OPENFLOWPORT 1004
+#define SFLOW_TAG_CTR_PORTNAME 1005
 #define SFLOW_TAG_PKT_HEADER 1
 #define SFLOW_TAG_PKT_SWITCH 1001
+#define SFLOW_TAG_PKT_TUNNEL4_OUT 1023
+#define SFLOW_TAG_PKT_TUNNEL4_IN 1024
+#define SFLOW_TAG_PKT_TUNNEL_VNI_OUT 1029
+#define SFLOW_TAG_PKT_TUNNEL_VNI_IN 1030
+
+/* string sizes */
+#define SFL_MAX_PORTNAME_LEN 255
 
 struct sflow_addr {
     enum {
@@ -82,7 +92,7 @@ struct sflow_xdr {
 
     /* Agent. */
     struct sflow_addr agentAddr;
-    char agentIPStr[SFLOW_MAX_AGENTIP_STRLEN];
+    char agentIPStr[INET6_ADDRSTRLEN + 2];
     uint32_t subAgentId;
     uint32_t uptime_mS;
 
@@ -99,7 +109,14 @@ struct sflow_xdr {
     struct {
         uint32_t HEADER;
         uint32_t SWITCH;
+       uint32_t TUNNEL4_OUT;
+       uint32_t TUNNEL4_IN;
+       uint32_t TUNNEL_VNI_OUT;
+       uint32_t TUNNEL_VNI_IN;
         uint32_t IFCOUNTERS;
+       uint32_t LACPCOUNTERS;
+       uint32_t OPENFLOWPORT;
+       uint32_t PORTNAME;
     } offset;
 
     /* Flow sample fields. */
@@ -221,6 +238,63 @@ process_counter_sample(struct sflow_xdr *x)
         printf(" promiscuous=%"PRIu32, sflowxdr_next(x));
         printf("\n");
     }
+    if (x->offset.LACPCOUNTERS) {
+       uint8_t *mac;
+       union {
+           ovs_be32 all;
+           struct {
+               uint8_t actorAdmin;
+               uint8_t actorOper;
+               uint8_t partnerAdmin;
+               uint8_t partnerOper;
+           } v;
+       } state;
+
+        sflowxdr_setc(x, x->offset.LACPCOUNTERS);
+        printf("LACPCOUNTERS");
+       mac = (uint8_t *)sflowxdr_str(x);
+       printf(" sysID="ETH_ADDR_FMT, ETH_ADDR_ARGS(mac));
+       sflowxdr_skip(x, 2);
+       mac = (uint8_t *)sflowxdr_str(x);
+       printf(" partnerID="ETH_ADDR_FMT, ETH_ADDR_ARGS(mac));
+       sflowxdr_skip(x, 2);
+       printf(" aggID=%"PRIu32, sflowxdr_next(x));
+       state.all = sflowxdr_next_n(x);
+       printf(" actorAdmin=0x%"PRIx32, state.v.actorAdmin);
+       printf(" actorOper=0x%"PRIx32, state.v.actorOper);
+       printf(" partnerAdmin=0x%"PRIx32, state.v.partnerAdmin);
+       printf(" partnerOper=0x%"PRIx32, state.v.partnerOper);
+       printf(" LACPUDsRx=%"PRIu32, sflowxdr_next(x));
+       printf(" markerPDUsRx=%"PRIu32, sflowxdr_next(x));
+       printf(" markerRespPDUsRx=%"PRIu32, sflowxdr_next(x));
+       printf(" unknownRx=%"PRIu32, sflowxdr_next(x));
+       printf(" illegalRx=%"PRIu32, sflowxdr_next(x));
+       printf(" LACPUDsTx=%"PRIu32, sflowxdr_next(x));
+       printf(" markerPDUsTx=%"PRIu32, sflowxdr_next(x));
+       printf(" markerRespPDUsTx=%"PRIu32, sflowxdr_next(x));
+        printf("\n");
+    }
+    if (x->offset.OPENFLOWPORT) {
+        sflowxdr_setc(x, x->offset.OPENFLOWPORT);
+        printf("OPENFLOWPORT");
+        printf(" datapath_id=%"PRIu64, sflowxdr_next_int64(x));
+        printf(" port_no=%"PRIu32, sflowxdr_next(x));
+       printf("\n");
+    }
+    if (x->offset.PORTNAME) {
+       uint32_t pnLen;
+       const char *pnBytes;
+       char portName[SFL_MAX_PORTNAME_LEN + 1];
+        sflowxdr_setc(x, x->offset.PORTNAME);
+        printf("PORTNAME");
+       pnLen = sflowxdr_next(x);
+       SFLOWXDR_assert(x, (pnLen <= SFL_MAX_PORTNAME_LEN));
+       pnBytes = sflowxdr_str(x);
+       memcpy(portName, pnBytes, pnLen);
+       portName[pnLen] = '\0';
+       printf(" portName=%s", portName);
+       printf("\n");
+    }
 }
 
 static char
@@ -251,6 +325,25 @@ print_hex(const char *a, int len, char *buf, int bufLen)
     return b;
 }
 
+static void
+print_struct_ipv4(struct sflow_xdr *x, const char *prefix)
+{
+    ovs_be32 src, dst;
+
+    printf(" %s_length=%"PRIu32,    prefix, sflowxdr_next(x));
+    printf(" %s_protocol=%"PRIu32,  prefix, sflowxdr_next(x));
+
+    src = sflowxdr_next_n(x);
+    dst = sflowxdr_next_n(x);
+    printf(" %s_src="IP_FMT,        prefix, IP_ARGS(src));
+    printf(" %s_dst="IP_FMT,        prefix, IP_ARGS(dst));
+
+    printf(" %s_src_port=%"PRIu32,  prefix, sflowxdr_next(x));
+    printf(" %s_dst_port=%"PRIu32,  prefix, sflowxdr_next(x));
+    printf(" %s_tcp_flags=%"PRIu32, prefix, sflowxdr_next(x));
+    printf(" %s_tos=%"PRIu32,       prefix, sflowxdr_next(x));
+}
+
 #define SFLOW_HEX_SCRATCH 1024
 
 static void
@@ -266,6 +359,26 @@ process_flow_sample(struct sflow_xdr *x)
                x->agentIPStr, x->dsClass, x->dsIndex);
         printf(" fsSeqNo=%"PRIu32, x->fsSeqNo);
 
+        if (x->offset.TUNNEL4_IN) {
+            sflowxdr_setc(x, x->offset.TUNNEL4_IN);
+           print_struct_ipv4(x, "tunnel4_in");
+        }
+
+        if (x->offset.TUNNEL4_OUT) {
+            sflowxdr_setc(x, x->offset.TUNNEL4_OUT);
+           print_struct_ipv4(x, "tunnel4_out");
+        }
+
+        if (x->offset.TUNNEL_VNI_IN) {
+            sflowxdr_setc(x, x->offset.TUNNEL_VNI_IN);
+           printf( " tunnel_in_vni=%"PRIu32, sflowxdr_next(x));
+        }
+
+        if (x->offset.TUNNEL_VNI_OUT) {
+            sflowxdr_setc(x, x->offset.TUNNEL_VNI_OUT);
+           printf( " tunnel_out_vni=%"PRIu32, sflowxdr_next(x));
+        }
+
         if (x->offset.SWITCH) {
             sflowxdr_setc(x, x->offset.SWITCH);
             printf(" in_vlan=%"PRIu32, sflowxdr_next(x));
@@ -325,14 +438,12 @@ process_datagram(struct sflow_xdr *x)
 
     /* Store the agent address as a string. */
     if (x->agentAddr.type == SFLOW_ADDRTYPE_IP6) {
-        snprintf(x->agentIPStr, SFLOW_MAX_AGENTIP_STRLEN,
-                 "%04x:%04x:%04x:%04x",
-                 x->agentAddr.a.ip6[0],
-                 x->agentAddr.a.ip6[1],
-                 x->agentAddr.a.ip6[2],
-                 x->agentAddr.a.ip6[3]);
+        char ipstr[INET6_ADDRSTRLEN];
+        inet_ntop(AF_INET6, (const void *) &x->agentAddr.a.ip6,
+                  ipstr, INET6_ADDRSTRLEN);
+        snprintf(x->agentIPStr, sizeof x->agentIPStr, "[%s]", ipstr);
     } else {
-        snprintf(x->agentIPStr, SFLOW_MAX_AGENTIP_STRLEN,
+        snprintf(x->agentIPStr, sizeof x->agentIPStr,
                  IP_FMT, IP_ARGS(x->agentAddr.a.ip4));
     }
 
@@ -374,6 +485,15 @@ process_datagram(struct sflow_xdr *x)
                 case SFLOW_TAG_CTR_IFCOUNTERS:
                     sflowxdr_mark_unique(x, &x->offset.IFCOUNTERS);
                     break;
+                case SFLOW_TAG_CTR_LACPCOUNTERS:
+                    sflowxdr_mark_unique(x, &x->offset.LACPCOUNTERS);
+                    break;
+                case SFLOW_TAG_CTR_PORTNAME:
+                    sflowxdr_mark_unique(x, &x->offset.PORTNAME);
+                    break;
+                case SFLOW_TAG_CTR_OPENFLOWPORT:
+                    sflowxdr_mark_unique(x, &x->offset.OPENFLOWPORT);
+                    break;
 
                     /* Add others here... */
                 }
@@ -442,6 +562,22 @@ process_datagram(struct sflow_xdr *x)
                     sflowxdr_mark_unique(x, &x->offset.SWITCH);
                     break;
 
+               case SFLOW_TAG_PKT_TUNNEL4_OUT:
+                    sflowxdr_mark_unique(x, &x->offset.TUNNEL4_OUT);
+                    break;
+
+               case SFLOW_TAG_PKT_TUNNEL4_IN:
+                    sflowxdr_mark_unique(x, &x->offset.TUNNEL4_IN);
+                    break;
+
+               case SFLOW_TAG_PKT_TUNNEL_VNI_OUT:
+                    sflowxdr_mark_unique(x, &x->offset.TUNNEL_VNI_OUT);
+                    break;
+
+               case SFLOW_TAG_PKT_TUNNEL_VNI_IN:
+                    sflowxdr_mark_unique(x, &x->offset.TUNNEL_VNI_IN);
+                    break;
+
                     /* Add others here... */
                 }
 
@@ -471,13 +607,13 @@ static void
 print_sflow(struct ofpbuf *buf)
 {
     char *dgram_buf;
-    int dgram_len = buf->size;
+    int dgram_len = ofpbuf_size(buf);
     struct sflow_xdr xdrDatagram;
     struct sflow_xdr *x = &xdrDatagram;
 
     memset(x, 0, sizeof *x);
     if (SFLOWXDR_try(x)) {
-        SFLOWXDR_assert(x, (dgram_buf = ofpbuf_try_pull(buf, buf->size)));
+        SFLOWXDR_assert(x, (dgram_buf = ofpbuf_try_pull(buf, ofpbuf_size(buf))));
         sflowxdr_init(x, dgram_buf, dgram_len);
         SFLOWXDR_assert(x, dgram_len >= SFLOW_MIN_LEN);
         process_datagram(x);
@@ -487,8 +623,8 @@ print_sflow(struct ofpbuf *buf)
     }
 }
 
-int
-main(int argc, char *argv[])
+static void
+test_sflow_main(int argc, char *argv[])
 {
     struct unixctl_server *server;
     enum { MAX_RECV = 1500 };
@@ -500,6 +636,7 @@ main(int argc, char *argv[])
 
     proctitle_init(argc, argv);
     set_program_name(argv[0]);
+    service_start(&argc, &argv);
     parse_options(argc, argv);
 
     if (argc - optind != 1) {
@@ -508,9 +645,9 @@ main(int argc, char *argv[])
     }
     target = argv[optind];
 
-    sock = inet_open_passive(SOCK_DGRAM, target, 0, NULL, 0);
+    sock = inet_open_passive(SOCK_DGRAM, target, 0, NULL, 0, true);
     if (sock < 0) {
-        ovs_fatal(0, "%s: failed to open (%s)", argv[1], strerror(-sock));
+        ovs_fatal(0, "%s: failed to open (%s)", argv[1], ovs_strerror(-sock));
     }
 
     daemon_save_fd(STDOUT_FILENO);
@@ -532,7 +669,7 @@ main(int argc, char *argv[])
 
         ofpbuf_clear(&buf);
         do {
-            retval = read(sock, buf.data, buf.allocated);
+            retval = recv(sock, ofpbuf_data(&buf), buf.allocated, 0);
         } while (retval < 0 && errno == EINTR);
         if (retval > 0) {
             ofpbuf_put_uninit(&buf, retval);
@@ -548,8 +685,6 @@ main(int argc, char *argv[])
         unixctl_server_wait(server);
         poll_block();
     }
-
-    return 0;
 }
 
 static void
@@ -615,3 +750,5 @@ test_sflow_exit(struct unixctl_conn *conn,
     *exiting = true;
     unixctl_command_reply(conn, NULL);
 }
+
+OVSTEST_REGISTER("test-sflow", test_sflow_main);