Add pointers to headers to buffer, and initialize them in flow_extract.
authorBen Pfaff <blp@nicira.com>
Thu, 27 Mar 2008 22:09:32 +0000 (15:09 -0700)
committerBen Pfaff <blp@nicira.com>
Fri, 28 Mar 2008 00:50:33 +0000 (17:50 -0700)
This will be used in the userspace switch implementation.

include/buffer.h
include/flow.h
lib/buffer.c
lib/flow.c

index 98750244ad0f317cf107257ab331cfb430854ff0..9c3b0256ddd3e38c70754f74c461a7ce6e9dff56 100644 (file)
@@ -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 *);
index 63db5679ba451723024da0f2783cc036b10238c9..5134ef0a2acd547cfeb09255cd936d93b83e2d6e 100644 (file)
@@ -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);
index 0ce1045e1e5df2adc26499380b163b4113febf78..1a988d4c0e5b410858a20a92977539f920800639 100644 (file)
@@ -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;
 }
+
index bccc0efe8f1e00c03f128c3569e5670eb34f84ea..2ba560c9172f0f4ec0ef681f923c8586e70b3993 100644 (file)
@@ -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;