From: Ben Pfaff Date: Wed, 28 Aug 2013 05:10:22 +0000 (-0700) Subject: packets, pktbuf: Align L3 headers on 32-bit boundary. X-Git-Tag: sliver-openvswitch-2.0.90-1~18^2~1 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=bb622f82d709e7468a5bc9eb4f038ce9343f74f6;p=sliver-openvswitch.git packets, pktbuf: Align L3 headers on 32-bit boundary. Memory access tends to be faster when data is properly aligned. Signed-off-by: Ben Pfaff --- diff --git a/lib/packets.c b/lib/packets.c index 07cc015ad..d15c402fb 100644 --- a/lib/packets.c +++ b/lib/packets.c @@ -152,9 +152,9 @@ compose_rarp(struct ofpbuf *b, const uint8_t eth_src[ETH_ADDR_LEN]) struct arp_eth_header *arp; ofpbuf_clear(b); - ofpbuf_prealloc_tailroom(b, ETH_HEADER_LEN + VLAN_HEADER_LEN + ofpbuf_prealloc_tailroom(b, 2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + ARP_ETH_HEADER_LEN); - ofpbuf_reserve(b, VLAN_HEADER_LEN); + ofpbuf_reserve(b, 2 + VLAN_HEADER_LEN); eth = ofpbuf_put_uninit(b, sizeof *eth); memcpy(eth->eth_dst, eth_addr_broadcast, ETH_ADDR_LEN); memcpy(eth->eth_src, eth_src, ETH_ADDR_LEN); @@ -396,13 +396,16 @@ pop_mpls(struct ofpbuf *packet, ovs_be16 ethtype) /* Converts hex digits in 'hex' to an Ethernet packet in '*packetp'. The * caller must free '*packetp'. On success, returns NULL. On failure, returns - * an error message and stores NULL in '*packetp'. */ + * an error message and stores NULL in '*packetp'. + * + * Aligns the L3 header of '*packetp' on a 32-bit boundary. */ const char * eth_from_hex(const char *hex, struct ofpbuf **packetp) { struct ofpbuf *packet; - packet = *packetp = ofpbuf_new(strlen(hex) / 2); + /* Use 2 bytes of headroom to 32-bit align the L3 header. */ + packet = *packetp = ofpbuf_new_with_headroom(strlen(hex) / 2, 2); if (ofpbuf_put_hex(packet, hex, NULL)[0] != '\0') { ofpbuf_delete(packet); @@ -603,7 +606,8 @@ ipv6_is_cidr(const struct in6_addr *netmask) * 'eth_src' and 'eth_type' parameters. A payload of 'size' bytes is allocated * in 'b' and returned. This payload may be populated with appropriate * information by the caller. Sets 'b''s 'l2' and 'l3' pointers to the - * Ethernet header and payload respectively. + * Ethernet header and payload respectively. Aligns b->l3 on a 32-bit + * boundary. * * The returned packet has enough headroom to insert an 802.1Q VLAN header if * desired. */ @@ -617,8 +621,10 @@ eth_compose(struct ofpbuf *b, const uint8_t eth_dst[ETH_ADDR_LEN], ofpbuf_clear(b); - ofpbuf_prealloc_tailroom(b, ETH_HEADER_LEN + VLAN_HEADER_LEN + size); - ofpbuf_reserve(b, VLAN_HEADER_LEN); + /* The magic 2 here ensures that the L3 header (when it is added later) + * will be 32-bit aligned. */ + ofpbuf_prealloc_tailroom(b, 2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + size); + ofpbuf_reserve(b, 2 + VLAN_HEADER_LEN); eth = ofpbuf_put_uninit(b, ETH_HEADER_LEN); data = ofpbuf_put_uninit(b, size); diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index 63d26872e..d6a8a0bd9 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -1072,6 +1072,7 @@ struct ofproto_class { * flow->tunnel and flow->in_port, which are assigned the correct values * for the incoming packet. The register values are zeroed. 'packet''s * header pointers (e.g. packet->l3) are appropriately initialized. + * packet->l3 is aligned on a 32-bit boundary. * * The implementation should add the statistics for 'packet' into 'rule'. * diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 85fad04fb..1173936e9 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -2525,8 +2525,8 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh) goto exit_free_ofpacts; } } else { - payload = xmalloc(sizeof *payload); - ofpbuf_use_const(payload, po.packet, po.packet_len); + /* Ensure that the L3 header is 32-bit aligned. */ + payload = ofpbuf_clone_data_with_headroom(po.packet, po.packet_len, 2); } /* Verify actions against packet, then send packet if successful. */ diff --git a/ofproto/pktbuf.c b/ofproto/pktbuf.c index 65fcef680..38ec34853 100644 --- a/ofproto/pktbuf.c +++ b/ofproto/pktbuf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -119,9 +119,9 @@ pktbuf_save(struct pktbuf *pb, const void *buffer, size_t buffer_size, if (++p->cookie >= COOKIE_MAX) { p->cookie = 0; } - p->buffer = ofpbuf_clone_data_with_headroom(buffer, buffer_size, - sizeof(struct ofp10_packet_in)); + /* Use 2 bytes of headroom to 32-bit align the L3 header. */ + p->buffer = ofpbuf_clone_data_with_headroom(buffer, buffer_size, 2); p->timeout = time_msec() + OVERWRITE_MSECS; p->in_port = in_port; @@ -165,8 +165,7 @@ pktbuf_get_null(void) * * 'in_port' may be NULL if the input port is not of interest. * - * A returned packet will have at least sizeof(struct ofp10_packet_in) bytes of - * headroom. + * The L3 header of a returned packet will be 32-bit aligned. * * On failure, stores NULL in in '*bufferp' and UINT16_MAX in '*in_port'. */ enum ofperr