/*
- * Copyright (c) 2009, 2010, 2012, 2013 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2012, 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <sys/stat.h>
#include "byte-order.h"
#include "compiler.h"
+#include "dp-packet.h"
#include "flow.h"
#include "hmap.h"
-#include "ofpbuf.h"
#include "packets.h"
#include "timeval.h"
#include "unaligned.h"
-#include "vlog.h"
+#include "openvswitch/vlog.h"
VLOG_DEFINE_THIS_MODULE(pcap);
}
int
-ovs_pcap_read(FILE *file, struct ofpbuf **bufp, long long int *when)
+ovs_pcap_read(FILE *file, struct dp_packet **bufp, long long int *when)
{
struct pcaprec_hdr prh;
- struct ofpbuf *buf;
+ struct dp_packet *buf;
void *data;
size_t len;
bool swap;
}
/* Read packet. */
- buf = ofpbuf_new(len);
- data = ofpbuf_put_uninit(buf, len);
+ buf = dp_packet_new(len);
+ data = dp_packet_put_uninit(buf, len);
if (fread(data, len, 1, file) != 1) {
int error = ferror(file) ? errno : EOF;
VLOG_WARN("failed to read pcap packet: %s",
ovs_retval_to_string(error));
- ofpbuf_delete(buf);
+ dp_packet_delete(buf);
return error;
}
*bufp = buf;
}
void
-ovs_pcap_write(FILE *file, struct ofpbuf *buf)
+ovs_pcap_write(FILE *file, struct dp_packet *buf)
{
struct pcaprec_hdr prh;
struct timeval tv;
xgettimeofday(&tv);
prh.ts_sec = tv.tv_sec;
prh.ts_usec = tv.tv_usec;
- prh.incl_len = buf->size;
- prh.orig_len = buf->size;
+ prh.incl_len = dp_packet_size(buf);
+ prh.orig_len = dp_packet_size(buf);
ignore(fwrite(&prh, sizeof prh, 1, file));
- ignore(fwrite(buf->data, buf->size, 1, file));
+ ignore(fwrite(dp_packet_data(buf), dp_packet_size(buf), 1, file));
}
\f
struct tcp_key {
struct hmap_node hmap_node;
struct tcp_key key;
uint32_t seq_no;
- struct ofpbuf payload;
+ struct dp_packet payload;
};
struct tcp_reader {
tcp_stream_destroy(struct tcp_reader *r, struct tcp_stream *stream)
{
hmap_remove(&r->streams, &stream->hmap_node);
- ofpbuf_uninit(&stream->payload);
+ dp_packet_uninit(&stream->payload);
free(stream);
}
}
static struct tcp_stream *
-tcp_stream_lookup(struct tcp_reader *r, const struct flow *flow)
+tcp_stream_lookup(struct tcp_reader *r,
+ const struct tcp_key *key, uint32_t hash)
{
struct tcp_stream *stream;
- struct tcp_key key;
- uint32_t hash;
-
- memset(&key, 0, sizeof key);
- key.nw_src = flow->nw_src;
- key.nw_dst = flow->nw_dst;
- key.tp_src = flow->tp_src;
- key.tp_dst = flow->tp_dst;
- hash = hash_bytes(&key, sizeof key, 0);
HMAP_FOR_EACH_WITH_HASH (stream, hmap_node, hash, &r->streams) {
- if (!memcmp(&stream->key, &key, sizeof key)) {
+ if (!memcmp(&stream->key, key, sizeof *key)) {
return stream;
}
}
+ return NULL;
+}
+
+static struct tcp_stream *
+tcp_stream_new(struct tcp_reader *r, const struct tcp_key *key, uint32_t hash)
+{
+ struct tcp_stream *stream;
stream = xmalloc(sizeof *stream);
hmap_insert(&r->streams, &stream->hmap_node, hash);
- memcpy(&stream->key, &key, sizeof key);
+ memcpy(&stream->key, key, sizeof *key);
stream->seq_no = 0;
- ofpbuf_init(&stream->payload, 2048);
+ dp_packet_init(&stream->payload, 2048);
return stream;
}
* extracted the packet's headers into 'flow', using flow_extract().
*
* If 'packet' is a TCP packet, then the reader attempts to reconstruct the
- * data stream. If successful, it returns an ofpbuf that represents the data
- * stream so far. The caller may examine the data in the ofpbuf and pull off
+ * data stream. If successful, it returns an dp_packet that represents the data
+ * stream so far. The caller may examine the data in the dp_packet and pull off
* any data that it has fully processed. The remaining data that the caller
* does not pull off will be presented again in future calls if more data
* arrives in the stream.
*
* Returns null if 'packet' doesn't add new data to a TCP stream. */
-struct ofpbuf *
+struct dp_packet *
tcp_reader_run(struct tcp_reader *r, const struct flow *flow,
- const struct ofpbuf *packet)
+ const struct dp_packet *packet)
{
struct tcp_stream *stream;
struct tcp_header *tcp;
- struct ofpbuf *payload;
+ struct dp_packet *payload;
+ unsigned int l7_length;
+ struct tcp_key key;
+ uint32_t hash;
uint32_t seq;
uint8_t flags;
+ const char *l7 = dp_packet_get_tcp_payload(packet);
if (flow->dl_type != htons(ETH_TYPE_IP)
|| flow->nw_proto != IPPROTO_TCP
- || !packet->l7) {
+ || !l7) {
return NULL;
}
-
- stream = tcp_stream_lookup(r, flow);
- payload = &stream->payload;
-
- tcp = packet->l4;
+ tcp = dp_packet_l4(packet);
flags = TCP_FLAGS(tcp->tcp_ctl);
+ l7_length = (char *) dp_packet_tail(packet) - l7;
seq = ntohl(get_16aligned_be32(&tcp->tcp_seq));
- if (flags & TCP_SYN) {
- ofpbuf_clear(payload);
+
+ /* Construct key. */
+ memset(&key, 0, sizeof key);
+ key.nw_src = flow->nw_src;
+ key.nw_dst = flow->nw_dst;
+ key.tp_src = flow->tp_src;
+ key.tp_dst = flow->tp_dst;
+ hash = hash_bytes(&key, sizeof key, 0);
+
+ /* Find existing stream or start a new one for a SYN or if there's data. */
+ stream = tcp_stream_lookup(r, &key, hash);
+ if (!stream) {
+ if (flags & TCP_SYN || l7_length) {
+ stream = tcp_stream_new(r, &key, hash);
+ stream->seq_no = flags & TCP_SYN ? seq + 1 : seq;
+ } else {
+ return NULL;
+ }
+ }
+
+ payload = &stream->payload;
+ if (flags & TCP_SYN || !stream->seq_no) {
+ dp_packet_clear(payload);
stream->seq_no = seq + 1;
return NULL;
} else if (flags & (TCP_FIN | TCP_RST)) {
tcp_stream_destroy(r, stream);
return NULL;
} else if (seq == stream->seq_no) {
- size_t length;
-
/* Shift all of the existing payload to the very beginning of the
* allocated space, so that we reuse allocated space instead of
* continually expanding it. */
- ofpbuf_shift(payload, (char *) payload->base - (char *) payload->data);
+ dp_packet_shift(payload, (char *) dp_packet_base(payload) - (char *) dp_packet_data(payload));
- length = (char *) ofpbuf_end(packet) - (char *) packet->l7;
- ofpbuf_put(payload, packet->l7, length);
- stream->seq_no += length;
+ dp_packet_put(payload, l7, l7_length);
+ stream->seq_no += l7_length;
return payload;
} else {
return NULL;