diff options
author | Bill Fischofer <bill.fischofer@linaro.org> | 2014-12-16 14:30:41 +0200 |
---|---|---|
committer | Maxim Uvarov <maxim.uvarov@linaro.org> | 2014-12-16 19:03:39 +0300 |
commit | 543fd5e56c6cf468ed25ccc8fe3e5c48a0c39fc2 (patch) | |
tree | d1dcf4689170a8940660a1cc5510f48faa49f9f3 /platform/linux-generic | |
parent | f91bb0688fef8e9cf0fa2986673e535dfbd386a8 (diff) |
api: packet: add head/tail room manipulation
Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>
Signed-off-by: Taras Kondratiuk <taras.kondratiuk@linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer@linaro.org>
Reviewed-by: Petri Savolainen <petri.savolainen@linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Diffstat (limited to 'platform/linux-generic')
-rw-r--r-- | platform/linux-generic/include/api/odp_packet.h | 275 | ||||
-rw-r--r-- | platform/linux-generic/include/odp_packet_internal.h | 33 | ||||
-rw-r--r-- | platform/linux-generic/odp_packet.c | 97 |
3 files changed, 346 insertions, 59 deletions
diff --git a/platform/linux-generic/include/api/odp_packet.h b/platform/linux-generic/include/api/odp_packet.h index cb5f17783..853709d92 100644 --- a/platform/linux-generic/include/api/odp_packet.h +++ b/platform/linux-generic/include/api/odp_packet.h @@ -113,6 +113,235 @@ odp_packet_t odp_packet_from_buffer(odp_buffer_t buf); */ odp_buffer_t odp_packet_to_buffer(odp_packet_t pkt); + +/* + * + * Pointers and lengths + * ******************************************************** + * + */ + +/** + * Packet head address + * + * Returns start address of the first segment. Packet level headroom starts + * from here. Use odp_packet_data() or odp_packet_l2_ptr() to return the + * packet data start address. + * + * @param pkt Packet handle + * + * @return Pointer to the start address of the first packet segment + * + * @see odp_packet_data(), odp_packet_l2_ptr(), odp_packet_headroom() + */ +void *odp_packet_head(odp_packet_t pkt); + +/** + * Total packet buffer length + * + * Returns sum of buffer lengths over all packet segments. + * + * @param pkt Packet handle + * + * @return Total packet buffer length in bytes + * + * @see odp_packet_reset() + */ +uint32_t odp_packet_buf_len(odp_packet_t pkt); + +/** + * Packet data pointer + * + * Returns the current packet data pointer. When a packet is received + * from packet input, this points to the first byte of the received + * packet. Packet level offsets are calculated relative to this position. + * + * User can adjust the data pointer with head_push/head_pull (does not modify + * segmentation) and add_data/rem_data calls (may modify segmentation). + * + * @param pkt Packet handle + * + * @return Pointer to the packet data + * + * @see odp_packet_l2_ptr(), odp_packet_seg_len() + */ +void *odp_packet_data(odp_packet_t pkt); + +/** + * Packet segment data length + * + * Returns number of data bytes following the current data pointer + * (odp_packet_data()) location in the segment. + * + * @param pkt Packet handle + * + * @return Segment data length in bytes (pointed by odp_packet_data()) + * + * @see odp_packet_data() + */ +uint32_t odp_packet_seg_len(odp_packet_t pkt); + +/** + * Packet data length + * + * Returns sum of data lengths over all packet segments. + * + * @param pkt Packet handle + * + * @return Packet data length + */ +uint32_t odp_packet_len(odp_packet_t pkt); + +/** + * Packet headroom length + * + * Returns the current packet level headroom length. + * + * @param pkt Packet handle + * + * @return Headroom length + */ +uint32_t odp_packet_headroom(odp_packet_t pkt); + +/** + * Packet tailroom length + * + * Returns the current packet level tailroom length. + * + * @param pkt Packet handle + * + * @return Tailroom length + */ +uint32_t odp_packet_tailroom(odp_packet_t pkt); + +/** + * Packet tailroom pointer + * + * Returns pointer to the start of the current packet level tailroom. + * + * User can adjust the tail pointer with tail_push/tail_pull (does not modify + * segmentation) and add_data/rem_data calls (may modify segmentation). + * + * @param pkt Packet handle + * + * @return Tailroom pointer + * + * @see odp_packet_tailroom() + */ +void *odp_packet_tail(odp_packet_t pkt); + +/** + * Push out packet head + * + * Increase packet data length by moving packet head into packet headroom. + * Packet headroom is decreased with the same amount. The packet head may be + * pushed out up to 'headroom' bytes. Packet is not modified if there's not + * enough headroom space. + * + * odp_packet_xxx: + * seg_len += len + * len += len + * headroom -= len + * data -= len + * + * Operation does not modify packet segmentation or move data. Handles and + * pointers remain valid. User is responsible to update packet meta-data + * offsets when needed. + * + * @param pkt Packet handle + * @param len Number of bytes to push the head (0 ... headroom) + * + * @return The new data pointer + * @retval NULL Requested offset exceeds available headroom + * + * @see odp_packet_headroom(), odp_packet_pull_head() + */ +void *odp_packet_push_head(odp_packet_t pkt, uint32_t len); + +/** + * Pull in packet head + * + * Decrease packet data length by removing data from the head of the packet. + * Packet headroom is increased with the same amount. Packet head may be pulled + * in up to seg_len - 1 bytes (i.e. packet data pointer must stay in the + * first segment). Packet is not modified if there's not enough data. + * + * odp_packet_xxx: + * seg_len -= len + * len -= len + * headroom += len + * data += len + * + * Operation does not modify packet segmentation or move data. Handles and + * pointers remain valid. User is responsible to update packet meta-data + * offsets when needed. + * + * @param pkt Packet handle + * @param len Number of bytes to pull the head (0 ... seg_len - 1) + * + * @return The new data pointer, or NULL in case of an error. + * @retval NULL Requested offset exceeds packet segment length + * + * @see odp_packet_seg_len(), odp_packet_push_head() + */ +void *odp_packet_pull_head(odp_packet_t pkt, uint32_t len); + +/** + * Push out packet tail + * + * Increase packet data length by moving packet tail into packet tailroom. + * Packet tailroom is decreased with the same amount. The packet tail may be + * pushed out up to 'tailroom' bytes. Packet is not modified if there's not + * enough tailroom. + * + * last_seg: + * data_len += len + * + * odp_packet_xxx: + * len += len + * tail += len + * tailroom -= len + * + * Operation does not modify packet segmentation or move data. Handles, + * pointers and offsets remain valid. + * + * @param pkt Packet handle + * @param len Number of bytes to push the tail (0 ... tailroom) + * + * @return The old tail pointer + * @retval NULL Requested offset exceeds available tailroom + * + * @see odp_packet_tailroom(), odp_packet_pull_tail() + */ +void *odp_packet_push_tail(odp_packet_t pkt, uint32_t len); + +/** + * Pull in packet tail + * + * Decrease packet data length by removing data from the tail of the packet. + * Packet tailroom is increased with the same amount. Packet tail may be pulled + * in up to last segment data_len - 1 bytes. (i.e. packet tail must stay in the + * last segment). Packet is not modified if there's not enough data. + * + * last_seg: + * data_len -= len + * + * odp_packet_xxx: + * len -= len + * tail -= len + * tailroom += len + * + * Operation does not modify packet segmentation or move data. Handles and + * pointers remain valid. User is responsible to update packet meta-data + * offsets when needed. + * + * @param pkt Packet handle + * @param len Number of bytes to pull the tail (0 ... last_seg:data_len - 1) + * + * @return The new tail pointer + * @retval NULL The specified offset exceeds allowable data length + */ +void *odp_packet_pull_tail(odp_packet_t pkt, uint32_t len); /** * Set the packet length * @@ -177,52 +406,6 @@ uint64_t odp_packet_user_u64(odp_packet_t pkt); void odp_packet_user_u64_set(odp_packet_t pkt, uint64_t ctx); /** - * Packet buffer start address - * - * Returns a pointer to the start of the packet buffer. The address is not - * necessarily the same as packet data address. E.g. on a received Ethernet - * frame, the protocol header may start 2 or 6 bytes within the buffer to - * ensure 32 or 64-bit alignment of the IP header. - * - * Use odp_packet_l2(pkt) to get the start address of a received valid frame - * or odp_packet_data(pkt) to get the current packet data address. - * - * @param pkt Packet handle - * - * @return Pointer to the start of the packet buffer - * - * @see odp_packet_l2(), odp_packet_data() - */ -uint8_t *odp_packet_addr(odp_packet_t pkt); - -/** - * Packet buffer maximum data size - * - * @note odp_packet_buf_size(pkt) != odp_packet_get_len(pkt), the former returns - * the max length of the buffer, the latter the size of a received packet. - * - * @param pkt Packet handle - * - * @return Packet buffer maximum data size - */ -size_t odp_packet_buf_size(odp_packet_t pkt); - -/** - * Packet data pointer - * - * Returns the current packet data pointer. When a packet is received - * from packet input, this points to the first byte of the received - * packet. Packet level offsets are calculated relative to this position. - * - * @param pkt Packet handle - * - * @return Pointer to the packet data - * - * @see odp_packet_l2(), odp_packet_addr() - */ -void *odp_packet_data(odp_packet_t pkt); - -/** * Layer 2 start pointer * * Returns pointer to the start of the layer 2 header. Optionally, outputs diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h index 83d0e923e..e1dc2d843 100644 --- a/platform/linux-generic/include/odp_packet_internal.h +++ b/platform/linux-generic/include/odp_packet_internal.h @@ -192,6 +192,39 @@ static inline void *packet_map(odp_packet_hdr_t *pkt_hdr, pkt_hdr->headroom + pkt_hdr->frame_len); } +#define pull_offset(x, len) (x = x < len ? 0 : x - len) + +static inline void push_head(odp_packet_hdr_t *pkt_hdr, size_t len) +{ + pkt_hdr->headroom -= len; + pkt_hdr->frame_len += len; + pkt_hdr->l2_offset += len; + pkt_hdr->l3_offset += len; + pkt_hdr->l4_offset += len; +} + +static inline void pull_head(odp_packet_hdr_t *pkt_hdr, size_t len) +{ + pkt_hdr->headroom += len; + pkt_hdr->frame_len -= len; + pull_offset(pkt_hdr->l2_offset, len); + pull_offset(pkt_hdr->l3_offset, len); + pull_offset(pkt_hdr->l4_offset, len); +} + +static inline void push_tail(odp_packet_hdr_t *pkt_hdr, size_t len) +{ + pkt_hdr->tailroom -= len; + pkt_hdr->frame_len += len; +} + + +static inline void pull_tail(odp_packet_hdr_t *pkt_hdr, size_t len) +{ + pkt_hdr->tailroom += len; + pkt_hdr->frame_len -= len; +} + static inline void packet_set_len(odp_packet_t pkt, uint32_t len) { odp_packet_hdr(pkt)->frame_len = len; diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c index ff05849f5..9f1854091 100644 --- a/platform/linux-generic/odp_packet.c +++ b/platform/linux-generic/odp_packet.c @@ -78,28 +78,106 @@ odp_buffer_t odp_packet_to_buffer(odp_packet_t pkt) return (odp_buffer_t)pkt; } -void odp_packet_set_len(odp_packet_t pkt, size_t len) +/* + * + * Pointers and lengths + * ******************************************************** + * + */ + +void *odp_packet_head(odp_packet_t pkt) +{ + odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); + return buffer_map(&pkt_hdr->buf_hdr, 0, NULL, 0); +} + +uint32_t odp_packet_buf_len(odp_packet_t pkt) +{ + return odp_packet_hdr(pkt)->buf_hdr.size; +} + +void *odp_packet_data(odp_packet_t pkt) { - odp_packet_hdr(pkt)->frame_len = len; + odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); + return packet_map(pkt_hdr, 0, NULL); +} + +uint32_t odp_packet_seg_len(odp_packet_t pkt) +{ + odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); + uint32_t seglen; + + /* Call returns length of 1st data segment */ + packet_map(pkt_hdr, 0, &seglen); + return seglen; } -size_t odp_packet_get_len(odp_packet_t pkt) +uint32_t odp_packet_len(odp_packet_t pkt) { return odp_packet_hdr(pkt)->frame_len; } -uint8_t *odp_packet_addr(odp_packet_t pkt) +uint32_t odp_packet_headroom(odp_packet_t pkt) +{ + return odp_packet_hdr(pkt)->headroom; +} + +uint32_t odp_packet_tailroom(odp_packet_t pkt) +{ + return odp_packet_hdr(pkt)->tailroom; +} + +void *odp_packet_tail(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - return buffer_map(&pkt_hdr->buf_hdr, 0, NULL, 0); + return packet_map(pkt_hdr, pkt_hdr->frame_len, NULL); } -void *odp_packet_data(odp_packet_t pkt) +void *odp_packet_push_head(odp_packet_t pkt, uint32_t len) +{ + odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); + + if (len > pkt_hdr->headroom) + return NULL; + + push_head(pkt_hdr, len); + return packet_map(pkt_hdr, 0, NULL); +} + +void *odp_packet_pull_head(odp_packet_t pkt, uint32_t len) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); + + if (len > pkt_hdr->frame_len) + return NULL; + + pull_head(pkt_hdr, len); return packet_map(pkt_hdr, 0, NULL); } +void *odp_packet_push_tail(odp_packet_t pkt, uint32_t len) +{ + odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); + uint32_t origin = pkt_hdr->frame_len; + + if (len > pkt_hdr->tailroom) + return NULL; + + push_tail(pkt_hdr, len); + return packet_map(pkt_hdr, origin, NULL); +} + +void *odp_packet_pull_tail(odp_packet_t pkt, uint32_t len) +{ + odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); + + if (len > pkt_hdr->frame_len) + return NULL; + + pull_tail(pkt_hdr, len); + return packet_map(pkt_hdr, pkt_hdr->frame_len, NULL); +} + void *odp_packet_user_ptr(odp_packet_t pkt) { return odp_packet_hdr(pkt)->buf_hdr.buf_ctx; @@ -265,13 +343,6 @@ int odp_packet_is_valid(odp_packet_t pkt) return odp_buffer_is_valid(buf); } -size_t odp_packet_buf_size(odp_packet_t pkt) -{ - odp_buffer_t buf = odp_packet_to_buffer(pkt); - - return odp_buffer_size(buf); -} - /* * * Internal Use Routines |