*/
#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"
#include "util.h"
#include "vlog.h"
-static void usage(void) NO_RETURN;
+NO_RETURN static void usage(void);
static void parse_options(int argc, char *argv[]);
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 {
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. */
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
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
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));
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... */
}
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... */
}
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);
}
}
-int
-main(int argc, char *argv[])
+static void
+test_sflow_main(int argc, char *argv[])
{
struct unixctl_server *server;
enum { MAX_RECV = 1500 };
proctitle_init(argc, argv);
set_program_name(argv[0]);
+ service_start(&argc, &argv);
parse_options(argc, argv);
if (argc - optind != 1) {
}
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], ovs_strerror(-sock));
}
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);
unixctl_server_wait(server);
poll_block();
}
-
- return 0;
}
static void
*exiting = true;
unixctl_command_reply(conn, NULL);
}
+
+OVSTEST_REGISTER("test-sflow", test_sflow_main);