From 76c58e37e36baf8e5f748061c6991dac5d110fe1 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 27 Mar 2008 15:09:32 -0700 Subject: [PATCH] Add pointers to headers to buffer, and initialize them in flow_extract. This will be used in the userspace switch implementation. --- include/buffer.h | 6 ++++++ include/flow.h | 2 +- lib/buffer.c | 39 +++++++++++++++++++++++++++++++++++++-- lib/flow.c | 8 +++++++- 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/include/buffer.h b/include/buffer.h index 98750244..9c3b0256 100644 --- a/include/buffer.h +++ b/include/buffer.h @@ -33,6 +33,10 @@ struct buffer { void *data; /* First byte actually in use. */ size_t size; /* Number of bytes in use. */ + void *l2; /* Link-level header. */ + void *l3; /* Network-level header. */ + void *l4; /* Transport-level header. */ + struct buffer *next; /* Next in a list of buffers. */ }; @@ -43,6 +47,7 @@ void buffer_uninit(struct buffer *); void buffer_reinit(struct buffer *, size_t); struct buffer *buffer_new(size_t); +struct buffer *buffer_clone(const struct buffer *); void buffer_delete(struct buffer *); void *buffer_at(const struct buffer *, size_t offset, size_t size); @@ -52,6 +57,7 @@ void *buffer_end(const struct buffer *); void *buffer_put_uninit(struct buffer *, size_t); void buffer_put(struct buffer *, const void *, size_t); +void *buffer_push_uninit(struct buffer *b, size_t); size_t buffer_headroom(struct buffer *); size_t buffer_tailroom(struct buffer *); diff --git a/include/flow.h b/include/flow.h index 63db5679..5134ef0a 100644 --- a/include/flow.h +++ b/include/flow.h @@ -25,7 +25,7 @@ struct flow { }; BUILD_ASSERT_DECL(sizeof (struct flow) == 32); -void flow_extract(const struct buffer *, uint16_t in_port, struct flow *); +void flow_extract(struct buffer *, uint16_t in_port, struct flow *); void flow_print(FILE *, const struct flow *); int flow_compare(const struct flow *, const struct flow *); unsigned long int flow_hash(const struct flow *, uint32_t basis); diff --git a/lib/buffer.c b/lib/buffer.c index 0ce1045e..1a988d4c 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -38,6 +38,7 @@ buffer_use(struct buffer *b, void *base, size_t allocated) b->base = b->data = base; b->allocated = allocated; b->size = 0; + b->l2 = b->l3 = b->l4 = NULL; b->next = NULL; } @@ -75,6 +76,15 @@ buffer_new(size_t size) return b; } +struct buffer * +buffer_clone(const struct buffer *buffer) +{ + /* FIXME: reference counting. */ + struct buffer *b = buffer_new(buffer->size); + buffer_put(b, buffer->data, buffer->size); + return b; +} + /* Frees memory that 'b' points to, as well as 'b' itself. */ void buffer_delete(struct buffer *b) @@ -109,17 +119,32 @@ void buffer_reserve_tailroom(struct buffer *b, size_t size) { if (size > buffer_tailroom(b)) { - size_t headroom = buffer_headroom(b); size_t new_allocated = b->allocated + MAX(size, 64); void *new_base = xmalloc(new_allocated); + uintptr_t base_delta = new_base - b->base; memcpy(new_base, b->base, b->allocated); free(b->base); b->base = new_base; b->allocated = new_allocated; - b->data = new_base + headroom; + b->data += base_delta; + if (b->l2) { + b->l2 += base_delta; + } + if (b->l3) { + b->l3 += base_delta; + } + if (b->l4) { + b->l4 += base_delta; + } } } +void +buffer_reserve_headroom(struct buffer *b, size_t size) +{ + assert(size <= buffer_headroom(b)); +} + /* Appends 'size' bytes of data to the tail end of 'b', reallocating and * copying its data if necessary. Returns a pointer to the first byte of the * new data, which is left uninitialized. */ @@ -141,6 +166,15 @@ buffer_put(struct buffer *b, const void *p, size_t size) memcpy(buffer_put_uninit(b, size), p, size); } +void * +buffer_push_uninit(struct buffer *b, size_t size) +{ + buffer_reserve_headroom(b, size); + b->data -= size; + b->size += size; + return b->data; +} + /* If 'b' contains at least 'offset + size' bytes of data, returns a pointer to * byte 'offset'. Otherwise, returns a null pointers. */ void * @@ -190,3 +224,4 @@ buffer_pull(struct buffer *b, size_t size) b->data += size; b->size -= size; } + diff --git a/lib/flow.c b/lib/flow.c index bccc0efe..2ba560c9 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -14,7 +14,7 @@ #define THIS_MODULE VLM_flow void -flow_extract(const struct buffer *packet, uint16_t in_port, struct flow *flow) +flow_extract(struct buffer *packet, uint16_t in_port, struct flow *flow) { struct buffer b = *packet; struct eth_header *eth; @@ -27,6 +27,10 @@ flow_extract(const struct buffer *packet, uint16_t in_port, struct flow *flow) memset(flow, 0, sizeof *flow); flow->in_port = htons(in_port); + packet->l2 = b.data; + packet->l3 = NULL; + packet->l4 = NULL; + eth = buffer_at(&b, 0, sizeof *eth); if (eth) { buffer_pull(&b, ETH_HEADER_LEN); @@ -64,12 +68,14 @@ flow_extract(const struct buffer *packet, uint16_t in_port, struct flow *flow) memcpy(flow->dl_src, eth->eth_src, ETH_ADDR_LEN); memcpy(flow->dl_dst, eth->eth_dst, ETH_ADDR_LEN); + packet->l3 = b.data; if (flow->dl_type == htons(ETH_TYPE_IP)) { const struct ip_header *nh = buffer_at(&b, 0, sizeof *nh); if (nh) { flow->nw_src = nh->ip_src; flow->nw_dst = nh->ip_dst; flow->nw_proto = nh->ip_proto; + packet->l4 = b.data + IP_HEADER_LEN; if (flow->nw_proto == IP_TYPE_TCP || flow->nw_proto == IP_TYPE_UDP) { int udp_ofs = IP_IHL(nh->ip_ihl_ver) * 4; -- 2.30.2