diff options
Diffstat (limited to 'lib/libtle_l4p/misc.h')
-rw-r--r-- | lib/libtle_l4p/misc.h | 166 |
1 files changed, 149 insertions, 17 deletions
diff --git a/lib/libtle_l4p/misc.h b/lib/libtle_l4p/misc.h index 8be5dfe..d39e5a1 100644 --- a/lib/libtle_l4p/misc.h +++ b/lib/libtle_l4p/misc.h @@ -16,12 +16,34 @@ #ifndef _MISC_H_ #define _MISC_H_ +#include <tle_stats.h> #include <tle_dpdk_wrapper.h> #ifdef __cplusplus extern "C" { #endif +union typflg { + uint16_t raw; + struct { + uint8_t type; /* TLE_V4/TLE_V6 */ + uint8_t flags; /* TCP header flags */ + }; +}; + +union pkt_info { + rte_xmm_t raw; + struct { + union typflg tf; + uint16_t csf; /* checksum flags */ + union l4_ports port; + union { + union ipv4_addrs addr4; + const union ipv6_addrs *addr6; + }; + }; +}; + static inline int xmm_cmp(const rte_xmm_t *da, const rte_xmm_t *sa) { @@ -286,43 +308,41 @@ _ipv4x_cksum(const void *iph, size_t len) return (cksum == 0xffff) ? cksum : ~cksum; } -/* - * helper function to check csum. - */ static inline int -check_pkt_csum(const struct rte_mbuf *m, uint64_t ol_flags, uint32_t type, - uint32_t proto) +check_pkt_csum(const struct rte_mbuf *m, uint32_t type, uint32_t proto) { const struct ipv4_hdr *l3h4; const struct ipv6_hdr *l3h6; const struct udp_hdr *l4h; - uint64_t fl3, fl4; - uint16_t csum; int32_t ret; - - fl4 = ol_flags & PKT_RX_L4_CKSUM_MASK; - fl3 = (type == TLE_V4) ? - (ol_flags & PKT_RX_IP_CKSUM_MASK) : PKT_RX_IP_CKSUM_GOOD; + uint16_t csum; + uint64_t ol_flags = m->ol_flags; /* case 0: both ip and l4 cksum is verified or data is valid */ - if ((fl3 | fl4) == (PKT_RX_IP_CKSUM_GOOD | PKT_RX_L4_CKSUM_GOOD)) + if ((ol_flags & PKT_RX_IP_CKSUM_GOOD) && + (ol_flags & PKT_RX_L4_CKSUM_GOOD)) return 0; /* case 1: either ip or l4 cksum bad */ - if (fl3 == PKT_RX_IP_CKSUM_BAD || fl4 == PKT_RX_L4_CKSUM_BAD) + if ((ol_flags & PKT_RX_IP_CKSUM_MASK) == PKT_RX_IP_CKSUM_BAD) + return 1; + + if ((ol_flags & PKT_RX_L4_CKSUM_MASK) == PKT_RX_L4_CKSUM_BAD) return 1; /* case 2: either ip or l4 or both cksum is unknown */ + ret = 0; l3h4 = rte_pktmbuf_mtod_offset(m, const struct ipv4_hdr *, m->l2_len); l3h6 = rte_pktmbuf_mtod_offset(m, const struct ipv6_hdr *, m->l2_len); - ret = 0; - if (fl3 == PKT_RX_IP_CKSUM_UNKNOWN && l3h4->hdr_checksum != 0) { + if ((ol_flags & PKT_RX_IP_CKSUM_MASK) == PKT_RX_IP_CKSUM_UNKNOWN && + l3h4->hdr_checksum != 0) { csum = _ipv4x_cksum(l3h4, m->l3_len); ret = (csum != UINT16_MAX); } - if (ret == 0 && fl4 == PKT_RX_L4_CKSUM_UNKNOWN) { + if (ret == 0 && (ol_flags & PKT_RX_L4_CKSUM_MASK) == + PKT_RX_L4_CKSUM_UNKNOWN) { /* * for IPv4 it is allowed to have zero UDP cksum, @@ -376,8 +396,20 @@ rwl_acquire(rte_atomic32_t *p) static inline void rwl_down(rte_atomic32_t *p) { - while (rte_atomic32_cmpset((volatile uint32_t *)p, 0, INT32_MIN) == 0) + while (rte_atomic32_cmpset((volatile uint32_t *)p, 0, INT32_MIN) == 0) + rte_pause(); +} + +static inline int +rwl_try_down(rte_atomic32_t *p) +{ + while (rte_atomic32_cmpset((volatile uint32_t *)p, 0, INT32_MIN) == 0) { + /* Already down */ + if (rte_atomic32_read(p) == INT32_MIN) + return -1; rte_pause(); + } + return 0; } static inline void @@ -510,6 +542,106 @@ _iovec_to_mbsegs(struct iovec *iv, uint32_t seglen, struct rte_mbuf *mb[], return i; } +/** + * Remove len bytes at the beginning of an mbuf. + * + * It's an enhancement version of rte_pktmbuf_abj which not support + * adjusting length greater than the length of the first segment. + * + * Returns a pointer to the new mbuf. If the + * length is greater than the total length of the mbuf, then the + * function will fail and return NULL, without modifying the mbuf. + * + * @param m + * The packet mbuf. + * @param len + * The amount of data to remove (in bytes). + * @return + * A pointer to the new start of the data. + */ +static inline struct rte_mbuf * +_rte_pktmbuf_adj(struct rte_mbuf *m, uint32_t len) +{ + struct rte_mbuf *next; + uint32_t remain, plen; + uint16_t segs; + + if (unlikely(len > m->pkt_len)) + return NULL; + + plen = m->pkt_len; + remain = len; + segs = m->nb_segs; + /* don't free last segment */ + while (remain >= m->data_len && m->next) { + next = m->next; + remain -= m->data_len; + segs--; + rte_pktmbuf_free_seg(m); + m = next; + } + + if (remain) { + m->data_len = (uint16_t)(m->data_len - remain); + m->data_off = (uint16_t)(m->data_off + remain); + } + + m->pkt_len = plen - len; + m->nb_segs = segs; + return m; +} + +/** + * Remove len bytes of data at the end of the mbuf. + * + * It's an enhancement version of rte_pktmbuf_trim, which not support + * removing length greater than the length of the last segment. + * + * @param m + * The packet mbuf. + * @param len + * The amount of data to remove (in bytes). + * @return + * - 0: On success. + * - -1: On error. + */ +static inline int +_rte_pktmbuf_trim(struct rte_mbuf *m, uint32_t len) +{ + struct rte_mbuf *last, *next, *tmp; + uint32_t remain; + uint16_t segs; + + if (unlikely(len > m->pkt_len)) + return -1; + + tmp = m; + /* find the last segment will remain after trim */ + remain = m->pkt_len - len; + while (remain > tmp->data_len) { + remain -= tmp->data_len; + tmp = tmp->next; + } + + /* trim the remained last segment */ + tmp->data_len = remain; + + /* remove trimmed segments */ + segs = m->nb_segs; + last = tmp; + for (tmp = tmp->next; tmp != NULL; tmp = next) { + next = tmp->next; + rte_pktmbuf_free_seg(tmp); + segs--; + } + + last->next = NULL; + m->pkt_len -= len; + m->nb_segs = segs; + + return 0; +} + #ifdef __cplusplus } #endif |