#include "cfg.h"
#include "flow.h"
#include "netflow.h"
+#include "ofproto.h"
#include "packets.h"
#include "socket-util.h"
#include "svec.h"
}
void
-netflow_expire(struct netflow *nf, const flow_t *flow,
- const struct odp_flow_stats *stats,
- long long int created)
+netflow_expire(struct netflow *nf, const struct ofexpired *expired)
{
struct netflow_v5_header nf_hdr;
struct netflow_v5_record nf_rec;
struct timeval now;
- long long int used;
int i;
time_timeval(&now);
nf_hdr.sampling_interval = htons(0);
memset(&nf_rec, 0, sizeof nf_rec);
- nf_rec.src_addr = flow->nw_src;
- nf_rec.dst_addr = flow->nw_dst;
+ nf_rec.src_addr = expired->flow.nw_src;
+ nf_rec.dst_addr = expired->flow.nw_dst;
nf_rec.nexthop = htons(0);
- nf_rec.input = htons(flow->in_port);
+ nf_rec.input = htons(expired->flow.in_port);
nf_rec.output = htons(0);
- nf_rec.packet_count = htonl(stats->n_packets);
- nf_rec.byte_count = htonl(stats->n_bytes);
- nf_rec.init_time = htonl(created - nf->boot_time);
- used = stats->used_sec * 1000 + stats->used_nsec / 1000000;
- nf_rec.used_time = htonl((used > created ? used : created)
+ nf_rec.packet_count = htonl(expired->packet_count);
+ nf_rec.byte_count = htonl(expired->byte_count);
+ nf_rec.init_time = htonl(expired->created - nf->boot_time);
+ nf_rec.used_time = htonl(MAX(expired->created, expired->used)
- nf->boot_time);
- if (flow->nw_proto == IP_TYPE_ICMP) {
+ if (expired->flow.nw_proto == IP_TYPE_ICMP) {
/* In NetFlow, the ICMP type and code are concatenated and
* placed in the 'dst_port' field. */
- uint8_t type = ntohs(flow->tp_src);
- uint8_t code = ntohs(flow->tp_dst);
+ uint8_t type = ntohs(expired->flow.tp_src);
+ uint8_t code = ntohs(expired->flow.tp_dst);
nf_rec.src_port = htons(0);
nf_rec.dst_port = htons((type << 8) | code);
} else {
- nf_rec.src_port = flow->tp_src;
- nf_rec.dst_port = flow->tp_dst;
+ nf_rec.src_port = expired->flow.tp_src;
+ nf_rec.dst_port = expired->flow.tp_dst;
}
- nf_rec.tcp_flags = stats->tcp_flags;
- nf_rec.ip_proto = flow->nw_proto;
- nf_rec.ip_tos = stats->ip_tos;
+ nf_rec.tcp_flags = expired->tcp_flags;
+ nf_rec.ip_proto = expired->flow.nw_proto;
+ nf_rec.ip_tos = expired->ip_tos;
nf_rec.src_as = htons(0);
nf_rec.dst_as = htons(0);
#include "flow.h"
-struct odp_flow_stats;
+struct ofexpired;
struct svec;
struct netflow *netflow_create(void);
void netflow_destroy(struct netflow *);
int netflow_set_collectors(struct netflow *, const struct svec *collectors);
-void netflow_expire(struct netflow *, const flow_t *,
- const struct odp_flow_stats *,
- long long int created);
+void netflow_expire(struct netflow *, const struct ofexpired *);
#endif /* netflow.h */
queue_tx(buf, prev);
}
- if (p->netflow && !rule->cr.wc.wildcards) {
- /* XXX this interface isn't so great */
- struct odp_flow_stats stats;
- stats.n_packets = rule->packet_count;
- stats.n_bytes = rule->byte_count;
- stats.used_sec = rule->used / 1000;
- stats.used_nsec = rule->used % 1000 * 1000000;
- stats.tcp_flags = rule->tcp_flags;
- stats.ip_tos = rule->ip_tos;
- stats.reserved = 0;
- netflow_expire(p->netflow, &rule->cr.flow, &stats, rule->created);
+ if (!rule->cr.wc.wildcards && p->netflow) {
+ struct ofexpired expired;
+ expired.flow = rule->cr.flow;
+ expired.packet_count = rule->packet_count;
+ expired.byte_count = rule->byte_count;
+ expired.used = rule->used;
+ expired.created = rule->created;
+ expired.tcp_flags = rule->tcp_flags;
+ expired.ip_tos = rule->ip_tos;
+ netflow_expire(p->netflow, &expired);
}
}
struct ofproto;
struct svec;
+struct ofexpired {
+ flow_t flow;
+ uint64_t packet_count; /* Packets from *expired* subrules. */
+ uint64_t byte_count; /* Bytes from *expired* subrules. */
+ long long int used; /* Last-used time (0 if never used). */
+ long long int created; /* Creation time. */
+ uint8_t tcp_flags; /* Bitwise-OR of all TCP flags seen. */
+ uint8_t ip_tos; /* Last-seen IP type-of-service. */
+};
+
int ofproto_create(const char *datapath, struct ofproto **ofprotop);
void ofproto_destroy(struct ofproto *);
int ofproto_run(struct ofproto *);