summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Eitzenberger <heitzenberger@astaro.com>2009-11-12 16:05:36 +0100
committerHarald Welte <laforge@gnumonks.org>2010-10-21 19:15:39 +0200
commit3b4a92b5daed8dfbf502f01d253831507a71c1be (patch)
tree38b2780b1c77c9489d077aa8eab5ba4806eae5e2
parentb9c73a89fe179a81d66d420f24a1f50a0f3a8014 (diff)
IPFIX: implement basic support for Set 256 (Vineyard)
Signed-off-by: Holger Eitzenberger <holger@eitzenberger.org>
-rw-r--r--output/ipfix/ipfix.c14
-rw-r--r--output/ipfix/ipfix.h46
-rw-r--r--output/ipfix/ulogd_output_IPFIX.c73
3 files changed, 87 insertions, 46 deletions
diff --git a/output/ipfix/ipfix.c b/output/ipfix/ipfix.c
index 1eb814a..7babef7 100644
--- a/output/ipfix/ipfix.c
+++ b/output/ipfix/ipfix.c
@@ -10,4 +10,18 @@
#include "ipfix.h"
+size_t
+ipfix_rec_len(uint16_t sid)
+{
+ BUG_ON(sid != htons(VY_IPFIX_SID));
+ return sizeof(struct vy_ipfix_data);
+}
+size_t
+ipfix_msg_len(const struct ipfix_hdr *hdr)
+{
+ struct ipfix_set_hdr *shdr = (struct ipfix_set_hdr *)hdr->data;
+
+ /* TODO count all sets */
+ return IPFIX_HDRLEN + shdr->len;
+}
diff --git a/output/ipfix/ipfix.h b/output/ipfix/ipfix.h
index bdca3b4..cd51b2b 100644
--- a/output/ipfix/ipfix.h
+++ b/output/ipfix/ipfix.h
@@ -14,10 +14,12 @@ struct ipfix_hdr {
uint16_t version;
uint16_t len;
uint32_t time;
- uint32_t seq;
- uint32_t odid; /* Observation Domain ID */
+ uint32_t seqno;
+ uint32_t oid; /* Observation Domain ID */
uint8_t data[];
-};
+} __packed;
+
+#define IPFIX_HDRLEN sizeof(struct ipfix_hdr)
/*
* IDs 0-255 are reserved for Template Sets. IDs of Data Sets are > 255.
@@ -26,7 +28,7 @@ struct ipfix_templ_hdr {
uint16_t id;
uint16_t cnt;
uint8_t data[];
-};
+} __packed;
struct ipfix_set_hdr {
#define IPFIX_SET_TEMPL 2
@@ -34,20 +36,10 @@ struct ipfix_set_hdr {
uint16_t id;
uint16_t len;
uint8_t data[];
-};
-
-/* Vineyard IPFIX-like protocol */
-struct vy_ipfix_hdr {
-#define VY_IPFIX_VERSION 'A'
- uint16_t version;
- uint8_t cnt; /* RecordCount */
- uint32_t dev_id;
- uint32_t uptime; /* milliseconds */
- uint32_t unix_secs;
- uint32_t unix_nsecs;
- uint8_t data[];
} __packed;
+#define IPFIX_SET_HDRLEN sizeof(struct ipfix_set_hdr)
+
struct vy_ipfix_data {
struct sockaddr_in saddr;
struct sockaddr_in daddr;
@@ -55,16 +47,26 @@ struct vy_ipfix_data {
uint16_t ifi_out;
uint32_t packets;
uint32_t bytes;
- uint32_t start; /* milliseconds */
- uint32_t end; /* milliseconds */
+ uint32_t start; /* Unix time */
+ uint32_t end; /* Unix time */
uint16_t sport;
uint16_t dport;
+ uint32_t aid; /* Application ID */
uint8_t l4_proto;
uint8_t dscp;
- uint32_t appsig;
- uint32_t retrans_rate;
- uint32_t rtt;
- uint8_t policy; /* discard, shape, ... */
+ uint16_t __padding;
} __packed;
+#define VY_IPFIX_SID 256
+
+#define VY_IPFIX_FLOWS 36
+#define VY_IPFIX_PKT_LEN (IPFIX_HDRLEN + IPFIX_SET_HDRLEN \
+ + VY_IPFIX_FLOWS * sizeof(struct vy_ipfix_data))
+
+/* template management */
+size_t ipfix_rec_len(uint16_t);
+
+/* message handling */
+size_t ipfix_msg_len(const struct ipfix_hdr *);
+
#endif /* IPFIX_H */
diff --git a/output/ipfix/ulogd_output_IPFIX.c b/output/ipfix/ulogd_output_IPFIX.c
index 99ec11f..1e55d34 100644
--- a/output/ipfix/ulogd_output_IPFIX.c
+++ b/output/ipfix/ulogd_output_IPFIX.c
@@ -19,6 +19,7 @@
#include <ulogd/common.h>
#include <ulogd/plugin.h>
#include <unistd.h>
+#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
@@ -66,9 +67,10 @@ struct ipfix_flow {
struct ipfix_priv {
struct ulogd_fd ufd;
uint32_t seqno;
- struct vy_ipfix_hdr *hdr;
+ struct ipfix_hdr *hdr;
char *end;
int num_flows;
+ int set_len;
struct ipfix_templ *templates;
int proto;
struct ulogd_timer timer;
@@ -91,6 +93,7 @@ enum {
InL4SPort,
InL4DPort,
InIpProto,
+ InCtMark,
};
static struct ulogd_key ipfix_in_keys[] = {
@@ -109,6 +112,7 @@ static struct ulogd_key ipfix_in_keys[] = {
[InL4SPort] = KEY(UINT16, "l4.sport"),
[InL4DPort] = KEY(UINT16, "l4.dport"),
[InIpProto] = KEY(UINT8, "ip.protocol"),
+ [InCtMark] = KEY(UINT32, "ct.mark"),
};
static int
@@ -168,7 +172,7 @@ ipfix_configure(struct ulogd_pluginstance *pi)
upi_log(pi, ULOGD_FATAL, "inet_pton: %m\n");
return ULOGD_IRET_ERR;
} else if (!ret) {
- upi_log(pi, ULOGD_FATAL, "host: invalid address\n");
+ upi_log(pi, ULOGD_FATAL, "host: invalid address '%s'\n", host_ce(pi));
return ULOGD_IRET_ERR;
}
@@ -225,7 +229,9 @@ static int
ipfix_start(struct ulogd_pluginstance *pi)
{
struct ipfix_priv *priv = upi_priv(pi);
- struct vy_ipfix_hdr *hdr = priv->hdr;
+ struct ipfix_hdr *hdr;
+ struct ipfix_set_hdr *shdr;
+ struct vy_ipfix_data *data;
char addr[16];
int ret;
@@ -252,16 +258,17 @@ ipfix_start(struct ulogd_pluginstance *pi)
ulogd_register_timer(&priv->timer);
- hdr = priv->hdr = malloc(sizeof(struct vy_ipfix_hdr)
- + 2 * sizeof(struct vy_ipfix_data));
- if (!priv->hdr) {
+ if ((hdr = priv->hdr = malloc(VY_IPFIX_PKT_LEN)) == NULL) {
upi_log(pi, ULOGD_ERROR, "out of memory\n");
return -1;
}
- hdr->version = VY_IPFIX_VERSION;
- hdr->cnt = 2;
- hdr->dev_id = 42;
+ memset(hdr, 0, IPFIX_HDRLEN + IPFIX_SET_HDRLEN);
+ shdr = (struct ipfix_set_hdr *)hdr->data;
+ data = (struct vy_ipfix_data *)shdr->data;
+ hdr->version = htons(IPFIX_VERSION);
+ hdr->oid = htonl(oid_ce(pi));
+ shdr->id = htons(VY_IPFIX_SID);
return ULOGD_IRET_OK;
}
@@ -284,38 +291,56 @@ ipfix_interp(struct ulogd_pluginstance *pi, unsigned *flags)
{
struct ipfix_priv *priv = upi_priv(pi);
struct ulogd_key *in = pi->input.keys;
- struct vy_ipfix_hdr *hdr = priv->hdr;
+ struct ipfix_hdr *hdr = priv->hdr;
+ struct ipfix_set_hdr *shdr;
struct vy_ipfix_data *data;
int ret;
BUG_ON(priv->num_flows < 0 || priv->num_flows >= 2);
- data = ((struct vy_ipfix_data *)hdr->data) + priv->num_flows;
+ BUG_ON(!hdr);
+ shdr = (struct ipfix_set_hdr *)hdr->data;
+ data = (struct vy_ipfix_data *)shdr->data + priv->num_flows;
if (!key_src_valid(&in[InIpSaddr]))
return ULOGD_IRET_OK;
key_src_in(&in[InIpSaddr], &data->saddr.sin_addr);
key_src_in(&in[InIpDaddr], &data->daddr.sin_addr);
- data->ifi_in = data->ifi_out = 0U;
- data->packets = (uint32_t)(key_src_u64(&in[InRawInPktCount])
- + key_src_u64(&in[InRawOutPktCount]));
- data->bytes = (uint32_t)(key_src_u64(&in[InRawInPktLen])
- + key_src_u64(&in[InRawOutPktLen]));
- data->start = key_src_u32(&in[InFlowStartSec])
- + key_src_u32(&in[InFlowStartUsec]) / 1000;
- data->end = key_src_u32(&in[InFlowEndSec])
- + key_src_u32(&in[InFlowEndUsec]) / 1000;
+ data->ifi_in = data->ifi_out = htons(1);
+
+ data->packets = htonl((uint32_t)(key_src_u64(&in[InRawInPktCount])
+ + key_src_u64(&in[InRawOutPktCount])));
+ data->bytes = htonl((uint32_t)(key_src_u64(&in[InRawInPktLen])
+ + key_src_u64(&in[InRawOutPktLen])));
+
+ data->start = htonl(key_src_u32(&in[InFlowStartSec]));
+ data->end = htonl(key_src_u32(&in[InFlowEndSec]));
+
if (key_src_valid(&in[InL4SPort])) {
- data->sport = key_src_u16(&in[InL4SPort]);
- data->dport = key_src_u16(&in[InL4DPort]);
+ data->sport = htons(key_src_u16(&in[InL4SPort]));
+ data->dport = htons(key_src_u16(&in[InL4DPort]));
}
+
+ if (key_src_valid(&in[InCtMark]))
+ data->aid = htonl(key_u32(&in[InCtMark]));
+ else
+ data->aid = 0;
data->l4_proto = key_src_u8(&in[InIpProto]);
data->dscp = 0;
+
+ priv->set_len += ipfix_rec_len(htons(VY_IPFIX_SID));
if (++priv->num_flows >= 2) {
- ret = send(priv->ufd.fd, priv->hdr, sizeof(struct vy_ipfix_hdr)
- + 2 * sizeof(struct vy_ipfix_data), 0);
+ hdr->time = htonl(time(NULL));
+ hdr->seqno = htonl(++priv->seqno);
+ shdr->len = htons(priv->set_len);
+ hdr->len = htons(IPFIX_HDRLEN + htons(shdr->len));
+
+ ret = send(priv->ufd.fd, priv->hdr, IPFIX_HDRLEN + priv->set_len, 0);
+
priv->num_flows = 0;
+ priv->set_len = 0;
+ shdr->len = 0;
}
return 0;