From: Petri Savolainen <petri.savolai...@linaro.org> Inline L2/L3/L4 pointer functions. Packet map function is exported to backup the unlikely case when offset is not within the first segment. Always use the inlined version within the implementation itself.
Signed-off-by: Petri Savolainen <petri.savolai...@linaro.org> --- /** Email created from pull request 360 (psavol:master-packet-offset-inline) ** https://github.com/Linaro/odp/pull/360 ** Patch: https://github.com/Linaro/odp/pull/360.patch ** Base sha: 3c02836d9d9ca16b1277bdd30e523779b9fe8374 ** Merge commit sha: 8a43dcccb105ee32ad867e39b8763d77c37b331e **/ .../include/odp/api/plat/packet_inlines.h | 62 ++++++++++++++++++++++ .../include/odp/api/plat/packet_inlines_api.h | 15 ++++++ platform/linux-generic/odp_packet.c | 40 ++++++-------- platform/linux-generic/odp_traffic_mngr.c | 6 +-- 4 files changed, 95 insertions(+), 28 deletions(-) diff --git a/platform/linux-generic/include/odp/api/plat/packet_inlines.h b/platform/linux-generic/include/odp/api/plat/packet_inlines.h index aa9ba812f..2ace0ca37 100644 --- a/platform/linux-generic/include/odp/api/plat/packet_inlines.h +++ b/platform/linux-generic/include/odp/api/plat/packet_inlines.h @@ -18,6 +18,11 @@ #include <odp/api/packet_io.h> #include <odp/api/hints.h> +/** @internal Inline function @param pkt_ptr @param offset @param seg_len + * @param seg_idx @return */ +void *_odp_packet_map(void *pkt_ptr, uint32_t offset, uint32_t *seg_len, + int *seg_idx); + /** @internal Inline function offsets */ extern const _odp_packet_inline_offset_t _odp_packet_inline; @@ -126,6 +131,63 @@ static inline uint32_t _odp_packet_l4_offset(odp_packet_t pkt) return _odp_pkt_get(pkt, uint16_t, l4_offset); } +/** @internal Inline function @param pkt @param len @return */ +static inline void *_odp_packet_l2_ptr(odp_packet_t pkt, uint32_t *len) +{ + uint32_t offset = _odp_packet_l2_offset(pkt); + uint32_t seg_len = _odp_packet_seg_len(pkt); + uint8_t *data = (uint8_t *)_odp_packet_data(pkt); + + if (odp_unlikely(offset > seg_len)) { + void *pkt_hdr = (void *)pkt; + + return _odp_packet_map(pkt_hdr, offset, len, NULL); + } + + if (len) + *len = seg_len - offset; + + return data + offset; +} + +/** @internal Inline function @param pkt @param len @return */ +static inline void *_odp_packet_l3_ptr(odp_packet_t pkt, uint32_t *len) +{ + uint32_t offset = _odp_packet_l3_offset(pkt); + uint32_t seg_len = _odp_packet_seg_len(pkt); + uint8_t *data = (uint8_t *)_odp_packet_data(pkt); + + if (odp_unlikely(offset > seg_len)) { + void *pkt_hdr = (void *)pkt; + + return _odp_packet_map(pkt_hdr, offset, len, NULL); + } + + if (len) + *len = seg_len - offset; + + return data + offset; +} + +/** @internal Inline function @param pkt @param len @return */ +static inline void *_odp_packet_l4_ptr(odp_packet_t pkt, uint32_t *len) +{ + uint32_t offset = _odp_packet_l4_offset(pkt); + uint32_t seg_len = _odp_packet_seg_len(pkt); + uint8_t *data = (uint8_t *)_odp_packet_data(pkt); + + if (odp_unlikely(offset > seg_len)) { + void *pkt_hdr = (void *)pkt; + + return _odp_packet_map(pkt_hdr, offset, len, NULL); + } + + if (len) + *len = seg_len - offset; + + return data + offset; +} + /** @internal Inline function @param pkt @return */ static inline uint32_t _odp_packet_flow_hash(odp_packet_t pkt) { diff --git a/platform/linux-generic/include/odp/api/plat/packet_inlines_api.h b/platform/linux-generic/include/odp/api/plat/packet_inlines_api.h index 84b4f08ab..c90a69c52 100644 --- a/platform/linux-generic/include/odp/api/plat/packet_inlines_api.h +++ b/platform/linux-generic/include/odp/api/plat/packet_inlines_api.h @@ -83,6 +83,21 @@ _ODP_INLINE uint32_t odp_packet_l4_offset(odp_packet_t pkt) return _odp_packet_l4_offset(pkt); } +_ODP_INLINE void *odp_packet_l2_ptr(odp_packet_t pkt, uint32_t *len) +{ + return _odp_packet_l2_ptr(pkt, len); +} + +_ODP_INLINE void *odp_packet_l3_ptr(odp_packet_t pkt, uint32_t *len) +{ + return _odp_packet_l3_ptr(pkt, len); +} + +_ODP_INLINE void *odp_packet_l4_ptr(odp_packet_t pkt, uint32_t *len) +{ + return _odp_packet_l4_ptr(pkt, len); +} + _ODP_INLINE uint32_t odp_packet_flow_hash(odp_packet_t pkt) { return _odp_packet_flow_hash(pkt); diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c index 3f0d764f6..0f4d32818 100644 --- a/platform/linux-generic/odp_packet.c +++ b/platform/linux-generic/odp_packet.c @@ -278,11 +278,12 @@ static inline void packet_seg_copy_md(odp_packet_hdr_t *dst, */ } -static inline void *packet_map(odp_packet_hdr_t *pkt_hdr, - uint32_t offset, uint32_t *seg_len, int *seg_idx) +static inline void *packet_map(void *pkt_ptr, uint32_t offset, + uint32_t *seg_len, int *seg_idx) { void *addr; uint32_t len; + odp_packet_hdr_t *pkt_hdr = pkt_ptr; int seg_id = 0; int seg_count = pkt_hdr->buf_hdr.segcount; @@ -323,6 +324,18 @@ static inline void *packet_map(odp_packet_hdr_t *pkt_hdr, return addr; } +#include <odp/visibility_begin.h> + +/* This file uses the inlined version directly. Inlined API calls use this when + * packet seg_len < offset. */ +void *_odp_packet_map(void *pkt_ptr, uint32_t offset, uint32_t *seg_len, + int *seg_idx) +{ + return packet_map(pkt_ptr, offset, seg_len, seg_idx); +} + +#include <odp/visibility_end.h> + void packet_parse_reset(odp_packet_hdr_t *pkt_hdr) { /* Reset parser metadata before new parse */ @@ -1207,15 +1220,6 @@ void odp_packet_user_ptr_set(odp_packet_t pkt, const void *ctx) packet_hdr(pkt)->buf_hdr.buf_cctx = ctx; } -void *odp_packet_l2_ptr(odp_packet_t pkt, uint32_t *len) -{ - odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - - if (!packet_hdr_has_l2(pkt_hdr)) - return NULL; - return packet_map(pkt_hdr, pkt_hdr->p.l2_offset, len, NULL); -} - int odp_packet_l2_offset_set(odp_packet_t pkt, uint32_t offset) { odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); @@ -1228,13 +1232,6 @@ int odp_packet_l2_offset_set(odp_packet_t pkt, uint32_t offset) return 0; } -void *odp_packet_l3_ptr(odp_packet_t pkt, uint32_t *len) -{ - odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - - return packet_map(pkt_hdr, pkt_hdr->p.l3_offset, len, NULL); -} - int odp_packet_l3_offset_set(odp_packet_t pkt, uint32_t offset) { odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); @@ -1246,13 +1243,6 @@ int odp_packet_l3_offset_set(odp_packet_t pkt, uint32_t offset) return 0; } -void *odp_packet_l4_ptr(odp_packet_t pkt, uint32_t *len) -{ - odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - - return packet_map(pkt_hdr, pkt_hdr->p.l4_offset, len, NULL); -} - int odp_packet_l4_offset_set(odp_packet_t pkt, uint32_t offset) { odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); diff --git a/platform/linux-generic/odp_traffic_mngr.c b/platform/linux-generic/odp_traffic_mngr.c index e22a33f29..556b2a1f2 100644 --- a/platform/linux-generic/odp_traffic_mngr.c +++ b/platform/linux-generic/odp_traffic_mngr.c @@ -1928,7 +1928,7 @@ static void egress_vlan_marking(tm_vlan_marking_t *vlan_marking, uint32_t hdr_len; uint16_t old_tci, new_tci; - ether_hdr_ptr = odp_packet_l2_ptr(odp_pkt, &hdr_len); + ether_hdr_ptr = _odp_packet_l2_ptr(odp_pkt, &hdr_len); vlan_hdr_ptr = (_odp_vlanhdr_t *)(ether_hdr_ptr + 1); /* If the split_hdr variable below is TRUE, then this indicates that @@ -1968,7 +1968,7 @@ static void egress_ipv4_tos_marking(tm_tos_marking_t *tos_marking, uint8_t old_tos, new_tos, ecn; l3_offset = _odp_packet_l3_offset(odp_pkt); - ipv4_hdr_ptr = odp_packet_l3_ptr(odp_pkt, &hdr_len); + ipv4_hdr_ptr = _odp_packet_l3_ptr(odp_pkt, &hdr_len); /* If the split_hdr variable below is TRUE, then this indicates that * for this odp (output) packet the IPv4 header is not all in the same @@ -2034,7 +2034,7 @@ static void egress_ipv6_tc_marking(tm_tos_marking_t *tos_marking, uint8_t old_tc, new_tc, ecn; l3_offset = _odp_packet_l3_offset(odp_pkt); - ipv6_hdr_ptr = odp_packet_l3_ptr(odp_pkt, &hdr_len); + ipv6_hdr_ptr = _odp_packet_l3_ptr(odp_pkt, &hdr_len); /* If the split_hdr variable below is TRUE, then this indicates that * for this odp (output) packet the IPv6 header is not all in the same