aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Kiss <zoltan.kiss@linaro.org>2016-07-22 14:56:51 +0100
committerZoltan Kiss <zoltan.kiss@linaro.org>2016-07-22 16:49:17 +0100
commit0e642ce9b2ac0a26198ef8d6e0c9cb0dbb549d99 (patch)
tree24cb5ac2e284a5463faa8c592df4202f27c33677
parent05eca183585c77fa7546a4f654cea0f7a7f7b876 (diff)
Port 072b5ca "linux-gen: packet: use packet_parser_t type argument with parser functions"
Signed-off-by: Zoltan Kiss <zoltan.kiss@linaro.org>
-rw-r--r--platform/linux-dpdk/include/odp_packet_internal.h28
-rw-r--r--platform/linux-dpdk/odp_packet.c166
-rw-r--r--platform/linux-dpdk/odp_packet_dpdk.c1
3 files changed, 106 insertions, 89 deletions
diff --git a/platform/linux-dpdk/include/odp_packet_internal.h b/platform/linux-dpdk/include/odp_packet_internal.h
index 2693b02a1..ff6f85664 100644
--- a/platform/linux-dpdk/include/odp_packet_internal.h
+++ b/platform/linux-dpdk/include/odp_packet_internal.h
@@ -32,6 +32,9 @@ extern "C" {
#include <rte_acl_osdep.h>
+/** Minimum segment length expected by packet_parse_common() */
+#define PACKET_PARSE_SEG_LEN 96
+
/**
* Packet input & protocol flags
*/
@@ -197,9 +200,9 @@ static inline void packet_set_len(odp_packet_hdr_t *pkt_hdr, uint32_t len)
rte_pktmbuf_pkt_len(&pkt_hdr->buf_hdr.mb) = len;
}
-static inline int packet_parse_l2_not_done(odp_packet_hdr_t *pkt_hdr)
+static inline int packet_parse_l2_not_done(packet_parser_t *prs)
{
- return !pkt_hdr->p.input_flags.parsed_l2;
+ return !prs->input_flags.parsed_l2;
}
static inline int packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr)
@@ -211,21 +214,21 @@ static inline int packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr)
void _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt);
/* Fill in parser metadata for L2 */
-static inline void packet_parse_l2(odp_packet_hdr_t *pkt_hdr)
+static inline void packet_parse_l2(packet_parser_t *prs, uint32_t frame_len)
{
/* Packet alloc or reset have already init other offsets and flags */
/* We only support Ethernet for now */
- pkt_hdr->p.input_flags.eth = 1;
+ prs->input_flags.eth = 1;
/* Detect jumbo frames */
- if (odp_packet_len((odp_packet_t)pkt_hdr) > ODPH_ETH_LEN_MAX)
- pkt_hdr->p.input_flags.jumbo = 1;
+ if (frame_len > ODPH_ETH_LEN_MAX)
+ prs->input_flags.jumbo = 1;
/* Assume valid L2 header, no CRC/FCS check in SW */
- pkt_hdr->p.input_flags.l2 = 1;
+ prs->input_flags.l2 = 1;
- pkt_hdr->p.input_flags.parsed_l2 = 1;
+ prs->input_flags.parsed_l2 = 1;
}
static inline void _odp_packet_reset_parse(odp_packet_t pkt)
@@ -233,7 +236,7 @@ static inline void _odp_packet_reset_parse(odp_packet_t pkt)
odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
pkt_hdr->p.input_flags.parsed_all = 0;
- packet_parse_l2(pkt_hdr);
+ packet_parse_l2(&pkt_hdr->p, odp_packet_len(pkt));
}
/* Perform full packet parse */
@@ -271,11 +274,8 @@ static inline void packet_set_ts(odp_packet_hdr_t *pkt_hdr, odp_time_t *ts)
}
}
-int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *parseptr);
-
-/* DPDK will reserve RTE_PKTMBUF_HEADROOM in any case */
-ODP_STATIC_ASSERT(ODP_CONFIG_PACKET_HEADROOM == RTE_PKTMBUF_HEADROOM,
- "ERROR: Headroom has to be equal to RTE_PKTMBUF_HEADROOM");
+int packet_parse_common(packet_parser_t *pkt_hdr, const uint8_t *ptr,
+ uint32_t pkt_len, uint32_t seg_len);
/* We can't enforce tailroom reservation for received packets */
ODP_STATIC_ASSERT(ODP_CONFIG_PACKET_TAILROOM == 0,
diff --git a/platform/linux-dpdk/odp_packet.c b/platform/linux-dpdk/odp_packet.c
index 96c634e28..08b5186f5 100644
--- a/platform/linux-dpdk/odp_packet.c
+++ b/platform/linux-dpdk/odp_packet.c
@@ -1152,8 +1152,8 @@ void _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt)
/**
* Parser helper function for IPv4
*/
-static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr,
- const uint8_t **parseptr, uint32_t *offset)
+static inline uint8_t parse_ipv4(packet_parser_t *prs, const uint8_t **parseptr,
+ uint32_t *offset, uint32_t frame_len)
{
const odph_ipv4hdr_t *ipv4 = (const odph_ipv4hdr_t *)*parseptr;
uint8_t ver = ODPH_IPV4HDR_VER(ipv4->ver_ihl);
@@ -1161,20 +1161,20 @@ static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr,
uint16_t frag_offset;
uint32_t dstaddr = odp_be_to_cpu_32(ipv4->dst_addr);
- pkt_hdr->p.l3_len = odp_be_to_cpu_16(ipv4->tot_len);
+ prs->l3_len = odp_be_to_cpu_16(ipv4->tot_len);
if (odp_unlikely(ihl < ODPH_IPV4HDR_IHL_MIN) ||
odp_unlikely(ver != 4) ||
- (pkt_hdr->p.l3_len > pkt_hdr->buf_hdr.mb.pkt_len - *offset)) {
- pkt_hdr->p.error_flags.ip_err = 1;
+ (prs->l3_len > frame_len - *offset)) {
+ prs->error_flags.ip_err = 1;
return 0;
}
*offset += ihl * 4;
*parseptr += ihl * 4;
- if (odp_unlikely(ihl > ODPH_IPV4HDR_IHL_MIN))
- pkt_hdr->p.input_flags.ipopt = 1;
+ if (odp_unlikely(ihl > _ODP_IPV4HDR_IHL_MIN))
+ prs->input_flags.ipopt = 1;
/* A packet is a fragment if:
* "more fragments" flag is set (all fragments except the last)
@@ -1182,12 +1182,12 @@ static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr,
* "fragment offset" field is nonzero (all fragments except the first)
*/
frag_offset = odp_be_to_cpu_16(ipv4->frag_offset);
- if (odp_unlikely(ODPH_IPV4HDR_IS_FRAGMENT(frag_offset)))
- pkt_hdr->p.input_flags.ipfrag = 1;
+ if (odp_unlikely(_ODP_IPV4HDR_IS_FRAGMENT(frag_offset)))
+ prs->input_flags.ipfrag = 1;
/* Handle IPv4 broadcast / multicast */
- pkt_hdr->p.input_flags.ip_bcast = (dstaddr == 0xffffffff);
- pkt_hdr->p.input_flags.ip_mcast = (dstaddr >> 28) == 0xd;
+ prs->input_flags.ip_bcast = (dstaddr == 0xffffffff);
+ prs->input_flags.ip_mcast = (dstaddr >> 28) == 0xd;
return ipv4->proto;
}
@@ -1195,26 +1195,27 @@ static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr,
/**
* Parser helper function for IPv6
*/
-static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr,
- const uint8_t **parseptr, uint32_t *offset)
+static inline uint8_t parse_ipv6(packet_parser_t *prs, const uint8_t **parseptr,
+ uint32_t *offset, uint32_t frame_len,
+ uint32_t seg_len)
{
const odph_ipv6hdr_t *ipv6 = (const odph_ipv6hdr_t *)*parseptr;
const odph_ipv6hdr_ext_t *ipv6ext;
uint32_t dstaddr0 = odp_be_to_cpu_32(ipv6->dst_addr[0]);
- pkt_hdr->p.l3_len = odp_be_to_cpu_16(ipv6->payload_len) +
- ODPH_IPV6HDR_LEN;
+ prs->l3_len = odp_be_to_cpu_16(ipv6->payload_len) +
+ _ODP_IPV6HDR_LEN;
/* Basic sanity checks on IPv6 header */
if ((odp_be_to_cpu_32(ipv6->ver_tc_flow) >> 28) != 6 ||
- pkt_hdr->p.l3_len > pkt_hdr->buf_hdr.mb.pkt_len - *offset) {
- pkt_hdr->p.error_flags.ip_err = 1;
+ prs->l3_len > frame_len - *offset) {
+ prs->error_flags.ip_err = 1;
return 0;
}
/* IPv6 broadcast / multicast flags */
- pkt_hdr->p.input_flags.ip_mcast = (dstaddr0 & 0xff000000) == 0xff000000;
- pkt_hdr->p.input_flags.ip_bcast = 0;
+ prs->input_flags.ip_mcast = (dstaddr0 & 0xff000000) == 0xff000000;
+ prs->input_flags.ip_bcast = 0;
/* Skip past IPv6 header */
*offset += sizeof(odph_ipv6hdr_t);
@@ -1223,7 +1224,7 @@ static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr,
/* Skip past any IPv6 extension headers */
if (ipv6->next_hdr == ODPH_IPPROTO_HOPOPTS ||
ipv6->next_hdr == ODPH_IPPROTO_ROUTE) {
- pkt_hdr->p.input_flags.ipopt = 1;
+ prs->input_flags.ipopt = 1;
do {
ipv6ext = (const odph_ipv6hdr_ext_t *)*parseptr;
@@ -1233,23 +1234,23 @@ static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr,
*parseptr += extlen;
} while ((ipv6ext->next_hdr == ODPH_IPPROTO_HOPOPTS ||
ipv6ext->next_hdr == ODPH_IPPROTO_ROUTE) &&
- *offset < pkt_hdr->buf_hdr.mb.pkt_len);
+ *offset < seg_len);
- if (*offset >= pkt_hdr->p.l3_offset +
+ if (*offset >= prs->l3_offset +
odp_be_to_cpu_16(ipv6->payload_len)) {
- pkt_hdr->p.error_flags.ip_err = 1;
+ prs->error_flags.ip_err = 1;
return 0;
}
if (ipv6ext->next_hdr == ODPH_IPPROTO_FRAG)
- pkt_hdr->p.input_flags.ipfrag = 1;
+ prs->input_flags.ipfrag = 1;
return ipv6ext->next_hdr;
}
if (odp_unlikely(ipv6->next_hdr == ODPH_IPPROTO_FRAG)) {
- pkt_hdr->p.input_flags.ipopt = 1;
- pkt_hdr->p.input_flags.ipfrag = 1;
+ prs->input_flags.ipopt = 1;
+ prs->input_flags.ipfrag = 1;
}
return ipv6->next_hdr;
@@ -1258,18 +1259,18 @@ static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr,
/**
* Parser helper function for TCP
*/
-static inline void parse_tcp(odp_packet_hdr_t *pkt_hdr,
+static inline void parse_tcp(packet_parser_t *prs,
const uint8_t **parseptr, uint32_t *offset)
{
const odph_tcphdr_t *tcp = (const odph_tcphdr_t *)*parseptr;
if (tcp->hl < sizeof(odph_tcphdr_t) / sizeof(uint32_t))
- pkt_hdr->p.error_flags.tcp_err = 1;
+ prs->error_flags.tcp_err = 1;
else if ((uint32_t)tcp->hl * 4 > sizeof(odph_tcphdr_t))
- pkt_hdr->p.input_flags.tcpopt = 1;
+ prs->input_flags.tcpopt = 1;
- pkt_hdr->l4_len = pkt_hdr->p.l3_len +
- pkt_hdr->p.l3_offset - pkt_hdr->p.l4_offset;
+ prs->l4_len = prs->l3_len +
+ prs->l3_offset - prs->l4_offset;
if (offset)
*offset += (uint32_t)tcp->hl * 4;
@@ -1279,26 +1280,33 @@ static inline void parse_tcp(odp_packet_hdr_t *pkt_hdr,
/**
* Parser helper function for UDP
*/
-static inline void parse_udp(odp_packet_hdr_t *pkt_hdr,
+static inline void parse_udp(packet_parser_t *prs,
const uint8_t **parseptr, uint32_t *offset)
{
const odph_udphdr_t *udp = (const odph_udphdr_t *)*parseptr;
uint32_t udplen = odp_be_to_cpu_16(udp->length);
if (udplen < sizeof(odph_udphdr_t) ||
- udplen > (pkt_hdr->p.l3_len +
- pkt_hdr->p.l4_offset - pkt_hdr->p.l3_offset)) {
- pkt_hdr->p.error_flags.udp_err = 1;
+ udplen > (prs->l3_len +
+ prs->l4_offset - prs->l3_offset)) {
+ prs->error_flags.udp_err = 1;
}
- pkt_hdr->l4_len = udplen;
+ prs->l4_len = udplen;
if (offset)
*offset += sizeof(odph_udphdr_t);
*parseptr += sizeof(odph_udphdr_t);
}
-int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *ptr)
+/**
+ * Parse common packet headers
+ *
+ * The function expects at least PACKET_PARSE_SEG_LEN bytes of data to be
+ * available from the ptr.
+ */
+int packet_parse_common(packet_parser_t *prs, const uint8_t *ptr,
+ uint32_t frame_len, uint32_t seg_len)
{
const odph_ethhdr_t *eth;
const odph_vlanhdr_t *vlan;
@@ -1309,15 +1317,14 @@ int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *ptr)
uint16_t macaddr0, macaddr2, macaddr4;
offset = sizeof(odph_ethhdr_t);
- if (packet_parse_l2_not_done(pkt_hdr))
- packet_parse_l2(pkt_hdr);
+ if (packet_parse_l2_not_done(prs))
+ packet_parse_l2(prs, frame_len);
- eth = ptr ? (const odph_ethhdr_t *)ptr :
- (odph_ethhdr_t *)odp_packet_data((odp_packet_t)pkt_hdr);
+ eth = (const _odp_ethhdr_t *)ptr;
/* Handle Ethernet broadcast/multicast addresses */
macaddr0 = odp_be_to_cpu_16(*((const uint16_t *)(const void *)eth));
- pkt_hdr->p.input_flags.eth_mcast = (macaddr0 & 0x0100) == 0x0100;
+ prs->input_flags.eth_mcast = (macaddr0 & 0x0100) == 0x0100;
if (macaddr0 == 0xffff) {
macaddr2 =
@@ -1326,10 +1333,10 @@ int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *ptr)
macaddr4 =
odp_be_to_cpu_16(*((const uint16_t *)
(const void *)eth + 2));
- pkt_hdr->p.input_flags.eth_bcast =
+ prs->input_flags.eth_bcast =
(macaddr2 == 0xffff) && (macaddr4 == 0xffff);
} else {
- pkt_hdr->p.input_flags.eth_bcast = 0;
+ prs->input_flags.eth_bcast = 0;
}
/* Get Ethertype */
@@ -1338,9 +1345,9 @@ int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *ptr)
/* Check for SNAP vs. DIX */
if (ethtype < ODPH_ETH_LEN_MAX) {
- pkt_hdr->p.input_flags.snap = 1;
- if (ethtype > odp_packet_len((odp_packet_t)pkt_hdr) - offset) {
- pkt_hdr->p.error_flags.snap_len = 1;
+ prs->input_flags.snap = 1;
+ if (ethtype > frame_len - offset) {
+ prs->error_flags.snap_len = 1;
goto parse_exit;
}
ethtype = odp_be_to_cpu_16(*((const uint16_t *)
@@ -1351,8 +1358,8 @@ int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *ptr)
/* Parse the VLAN header(s), if present */
if (ethtype == ODPH_ETHTYPE_VLAN_OUTER) {
- pkt_hdr->p.input_flags.vlan_qinq = 1;
- pkt_hdr->p.input_flags.vlan = 1;
+ prs->input_flags.vlan_qinq = 1;
+ prs->input_flags.vlan = 1;
vlan = (const odph_vlanhdr_t *)parseptr;
ethtype = odp_be_to_cpu_16(vlan->type);
@@ -1361,7 +1368,7 @@ int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *ptr)
}
if (ethtype == ODPH_ETHTYPE_VLAN) {
- pkt_hdr->p.input_flags.vlan = 1;
+ prs->input_flags.vlan = 1;
vlan = (const odph_vlanhdr_t *)parseptr;
ethtype = odp_be_to_cpu_16(vlan->type);
offset += sizeof(odph_vlanhdr_t);
@@ -1369,71 +1376,76 @@ int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *ptr)
}
/* Set l3_offset+flag only for known ethtypes */
- pkt_hdr->p.input_flags.l3 = 1;
- pkt_hdr->p.l3_offset = offset;
+ prs->input_flags.l3 = 1;
+ prs->l3_offset = offset;
/* Parse Layer 3 headers */
switch (ethtype) {
case ODPH_ETHTYPE_IPV4:
- pkt_hdr->p.input_flags.ipv4 = 1;
- ip_proto = parse_ipv4(pkt_hdr, &parseptr, &offset);
+ prs->input_flags.ipv4 = 1;
+ ip_proto = parse_ipv4(prs, &parseptr, &offset, frame_len);
break;
case ODPH_ETHTYPE_IPV6:
- pkt_hdr->p.input_flags.ipv6 = 1;
- ip_proto = parse_ipv6(pkt_hdr, &parseptr, &offset);
+ prs->input_flags.ipv6 = 1;
+ ip_proto = parse_ipv6(prs, &parseptr, &offset, frame_len,
+ seg_len);
break;
case ODPH_ETHTYPE_ARP:
- pkt_hdr->p.input_flags.arp = 1;
+ prs->input_flags.arp = 1;
ip_proto = 255; /* Reserved invalid by IANA */
break;
default:
- pkt_hdr->p.input_flags.l3 = 0;
- pkt_hdr->p.l3_offset = ODP_PACKET_OFFSET_INVALID;
+ prs->input_flags.l3 = 0;
+ prs->l3_offset = ODP_PACKET_OFFSET_INVALID;
ip_proto = 255; /* Reserved invalid by IANA */
}
/* Set l4_offset+flag only for known ip_proto */
- pkt_hdr->p.input_flags.l4 = 1;
- pkt_hdr->p.l4_offset = offset;
+ prs->input_flags.l4 = 1;
+ prs->l4_offset = offset;
/* Parse Layer 4 headers */
switch (ip_proto) {
case ODPH_IPPROTO_ICMP:
- pkt_hdr->p.input_flags.icmp = 1;
+ prs->input_flags.icmp = 1;
break;
case ODPH_IPPROTO_TCP:
- pkt_hdr->p.input_flags.tcp = 1;
- parse_tcp(pkt_hdr, &parseptr, NULL);
+ if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len))
+ return -1;
+ prs->input_flags.tcp = 1;
+ parse_tcp(prs, &parseptr, NULL);
break;
case ODPH_IPPROTO_UDP:
- pkt_hdr->p.input_flags.udp = 1;
- parse_udp(pkt_hdr, &parseptr, NULL);
+ if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len))
+ return -1;
+ prs->input_flags.udp = 1;
+ parse_udp(prs, &parseptr, NULL);
break;
case ODPH_IPPROTO_AH:
- pkt_hdr->p.input_flags.ipsec = 1;
- pkt_hdr->p.input_flags.ipsec_ah = 1;
+ prs->input_flags.ipsec = 1;
+ prs->input_flags.ipsec_ah = 1;
break;
case ODPH_IPPROTO_ESP:
- pkt_hdr->p.input_flags.ipsec = 1;
- pkt_hdr->p.input_flags.ipsec_esp = 1;
+ prs->input_flags.ipsec = 1;
+ prs->input_flags.ipsec_esp = 1;
break;
default:
- pkt_hdr->p.input_flags.l4 = 0;
- pkt_hdr->p.l4_offset = ODP_PACKET_OFFSET_INVALID;
+ prs->input_flags.l4 = 0;
+ prs->l4_offset = ODP_PACKET_OFFSET_INVALID;
break;
}
parse_exit:
- pkt_hdr->p.input_flags.parsed_all = 1;
- return pkt_hdr->p.error_flags.all != 0;
+ prs->input_flags.parsed_all = 1;
+ return prs->error_flags.all != 0;
}
/**
@@ -1441,5 +1453,9 @@ parse_exit:
*/
int packet_parse_full(odp_packet_hdr_t *pkt_hdr)
{
- return _odp_parse_common(pkt_hdr, NULL);
+ uint32_t seg_len = odp_packet_seg_len((odp_packet_t)pkt_hdr);
+ uint32_t len = packet_len(pkt_hdr);
+ void *base = odp_packet_data((odp_packet_t)pkt_hdr);
+
+ return packet_parse_common(&pkt_hdr->p, base, len, seg_len);
}
diff --git a/platform/linux-dpdk/odp_packet_dpdk.c b/platform/linux-dpdk/odp_packet_dpdk.c
index a1bcfc6fb..c8cc3a33b 100644
--- a/platform/linux-dpdk/odp_packet_dpdk.c
+++ b/platform/linux-dpdk/odp_packet_dpdk.c
@@ -425,6 +425,7 @@ static int recv_pkt_dpdk(pktio_entry_t *pktio_entry, int index,
pkt_addr = odp_packet_data(pkt_table[i]);
ret = cls_classify_packet(pktio_entry, pkt_addr,
odp_packet_len(pkt_table[i]),
+ odp_packet_len(pkt_table[i]),
&new_pool, &parsed_hdr);
if (ret) {
failed++;