Message ID | 1473777012-21850-1-git-send-email-matias.elo@nokia.com |
---|---|
State | Accepted |
Commit | 144a1d8c4d0265ff3ff6ae740b4e99045645e59d |
Headers | show |
For this series: Reviewed-and-tested-by: Bill Fischofer <bill.fischofer@linaro.org> On Tue, Sep 13, 2016 at 9:30 AM, Matias Elo <matias.elo@nokia.com> wrote: > Enable parsing packet headers up to a given protocol layer. > > Signed-off-by: Matias Elo <matias.elo@nokia.com> > --- > .../linux-generic/include/odp_packet_internal.h | 24 +- > platform/linux-generic/odp_classification.c | 2 +- > platform/linux-generic/odp_packet.c | 293 > ++++++++++++--------- > 3 files changed, 193 insertions(+), 126 deletions(-) > > diff --git a/platform/linux-generic/include/odp_packet_internal.h > b/platform/linux-generic/include/odp_packet_internal.h > index 392d670..9b4f59e 100644 > --- a/platform/linux-generic/include/odp_packet_internal.h > +++ b/platform/linux-generic/include/odp_packet_internal.h > @@ -41,7 +41,6 @@ typedef union { > > struct { > uint64_t parsed_l2:1; /**< L2 parsed */ > - uint64_t parsed_all:1;/**< Parsing complete */ > uint64_t dst_queue:1; /**< Dst queue present */ > > uint64_t flow_hash:1; /**< Flow hash present */ > @@ -131,6 +130,18 @@ ODP_STATIC_ASSERT(sizeof(output_flags_t) == > sizeof(uint32_t), > "OUTPUT_FLAGS_SIZE_ERROR"); > > /** > + * Protocol stack layers > + */ > +typedef enum { > + LAYER_NONE = 0, > + LAYER_L1, > + LAYER_L2, > + LAYER_L3, > + LAYER_L4, > + LAYER_ALL > +} layer_t; > + > +/** > * Packet parser metadata > */ > typedef struct { > @@ -145,6 +156,10 @@ typedef struct { > uint32_t l3_len; /**< Layer 3 length */ > uint32_t l4_len; /**< Layer 4 length */ > > + layer_t parsed_layers; /**< Highest parsed protocol stack layer */ > + uint16_t ethtype; /**< EtherType */ > + uint8_t ip_proto; /**< IP protocol */ > + > } packet_parser_t; > > /** > @@ -300,7 +315,7 @@ static inline int packet_parse_l2_not_done(packet_parser_t > *prs) > > static inline int packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr) > { > - return !pkt_hdr->p.input_flags.parsed_all; > + return pkt_hdr->p.parsed_layers != LAYER_ALL; > } > > /* Forward declarations */ > @@ -316,6 +331,9 @@ void packet_parse_l2(packet_parser_t *prs, uint32_t > frame_len); > /* Perform full packet parse */ > int packet_parse_full(odp_packet_hdr_t *pkt_hdr); > > +/* Perform packet parse up to a given protocol layer */ > +int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, layer_t layer); > + > /* Reset parser metadata for a new parse */ > void packet_parse_reset(odp_packet_hdr_t *pkt_hdr); > > @@ -349,7 +367,7 @@ static inline void packet_set_ts(odp_packet_hdr_t > *pkt_hdr, odp_time_t *ts) > } > > int packet_parse_common(packet_parser_t *pkt_hdr, const uint8_t *ptr, > - uint32_t pkt_len, uint32_t seg_len); > + uint32_t pkt_len, uint32_t seg_len, layer_t layer); > > int _odp_cls_parse(odp_packet_hdr_t *pkt_hdr, const uint8_t *parseptr); > > diff --git a/platform/linux-generic/odp_classification.c > b/platform/linux-generic/odp_classification.c > index ea223bf..868058d 100644 > --- a/platform/linux-generic/odp_classification.c > +++ b/platform/linux-generic/odp_classification.c > @@ -821,7 +821,7 @@ int cls_classify_packet(pktio_entry_t *entry, const > uint8_t *base, > packet_parse_reset(pkt_hdr); > packet_set_len(pkt_hdr, pkt_len); > > - packet_parse_common(&pkt_hdr->p, base, pkt_len, seg_len); > + packet_parse_common(&pkt_hdr->p, base, pkt_len, seg_len, > LAYER_ALL); > cos = cls_select_cos(entry, base, pkt_hdr); > > if (cos == NULL) > diff --git a/platform/linux-generic/odp_packet.c > b/platform/linux-generic/odp_packet.c > index c4cf324..5f84869 100644 > --- a/platform/linux-generic/odp_packet.c > +++ b/platform/linux-generic/odp_packet.c > @@ -30,12 +30,13 @@ > static inline void packet_parse_disable(odp_packet_hdr_t *pkt_hdr) > { > pkt_hdr->p.input_flags.parsed_l2 = 1; > - pkt_hdr->p.input_flags.parsed_all = 1; > + pkt_hdr->p.parsed_layers = LAYER_ALL; > } > > void packet_parse_reset(odp_packet_hdr_t *pkt_hdr) > { > /* Reset parser metadata before new parse */ > + pkt_hdr->p.parsed_layers = LAYER_NONE; > pkt_hdr->p.error_flags.all = 0; > pkt_hdr->p.input_flags.all = 0; > pkt_hdr->p.output_flags.all = 0; > @@ -50,6 +51,8 @@ void packet_parse_reset(odp_packet_hdr_t *pkt_hdr) > static void packet_init(pool_entry_t *pool, odp_packet_hdr_t *pkt_hdr, > size_t size, int parse) > { > + pkt_hdr->p.parsed_layers = LAYER_NONE; > + > pkt_hdr->p.input_flags.all = 0; > pkt_hdr->p.output_flags.all = 0; > pkt_hdr->p.error_flags.all = 0; > @@ -1166,151 +1169,185 @@ void packet_parse_l2(packet_parser_t *prs, > uint32_t frame_len) > } > > /** > - * Parse common packet headers > + * Parse common packet headers up to given layer > * > * 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) > + uint32_t frame_len, uint32_t seg_len, layer_t > layer) > { > - const _odp_ethhdr_t *eth; > - const _odp_vlanhdr_t *vlan; > - uint16_t ethtype; > uint32_t offset; > - uint8_t ip_proto = 0; > const uint8_t *parseptr; > - uint16_t macaddr0, macaddr2, macaddr4; > - > - offset = sizeof(_odp_ethhdr_t); > - if (packet_parse_l2_not_done(prs)) > - packet_parse_l2(prs, frame_len); > - > - eth = (const _odp_ethhdr_t *)ptr; > - > - /* Handle Ethernet broadcast/multicast addresses */ > - macaddr0 = odp_be_to_cpu_16(*((const uint16_t *)(const void > *)eth)); > - prs->input_flags.eth_mcast = (macaddr0 & 0x0100) == 0x0100; > - > - if (macaddr0 == 0xffff) { > - macaddr2 = > - odp_be_to_cpu_16(*((const uint16_t *) > - (const void *)eth + 1)); > - macaddr4 = > - odp_be_to_cpu_16(*((const uint16_t *) > - (const void *)eth + 2)); > - prs->input_flags.eth_bcast = > - (macaddr2 == 0xffff) && (macaddr4 == 0xffff); > - } else { > - prs->input_flags.eth_bcast = 0; > - } > - > - /* Get Ethertype */ > - ethtype = odp_be_to_cpu_16(eth->type); > - parseptr = (const uint8_t *)(eth + 1); > > - /* Check for SNAP vs. DIX */ > - if (ethtype < _ODP_ETH_LEN_MAX) { > - prs->input_flags.snap = 1; > - if (ethtype > frame_len - offset) { > - prs->error_flags.snap_len = 1; > - goto parse_exit; > + switch (prs->parsed_layers) { > + case LAYER_NONE: > + case LAYER_L2: > + { > + const _odp_ethhdr_t *eth; > + uint16_t macaddr0, macaddr2, macaddr4; > + const _odp_vlanhdr_t *vlan; > + > + offset = sizeof(_odp_ethhdr_t); > + if (packet_parse_l2_not_done(prs)) > + packet_parse_l2(prs, frame_len); > + > + eth = (const _odp_ethhdr_t *)ptr; > + > + /* Handle Ethernet broadcast/multicast addresses */ > + macaddr0 = odp_be_to_cpu_16(*((const uint16_t *) > + (const void *)eth)); > + prs->input_flags.eth_mcast = (macaddr0 & 0x0100) == 0x0100; > + > + if (macaddr0 == 0xffff) { > + macaddr2 = > + odp_be_to_cpu_16(*((const uint16_t *) > + (const void *)eth + 1)); > + macaddr4 = > + odp_be_to_cpu_16(*((const uint16_t *) > + (const void *)eth + 2)); > + prs->input_flags.eth_bcast = > + (macaddr2 == 0xffff) && (macaddr4 == > 0xffff); > + } else { > + prs->input_flags.eth_bcast = 0; > } > - ethtype = odp_be_to_cpu_16(*((const uint16_t *) > - (uintptr_t)(parseptr + 6))); > - offset += 8; > - parseptr += 8; > - } > - > - /* Parse the VLAN header(s), if present */ > - if (ethtype == _ODP_ETHTYPE_VLAN_OUTER) { > - prs->input_flags.vlan_qinq = 1; > - prs->input_flags.vlan = 1; > - > - vlan = (const _odp_vlanhdr_t *)parseptr; > - ethtype = odp_be_to_cpu_16(vlan->type); > - offset += sizeof(_odp_vlanhdr_t); > - parseptr += sizeof(_odp_vlanhdr_t); > - } > - > - if (ethtype == _ODP_ETHTYPE_VLAN) { > - prs->input_flags.vlan = 1; > - vlan = (const _odp_vlanhdr_t *)parseptr; > - ethtype = odp_be_to_cpu_16(vlan->type); > - offset += sizeof(_odp_vlanhdr_t); > - parseptr += sizeof(_odp_vlanhdr_t); > - } > > - /* Set l3_offset+flag only for known ethtypes */ > - prs->input_flags.l3 = 1; > - prs->l3_offset = offset; > + /* Get Ethertype */ > + prs->ethtype = odp_be_to_cpu_16(eth->type); > + parseptr = (const uint8_t *)(eth + 1); > + > + /* Check for SNAP vs. DIX */ > + if (prs->ethtype < _ODP_ETH_LEN_MAX) { > + prs->input_flags.snap = 1; > + if (prs->ethtype > frame_len - offset) { > + prs->error_flags.snap_len = 1; > + goto parse_exit; > + } > + prs->ethtype = odp_be_to_cpu_16(*((const uint16_t > *) > + (uintptr_t) > + (parseptr + 6))); > + offset += 8; > + parseptr += 8; > + } > > - /* Parse Layer 3 headers */ > - switch (ethtype) { > - case _ODP_ETHTYPE_IPV4: > - prs->input_flags.ipv4 = 1; > - ip_proto = parse_ipv4(prs, &parseptr, &offset, frame_len); > - break; > + /* Parse the VLAN header(s), if present */ > + if (prs->ethtype == _ODP_ETHTYPE_VLAN_OUTER) { > + prs->input_flags.vlan_qinq = 1; > + prs->input_flags.vlan = 1; > > - case _ODP_ETHTYPE_IPV6: > - prs->input_flags.ipv6 = 1; > - ip_proto = parse_ipv6(prs, &parseptr, &offset, frame_len, > - seg_len); > - break; > + vlan = (const _odp_vlanhdr_t *)parseptr; > + prs->ethtype = odp_be_to_cpu_16(vlan->type); > + offset += sizeof(_odp_vlanhdr_t); > + parseptr += sizeof(_odp_vlanhdr_t); > + } > > - case _ODP_ETHTYPE_ARP: > - prs->input_flags.arp = 1; > - ip_proto = 255; /* Reserved invalid by IANA */ > - break; > + if (prs->ethtype == _ODP_ETHTYPE_VLAN) { > + prs->input_flags.vlan = 1; > + vlan = (const _odp_vlanhdr_t *)parseptr; > + prs->ethtype = odp_be_to_cpu_16(vlan->type); > + offset += sizeof(_odp_vlanhdr_t); > + parseptr += sizeof(_odp_vlanhdr_t); > + } > > - default: > - prs->input_flags.l3 = 0; > - prs->l3_offset = ODP_PACKET_OFFSET_INVALID; > - ip_proto = 255; /* Reserved invalid by IANA */ > + prs->l3_offset = offset; > + prs->parsed_layers = LAYER_L2; > + if (layer == LAYER_L2) > + return prs->error_flags.all != 0; > } > + case LAYER_L3: > + { > + offset = prs->l3_offset; > + parseptr = (const uint8_t *)(ptr + offset); > + /* Set l3_offset+flag only for known ethtypes */ > + prs->input_flags.l3 = 1; > + > + /* Parse Layer 3 headers */ > + switch (prs->ethtype) { > + case _ODP_ETHTYPE_IPV4: > + prs->input_flags.ipv4 = 1; > + prs->ip_proto = parse_ipv4(prs, &parseptr, &offset, > + frame_len); > + break; > + > + case _ODP_ETHTYPE_IPV6: > + prs->input_flags.ipv6 = 1; > + prs->ip_proto = parse_ipv6(prs, &parseptr, &offset, > + frame_len, seg_len); > + break; > + > + case _ODP_ETHTYPE_ARP: > + prs->input_flags.arp = 1; > + prs->ip_proto = 255; /* Reserved invalid by IANA > */ > + break; > + > + default: > + prs->input_flags.l3 = 0; > + prs->l3_offset = ODP_PACKET_OFFSET_INVALID; > + prs->ip_proto = 255; /* Reserved invalid by IANA > */ > + } > > - /* Set l4_offset+flag only for known ip_proto */ > - prs->input_flags.l4 = 1; > - prs->l4_offset = offset; > - > - /* Parse Layer 4 headers */ > - switch (ip_proto) { > - case _ODP_IPPROTO_ICMP: > - prs->input_flags.icmp = 1; > - break; > - > - case _ODP_IPPROTO_TCP: > - if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len)) > - return -1; > - prs->input_flags.tcp = 1; > - parse_tcp(prs, &parseptr, NULL); > - break; > - > - case _ODP_IPPROTO_UDP: > - if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len)) > - return -1; > - prs->input_flags.udp = 1; > - parse_udp(prs, &parseptr, NULL); > - break; > + /* Set l4_offset+flag only for known ip_proto */ > + prs->l4_offset = offset; > + prs->parsed_layers = LAYER_L3; > + if (layer == LAYER_L3) > + return prs->error_flags.all != 0; > + } > + case LAYER_L4: > + { > + offset = prs->l4_offset; > + parseptr = (const uint8_t *)(ptr + offset); > + prs->input_flags.l4 = 1; > + > + /* Parse Layer 4 headers */ > + switch (prs->ip_proto) { > + case _ODP_IPPROTO_ICMP: > + prs->input_flags.icmp = 1; > + break; > + > + case _ODP_IPPROTO_TCP: > + if (odp_unlikely(offset + _ODP_TCPHDR_LEN > > seg_len)) > + return -1; > + prs->input_flags.tcp = 1; > + parse_tcp(prs, &parseptr, NULL); > + break; > + > + case _ODP_IPPROTO_UDP: > + if (odp_unlikely(offset + _ODP_UDPHDR_LEN > > seg_len)) > + return -1; > + prs->input_flags.udp = 1; > + parse_udp(prs, &parseptr, NULL); > + break; > + > + case _ODP_IPPROTO_AH: > + prs->input_flags.ipsec = 1; > + prs->input_flags.ipsec_ah = 1; > + break; > + > + case _ODP_IPPROTO_ESP: > + prs->input_flags.ipsec = 1; > + prs->input_flags.ipsec_esp = 1; > + break; > + > + default: > + prs->input_flags.l4 = 0; > + prs->l4_offset = ODP_PACKET_OFFSET_INVALID; > + break; > + } > > - case _ODP_IPPROTO_AH: > - prs->input_flags.ipsec = 1; > - prs->input_flags.ipsec_ah = 1; > + prs->parsed_layers = LAYER_L4; > break; > - > - case _ODP_IPPROTO_ESP: > - prs->input_flags.ipsec = 1; > - prs->input_flags.ipsec_esp = 1; > + } > + case LAYER_ALL: > break; > > default: > - prs->input_flags.l4 = 0; > - prs->l4_offset = ODP_PACKET_OFFSET_INVALID; > - break; > + ODP_ERR("Invalid parse layer: %d\n", (int)layer); > + return -1; > } > > + prs->parsed_layers = LAYER_ALL; > + > parse_exit: > - prs->input_flags.parsed_all = 1; > return prs->error_flags.all != 0; > } > > @@ -1323,5 +1360,17 @@ int packet_parse_full(odp_packet_hdr_t *pkt_hdr) > void *base = packet_map(pkt_hdr, 0, &seg_len); > > return packet_parse_common(&pkt_hdr->p, base, pkt_hdr->frame_len, > - seg_len); > + seg_len, LAYER_ALL); > +} > + > +/** > + * Simple packet parser > + */ > +int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, layer_t layer) > +{ > + uint32_t seg_len; > + void *base = packet_map(pkt_hdr, 0, &seg_len); > + > + return packet_parse_common(&pkt_hdr->p, base, pkt_hdr->frame_len, > + seg_len, layer); > } > -- > 2.7.4 > >
Merged, Maxim. On 10/24/16 14:48, Elo, Matias (Nokia - FI/Espoo) wrote: > Ping. This patch set has been reviewed and tested. > > -Matias > > > On 21 Sep 2016, at 22.36, Bill Fischofer <bill.fischofer@linaro.org<mailto:bill.fischofer@linaro.org>> wrote: > > For this series: > > Reviewed-and-tested-by: Bill Fischofer <bill.fischofer@linaro.org<mailto:bill.fischofer@linaro.org>> > > On Tue, Sep 13, 2016 at 9:30 AM, Matias Elo <matias.elo@nokia.com<mailto:matias.elo@nokia.com>> wrote: > Enable parsing packet headers up to a given protocol layer. > > Signed-off-by: Matias Elo <matias.elo@nokia.com<mailto:matias.elo@nokia.com>> > --- > .../linux-generic/include/odp_packet_internal.h | 24 +- > platform/linux-generic/odp_classification.c | 2 +- > platform/linux-generic/odp_packet.c | 293 ++++++++++++--------- > 3 files changed, 193 insertions(+), 126 deletions(-) > > diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h > index 392d670..9b4f59e 100644 > --- a/platform/linux-generic/include/odp_packet_internal.h > +++ b/platform/linux-generic/include/odp_packet_internal.h > @@ -41,7 +41,6 @@ typedef union { > > struct { > uint64_t parsed_l2:1; /**< L2 parsed */ > - uint64_t parsed_all:1;/**< Parsing complete */ > uint64_t dst_queue:1; /**< Dst queue present */ > > uint64_t flow_hash:1; /**< Flow hash present */ > @@ -131,6 +130,18 @@ ODP_STATIC_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t), > "OUTPUT_FLAGS_SIZE_ERROR"); > > /** > + * Protocol stack layers > + */ > +typedef enum { > + LAYER_NONE = 0, > + LAYER_L1, > + LAYER_L2, > + LAYER_L3, > + LAYER_L4, > + LAYER_ALL > +} layer_t; > + > +/** > * Packet parser metadata > */ > typedef struct { > @@ -145,6 +156,10 @@ typedef struct { > uint32_t l3_len; /**< Layer 3 length */ > uint32_t l4_len; /**< Layer 4 length */ > > + layer_t parsed_layers; /**< Highest parsed protocol stack layer */ > + uint16_t ethtype; /**< EtherType */ > + uint8_t ip_proto; /**< IP protocol */ > + > } packet_parser_t; > > /** > @@ -300,7 +315,7 @@ static inline int packet_parse_l2_not_done(packet_parser_t *prs) > > static inline int packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr) > { > - return !pkt_hdr->p.input_flags.parsed_all; > + return pkt_hdr->p.parsed_layers != LAYER_ALL; > } > > /* Forward declarations */ > @@ -316,6 +331,9 @@ void packet_parse_l2(packet_parser_t *prs, uint32_t frame_len); > /* Perform full packet parse */ > int packet_parse_full(odp_packet_hdr_t *pkt_hdr); > > +/* Perform packet parse up to a given protocol layer */ > +int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, layer_t layer); > + > /* Reset parser metadata for a new parse */ > void packet_parse_reset(odp_packet_hdr_t *pkt_hdr); > > @@ -349,7 +367,7 @@ static inline void packet_set_ts(odp_packet_hdr_t *pkt_hdr, odp_time_t *ts) > } > > int packet_parse_common(packet_parser_t *pkt_hdr, const uint8_t *ptr, > - uint32_t pkt_len, uint32_t seg_len); > + uint32_t pkt_len, uint32_t seg_len, layer_t layer); > > int _odp_cls_parse(odp_packet_hdr_t *pkt_hdr, const uint8_t *parseptr); > > diff --git a/platform/linux-generic/odp_classification.c b/platform/linux-generic/odp_classification.c > index ea223bf..868058d 100644 > --- a/platform/linux-generic/odp_classification.c > +++ b/platform/linux-generic/odp_classification.c > @@ -821,7 +821,7 @@ int cls_classify_packet(pktio_entry_t *entry, const uint8_t *base, > packet_parse_reset(pkt_hdr); > packet_set_len(pkt_hdr, pkt_len); > > - packet_parse_common(&pkt_hdr->p, base, pkt_len, seg_len); > + packet_parse_common(&pkt_hdr->p, base, pkt_len, seg_len, LAYER_ALL); > cos = cls_select_cos(entry, base, pkt_hdr); > > if (cos == NULL) > diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c > index c4cf324..5f84869 100644 > --- a/platform/linux-generic/odp_packet.c > +++ b/platform/linux-generic/odp_packet.c > @@ -30,12 +30,13 @@ > static inline void packet_parse_disable(odp_packet_hdr_t *pkt_hdr) > { > pkt_hdr->p.input_flags.parsed_l2 = 1; > - pkt_hdr->p.input_flags.parsed_all = 1; > + pkt_hdr->p.parsed_layers = LAYER_ALL; > } > > void packet_parse_reset(odp_packet_hdr_t *pkt_hdr) > { > /* Reset parser metadata before new parse */ > + pkt_hdr->p.parsed_layers = LAYER_NONE; > pkt_hdr->p.error_flags.all = 0; > pkt_hdr->p.input_flags.all = 0; > pkt_hdr->p.output_flags.all = 0; > @@ -50,6 +51,8 @@ void packet_parse_reset(odp_packet_hdr_t *pkt_hdr) > static void packet_init(pool_entry_t *pool, odp_packet_hdr_t *pkt_hdr, > size_t size, int parse) > { > + pkt_hdr->p.parsed_layers = LAYER_NONE; > + > pkt_hdr->p.input_flags.all = 0; > pkt_hdr->p.output_flags.all = 0; > pkt_hdr->p.error_flags.all = 0; > @@ -1166,151 +1169,185 @@ void packet_parse_l2(packet_parser_t *prs, uint32_t frame_len) > } > > /** > - * Parse common packet headers > + * Parse common packet headers up to given layer > * > * 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) > + uint32_t frame_len, uint32_t seg_len, layer_t layer) > { > - const _odp_ethhdr_t *eth; > - const _odp_vlanhdr_t *vlan; > - uint16_t ethtype; > uint32_t offset; > - uint8_t ip_proto = 0; > const uint8_t *parseptr; > - uint16_t macaddr0, macaddr2, macaddr4; > - > - offset = sizeof(_odp_ethhdr_t); > - if (packet_parse_l2_not_done(prs)) > - packet_parse_l2(prs, frame_len); > - > - eth = (const _odp_ethhdr_t *)ptr; > - > - /* Handle Ethernet broadcast/multicast addresses */ > - macaddr0 = odp_be_to_cpu_16(*((const uint16_t *)(const void *)eth)); > - prs->input_flags.eth_mcast = (macaddr0 & 0x0100) == 0x0100; > - > - if (macaddr0 == 0xffff) { > - macaddr2 = > - odp_be_to_cpu_16(*((const uint16_t *) > - (const void *)eth + 1)); > - macaddr4 = > - odp_be_to_cpu_16(*((const uint16_t *) > - (const void *)eth + 2)); > - prs->input_flags.eth_bcast = > - (macaddr2 == 0xffff) && (macaddr4 == 0xffff); > - } else { > - prs->input_flags.eth_bcast = 0; > - } > - > - /* Get Ethertype */ > - ethtype = odp_be_to_cpu_16(eth->type); > - parseptr = (const uint8_t *)(eth + 1); > > - /* Check for SNAP vs. DIX */ > - if (ethtype < _ODP_ETH_LEN_MAX) { > - prs->input_flags.snap = 1; > - if (ethtype > frame_len - offset) { > - prs->error_flags.snap_len = 1; > - goto parse_exit; > + switch (prs->parsed_layers) { > + case LAYER_NONE: > + case LAYER_L2: > + { > + const _odp_ethhdr_t *eth; > + uint16_t macaddr0, macaddr2, macaddr4; > + const _odp_vlanhdr_t *vlan; > + > + offset = sizeof(_odp_ethhdr_t); > + if (packet_parse_l2_not_done(prs)) > + packet_parse_l2(prs, frame_len); > + > + eth = (const _odp_ethhdr_t *)ptr; > + > + /* Handle Ethernet broadcast/multicast addresses */ > + macaddr0 = odp_be_to_cpu_16(*((const uint16_t *) > + (const void *)eth)); > + prs->input_flags.eth_mcast = (macaddr0 & 0x0100) == 0x0100; > + > + if (macaddr0 == 0xffff) { > + macaddr2 = > + odp_be_to_cpu_16(*((const uint16_t *) > + (const void *)eth + 1)); > + macaddr4 = > + odp_be_to_cpu_16(*((const uint16_t *) > + (const void *)eth + 2)); > + prs->input_flags.eth_bcast = > + (macaddr2 == 0xffff) && (macaddr4 == 0xffff); > + } else { > + prs->input_flags.eth_bcast = 0; > } > - ethtype = odp_be_to_cpu_16(*((const uint16_t *) > - (uintptr_t)(parseptr + 6))); > - offset += 8; > - parseptr += 8; > - } > - > - /* Parse the VLAN header(s), if present */ > - if (ethtype == _ODP_ETHTYPE_VLAN_OUTER) { > - prs->input_flags.vlan_qinq = 1; > - prs->input_flags.vlan = 1; > - > - vlan = (const _odp_vlanhdr_t *)parseptr; > - ethtype = odp_be_to_cpu_16(vlan->type); > - offset += sizeof(_odp_vlanhdr_t); > - parseptr += sizeof(_odp_vlanhdr_t); > - } > - > - if (ethtype == _ODP_ETHTYPE_VLAN) { > - prs->input_flags.vlan = 1; > - vlan = (const _odp_vlanhdr_t *)parseptr; > - ethtype = odp_be_to_cpu_16(vlan->type); > - offset += sizeof(_odp_vlanhdr_t); > - parseptr += sizeof(_odp_vlanhdr_t); > - } > > - /* Set l3_offset+flag only for known ethtypes */ > - prs->input_flags.l3 = 1; > - prs->l3_offset = offset; > + /* Get Ethertype */ > + prs->ethtype = odp_be_to_cpu_16(eth->type); > + parseptr = (const uint8_t *)(eth + 1); > + > + /* Check for SNAP vs. DIX */ > + if (prs->ethtype < _ODP_ETH_LEN_MAX) { > + prs->input_flags.snap = 1; > + if (prs->ethtype > frame_len - offset) { > + prs->error_flags.snap_len = 1; > + goto parse_exit; > + } > + prs->ethtype = odp_be_to_cpu_16(*((const uint16_t *) > + (uintptr_t) > + (parseptr + 6))); > + offset += 8; > + parseptr += 8; > + } > > - /* Parse Layer 3 headers */ > - switch (ethtype) { > - case _ODP_ETHTYPE_IPV4: > - prs->input_flags.ipv4 = 1; > - ip_proto = parse_ipv4(prs, &parseptr, &offset, frame_len); > - break; > + /* Parse the VLAN header(s), if present */ > + if (prs->ethtype == _ODP_ETHTYPE_VLAN_OUTER) { > + prs->input_flags.vlan_qinq = 1; > + prs->input_flags.vlan = 1; > > - case _ODP_ETHTYPE_IPV6: > - prs->input_flags.ipv6 = 1; > - ip_proto = parse_ipv6(prs, &parseptr, &offset, frame_len, > - seg_len); > - break; > + vlan = (const _odp_vlanhdr_t *)parseptr; > + prs->ethtype = odp_be_to_cpu_16(vlan->type); > + offset += sizeof(_odp_vlanhdr_t); > + parseptr += sizeof(_odp_vlanhdr_t); > + } > > - case _ODP_ETHTYPE_ARP: > - prs->input_flags.arp = 1; > - ip_proto = 255; /* Reserved invalid by IANA */ > - break; > + if (prs->ethtype == _ODP_ETHTYPE_VLAN) { > + prs->input_flags.vlan = 1; > + vlan = (const _odp_vlanhdr_t *)parseptr; > + prs->ethtype = odp_be_to_cpu_16(vlan->type); > + offset += sizeof(_odp_vlanhdr_t); > + parseptr += sizeof(_odp_vlanhdr_t); > + } > > - default: > - prs->input_flags.l3 = 0; > - prs->l3_offset = ODP_PACKET_OFFSET_INVALID; > - ip_proto = 255; /* Reserved invalid by IANA */ > + prs->l3_offset = offset; > + prs->parsed_layers = LAYER_L2; > + if (layer == LAYER_L2) > + return prs->error_flags.all != 0; > } > + case LAYER_L3: > + { > + offset = prs->l3_offset; > + parseptr = (const uint8_t *)(ptr + offset); > + /* Set l3_offset+flag only for known ethtypes */ > + prs->input_flags.l3 = 1; > + > + /* Parse Layer 3 headers */ > + switch (prs->ethtype) { > + case _ODP_ETHTYPE_IPV4: > + prs->input_flags.ipv4 = 1; > + prs->ip_proto = parse_ipv4(prs, &parseptr, &offset, > + frame_len); > + break; > + > + case _ODP_ETHTYPE_IPV6: > + prs->input_flags.ipv6 = 1; > + prs->ip_proto = parse_ipv6(prs, &parseptr, &offset, > + frame_len, seg_len); > + break; > + > + case _ODP_ETHTYPE_ARP: > + prs->input_flags.arp = 1; > + prs->ip_proto = 255; /* Reserved invalid by IANA */ > + break; > + > + default: > + prs->input_flags.l3 = 0; > + prs->l3_offset = ODP_PACKET_OFFSET_INVALID; > + prs->ip_proto = 255; /* Reserved invalid by IANA */ > + } > > - /* Set l4_offset+flag only for known ip_proto */ > - prs->input_flags.l4 = 1; > - prs->l4_offset = offset; > - > - /* Parse Layer 4 headers */ > - switch (ip_proto) { > - case _ODP_IPPROTO_ICMP: > - prs->input_flags.icmp = 1; > - break; > - > - case _ODP_IPPROTO_TCP: > - if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len)) > - return -1; > - prs->input_flags.tcp = 1; > - parse_tcp(prs, &parseptr, NULL); > - break; > - > - case _ODP_IPPROTO_UDP: > - if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len)) > - return -1; > - prs->input_flags.udp = 1; > - parse_udp(prs, &parseptr, NULL); > - break; > + /* Set l4_offset+flag only for known ip_proto */ > + prs->l4_offset = offset; > + prs->parsed_layers = LAYER_L3; > + if (layer == LAYER_L3) > + return prs->error_flags.all != 0; > + } > + case LAYER_L4: > + { > + offset = prs->l4_offset; > + parseptr = (const uint8_t *)(ptr + offset); > + prs->input_flags.l4 = 1; > + > + /* Parse Layer 4 headers */ > + switch (prs->ip_proto) { > + case _ODP_IPPROTO_ICMP: > + prs->input_flags.icmp = 1; > + break; > + > + case _ODP_IPPROTO_TCP: > + if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len)) > + return -1; > + prs->input_flags.tcp = 1; > + parse_tcp(prs, &parseptr, NULL); > + break; > + > + case _ODP_IPPROTO_UDP: > + if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len)) > + return -1; > + prs->input_flags.udp = 1; > + parse_udp(prs, &parseptr, NULL); > + break; > + > + case _ODP_IPPROTO_AH: > + prs->input_flags.ipsec = 1; > + prs->input_flags.ipsec_ah = 1; > + break; > + > + case _ODP_IPPROTO_ESP: > + prs->input_flags.ipsec = 1; > + prs->input_flags.ipsec_esp = 1; > + break; > + > + default: > + prs->input_flags.l4 = 0; > + prs->l4_offset = ODP_PACKET_OFFSET_INVALID; > + break; > + } > > - case _ODP_IPPROTO_AH: > - prs->input_flags.ipsec = 1; > - prs->input_flags.ipsec_ah = 1; > + prs->parsed_layers = LAYER_L4; > break; > - > - case _ODP_IPPROTO_ESP: > - prs->input_flags.ipsec = 1; > - prs->input_flags.ipsec_esp = 1; > + } > + case LAYER_ALL: > break; > > default: > - prs->input_flags.l4 = 0; > - prs->l4_offset = ODP_PACKET_OFFSET_INVALID; > - break; > + ODP_ERR("Invalid parse layer: %d\n", (int)layer); > + return -1; > } > > + prs->parsed_layers = LAYER_ALL; > + > parse_exit: > - prs->input_flags.parsed_all = 1; > return prs->error_flags.all != 0; > } > > @@ -1323,5 +1360,17 @@ int packet_parse_full(odp_packet_hdr_t *pkt_hdr) > void *base = packet_map(pkt_hdr, 0, &seg_len); > > return packet_parse_common(&pkt_hdr->p, base, pkt_hdr->frame_len, > - seg_len); > + seg_len, LAYER_ALL); > +} > + > +/** > + * Simple packet parser > + */ > +int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, layer_t layer) > +{ > + uint32_t seg_len; > + void *base = packet_map(pkt_hdr, 0, &seg_len); > + > + return packet_parse_common(&pkt_hdr->p, base, pkt_hdr->frame_len, > + seg_len, layer); > } > -- > 2.7.4 > > >
diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h index 392d670..9b4f59e 100644 --- a/platform/linux-generic/include/odp_packet_internal.h +++ b/platform/linux-generic/include/odp_packet_internal.h @@ -41,7 +41,6 @@ typedef union { struct { uint64_t parsed_l2:1; /**< L2 parsed */ - uint64_t parsed_all:1;/**< Parsing complete */ uint64_t dst_queue:1; /**< Dst queue present */ uint64_t flow_hash:1; /**< Flow hash present */ @@ -131,6 +130,18 @@ ODP_STATIC_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t), "OUTPUT_FLAGS_SIZE_ERROR"); /** + * Protocol stack layers + */ +typedef enum { + LAYER_NONE = 0, + LAYER_L1, + LAYER_L2, + LAYER_L3, + LAYER_L4, + LAYER_ALL +} layer_t; + +/** * Packet parser metadata */ typedef struct { @@ -145,6 +156,10 @@ typedef struct { uint32_t l3_len; /**< Layer 3 length */ uint32_t l4_len; /**< Layer 4 length */ + layer_t parsed_layers; /**< Highest parsed protocol stack layer */ + uint16_t ethtype; /**< EtherType */ + uint8_t ip_proto; /**< IP protocol */ + } packet_parser_t; /** @@ -300,7 +315,7 @@ static inline int packet_parse_l2_not_done(packet_parser_t *prs) static inline int packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr) { - return !pkt_hdr->p.input_flags.parsed_all; + return pkt_hdr->p.parsed_layers != LAYER_ALL; } /* Forward declarations */ @@ -316,6 +331,9 @@ void packet_parse_l2(packet_parser_t *prs, uint32_t frame_len); /* Perform full packet parse */ int packet_parse_full(odp_packet_hdr_t *pkt_hdr); +/* Perform packet parse up to a given protocol layer */ +int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, layer_t layer); + /* Reset parser metadata for a new parse */ void packet_parse_reset(odp_packet_hdr_t *pkt_hdr); @@ -349,7 +367,7 @@ static inline void packet_set_ts(odp_packet_hdr_t *pkt_hdr, odp_time_t *ts) } int packet_parse_common(packet_parser_t *pkt_hdr, const uint8_t *ptr, - uint32_t pkt_len, uint32_t seg_len); + uint32_t pkt_len, uint32_t seg_len, layer_t layer); int _odp_cls_parse(odp_packet_hdr_t *pkt_hdr, const uint8_t *parseptr); diff --git a/platform/linux-generic/odp_classification.c b/platform/linux-generic/odp_classification.c index ea223bf..868058d 100644 --- a/platform/linux-generic/odp_classification.c +++ b/platform/linux-generic/odp_classification.c @@ -821,7 +821,7 @@ int cls_classify_packet(pktio_entry_t *entry, const uint8_t *base, packet_parse_reset(pkt_hdr); packet_set_len(pkt_hdr, pkt_len); - packet_parse_common(&pkt_hdr->p, base, pkt_len, seg_len); + packet_parse_common(&pkt_hdr->p, base, pkt_len, seg_len, LAYER_ALL); cos = cls_select_cos(entry, base, pkt_hdr); if (cos == NULL) diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c index c4cf324..5f84869 100644 --- a/platform/linux-generic/odp_packet.c +++ b/platform/linux-generic/odp_packet.c @@ -30,12 +30,13 @@ static inline void packet_parse_disable(odp_packet_hdr_t *pkt_hdr) { pkt_hdr->p.input_flags.parsed_l2 = 1; - pkt_hdr->p.input_flags.parsed_all = 1; + pkt_hdr->p.parsed_layers = LAYER_ALL; } void packet_parse_reset(odp_packet_hdr_t *pkt_hdr) { /* Reset parser metadata before new parse */ + pkt_hdr->p.parsed_layers = LAYER_NONE; pkt_hdr->p.error_flags.all = 0; pkt_hdr->p.input_flags.all = 0; pkt_hdr->p.output_flags.all = 0; @@ -50,6 +51,8 @@ void packet_parse_reset(odp_packet_hdr_t *pkt_hdr) static void packet_init(pool_entry_t *pool, odp_packet_hdr_t *pkt_hdr, size_t size, int parse) { + pkt_hdr->p.parsed_layers = LAYER_NONE; + pkt_hdr->p.input_flags.all = 0; pkt_hdr->p.output_flags.all = 0; pkt_hdr->p.error_flags.all = 0; @@ -1166,151 +1169,185 @@ void packet_parse_l2(packet_parser_t *prs, uint32_t frame_len) } /** - * Parse common packet headers + * Parse common packet headers up to given layer * * 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) + uint32_t frame_len, uint32_t seg_len, layer_t layer) { - const _odp_ethhdr_t *eth; - const _odp_vlanhdr_t *vlan; - uint16_t ethtype; uint32_t offset; - uint8_t ip_proto = 0; const uint8_t *parseptr; - uint16_t macaddr0, macaddr2, macaddr4; - - offset = sizeof(_odp_ethhdr_t); - if (packet_parse_l2_not_done(prs)) - packet_parse_l2(prs, frame_len); - - eth = (const _odp_ethhdr_t *)ptr; - - /* Handle Ethernet broadcast/multicast addresses */ - macaddr0 = odp_be_to_cpu_16(*((const uint16_t *)(const void *)eth)); - prs->input_flags.eth_mcast = (macaddr0 & 0x0100) == 0x0100; - - if (macaddr0 == 0xffff) { - macaddr2 = - odp_be_to_cpu_16(*((const uint16_t *) - (const void *)eth + 1)); - macaddr4 = - odp_be_to_cpu_16(*((const uint16_t *) - (const void *)eth + 2)); - prs->input_flags.eth_bcast = - (macaddr2 == 0xffff) && (macaddr4 == 0xffff); - } else { - prs->input_flags.eth_bcast = 0; - } - - /* Get Ethertype */ - ethtype = odp_be_to_cpu_16(eth->type); - parseptr = (const uint8_t *)(eth + 1); - /* Check for SNAP vs. DIX */ - if (ethtype < _ODP_ETH_LEN_MAX) { - prs->input_flags.snap = 1; - if (ethtype > frame_len - offset) { - prs->error_flags.snap_len = 1; - goto parse_exit; + switch (prs->parsed_layers) { + case LAYER_NONE: + case LAYER_L2: + { + const _odp_ethhdr_t *eth; + uint16_t macaddr0, macaddr2, macaddr4; + const _odp_vlanhdr_t *vlan; + + offset = sizeof(_odp_ethhdr_t); + if (packet_parse_l2_not_done(prs)) + packet_parse_l2(prs, frame_len); + + eth = (const _odp_ethhdr_t *)ptr; + + /* Handle Ethernet broadcast/multicast addresses */ + macaddr0 = odp_be_to_cpu_16(*((const uint16_t *) + (const void *)eth)); + prs->input_flags.eth_mcast = (macaddr0 & 0x0100) == 0x0100; + + if (macaddr0 == 0xffff) { + macaddr2 = + odp_be_to_cpu_16(*((const uint16_t *) + (const void *)eth + 1)); + macaddr4 = + odp_be_to_cpu_16(*((const uint16_t *) + (const void *)eth + 2)); + prs->input_flags.eth_bcast = + (macaddr2 == 0xffff) && (macaddr4 == 0xffff); + } else { + prs->input_flags.eth_bcast = 0; } - ethtype = odp_be_to_cpu_16(*((const uint16_t *) - (uintptr_t)(parseptr + 6))); - offset += 8; - parseptr += 8; - } - - /* Parse the VLAN header(s), if present */ - if (ethtype == _ODP_ETHTYPE_VLAN_OUTER) { - prs->input_flags.vlan_qinq = 1; - prs->input_flags.vlan = 1; - - vlan = (const _odp_vlanhdr_t *)parseptr; - ethtype = odp_be_to_cpu_16(vlan->type); - offset += sizeof(_odp_vlanhdr_t); - parseptr += sizeof(_odp_vlanhdr_t); - } - - if (ethtype == _ODP_ETHTYPE_VLAN) { - prs->input_flags.vlan = 1; - vlan = (const _odp_vlanhdr_t *)parseptr; - ethtype = odp_be_to_cpu_16(vlan->type); - offset += sizeof(_odp_vlanhdr_t); - parseptr += sizeof(_odp_vlanhdr_t); - } - /* Set l3_offset+flag only for known ethtypes */ - prs->input_flags.l3 = 1; - prs->l3_offset = offset; + /* Get Ethertype */ + prs->ethtype = odp_be_to_cpu_16(eth->type); + parseptr = (const uint8_t *)(eth + 1); + + /* Check for SNAP vs. DIX */ + if (prs->ethtype < _ODP_ETH_LEN_MAX) { + prs->input_flags.snap = 1; + if (prs->ethtype > frame_len - offset) { + prs->error_flags.snap_len = 1; + goto parse_exit; + } + prs->ethtype = odp_be_to_cpu_16(*((const uint16_t *) + (uintptr_t) + (parseptr + 6))); + offset += 8; + parseptr += 8; + } - /* Parse Layer 3 headers */ - switch (ethtype) { - case _ODP_ETHTYPE_IPV4: - prs->input_flags.ipv4 = 1; - ip_proto = parse_ipv4(prs, &parseptr, &offset, frame_len); - break; + /* Parse the VLAN header(s), if present */ + if (prs->ethtype == _ODP_ETHTYPE_VLAN_OUTER) { + prs->input_flags.vlan_qinq = 1; + prs->input_flags.vlan = 1; - case _ODP_ETHTYPE_IPV6: - prs->input_flags.ipv6 = 1; - ip_proto = parse_ipv6(prs, &parseptr, &offset, frame_len, - seg_len); - break; + vlan = (const _odp_vlanhdr_t *)parseptr; + prs->ethtype = odp_be_to_cpu_16(vlan->type); + offset += sizeof(_odp_vlanhdr_t); + parseptr += sizeof(_odp_vlanhdr_t); + } - case _ODP_ETHTYPE_ARP: - prs->input_flags.arp = 1; - ip_proto = 255; /* Reserved invalid by IANA */ - break; + if (prs->ethtype == _ODP_ETHTYPE_VLAN) { + prs->input_flags.vlan = 1; + vlan = (const _odp_vlanhdr_t *)parseptr; + prs->ethtype = odp_be_to_cpu_16(vlan->type); + offset += sizeof(_odp_vlanhdr_t); + parseptr += sizeof(_odp_vlanhdr_t); + } - default: - prs->input_flags.l3 = 0; - prs->l3_offset = ODP_PACKET_OFFSET_INVALID; - ip_proto = 255; /* Reserved invalid by IANA */ + prs->l3_offset = offset; + prs->parsed_layers = LAYER_L2; + if (layer == LAYER_L2) + return prs->error_flags.all != 0; } + case LAYER_L3: + { + offset = prs->l3_offset; + parseptr = (const uint8_t *)(ptr + offset); + /* Set l3_offset+flag only for known ethtypes */ + prs->input_flags.l3 = 1; + + /* Parse Layer 3 headers */ + switch (prs->ethtype) { + case _ODP_ETHTYPE_IPV4: + prs->input_flags.ipv4 = 1; + prs->ip_proto = parse_ipv4(prs, &parseptr, &offset, + frame_len); + break; + + case _ODP_ETHTYPE_IPV6: + prs->input_flags.ipv6 = 1; + prs->ip_proto = parse_ipv6(prs, &parseptr, &offset, + frame_len, seg_len); + break; + + case _ODP_ETHTYPE_ARP: + prs->input_flags.arp = 1; + prs->ip_proto = 255; /* Reserved invalid by IANA */ + break; + + default: + prs->input_flags.l3 = 0; + prs->l3_offset = ODP_PACKET_OFFSET_INVALID; + prs->ip_proto = 255; /* Reserved invalid by IANA */ + } - /* Set l4_offset+flag only for known ip_proto */ - prs->input_flags.l4 = 1; - prs->l4_offset = offset; - - /* Parse Layer 4 headers */ - switch (ip_proto) { - case _ODP_IPPROTO_ICMP: - prs->input_flags.icmp = 1; - break; - - case _ODP_IPPROTO_TCP: - if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len)) - return -1; - prs->input_flags.tcp = 1; - parse_tcp(prs, &parseptr, NULL); - break; - - case _ODP_IPPROTO_UDP: - if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len)) - return -1; - prs->input_flags.udp = 1; - parse_udp(prs, &parseptr, NULL); - break; + /* Set l4_offset+flag only for known ip_proto */ + prs->l4_offset = offset; + prs->parsed_layers = LAYER_L3; + if (layer == LAYER_L3) + return prs->error_flags.all != 0; + } + case LAYER_L4: + { + offset = prs->l4_offset; + parseptr = (const uint8_t *)(ptr + offset); + prs->input_flags.l4 = 1; + + /* Parse Layer 4 headers */ + switch (prs->ip_proto) { + case _ODP_IPPROTO_ICMP: + prs->input_flags.icmp = 1; + break; + + case _ODP_IPPROTO_TCP: + if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len)) + return -1; + prs->input_flags.tcp = 1; + parse_tcp(prs, &parseptr, NULL); + break; + + case _ODP_IPPROTO_UDP: + if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len)) + return -1; + prs->input_flags.udp = 1; + parse_udp(prs, &parseptr, NULL); + break; + + case _ODP_IPPROTO_AH: + prs->input_flags.ipsec = 1; + prs->input_flags.ipsec_ah = 1; + break; + + case _ODP_IPPROTO_ESP: + prs->input_flags.ipsec = 1; + prs->input_flags.ipsec_esp = 1; + break; + + default: + prs->input_flags.l4 = 0; + prs->l4_offset = ODP_PACKET_OFFSET_INVALID; + break; + } - case _ODP_IPPROTO_AH: - prs->input_flags.ipsec = 1; - prs->input_flags.ipsec_ah = 1; + prs->parsed_layers = LAYER_L4; break; - - case _ODP_IPPROTO_ESP: - prs->input_flags.ipsec = 1; - prs->input_flags.ipsec_esp = 1; + } + case LAYER_ALL: break; default: - prs->input_flags.l4 = 0; - prs->l4_offset = ODP_PACKET_OFFSET_INVALID; - break; + ODP_ERR("Invalid parse layer: %d\n", (int)layer); + return -1; } + prs->parsed_layers = LAYER_ALL; + parse_exit: - prs->input_flags.parsed_all = 1; return prs->error_flags.all != 0; } @@ -1323,5 +1360,17 @@ int packet_parse_full(odp_packet_hdr_t *pkt_hdr) void *base = packet_map(pkt_hdr, 0, &seg_len); return packet_parse_common(&pkt_hdr->p, base, pkt_hdr->frame_len, - seg_len); + seg_len, LAYER_ALL); +} + +/** + * Simple packet parser + */ +int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, layer_t layer) +{ + uint32_t seg_len; + void *base = packet_map(pkt_hdr, 0, &seg_len); + + return packet_parse_common(&pkt_hdr->p, base, pkt_hdr->frame_len, + seg_len, layer); }
Enable parsing packet headers up to a given protocol layer. Signed-off-by: Matias Elo <matias.elo@nokia.com> --- .../linux-generic/include/odp_packet_internal.h | 24 +- platform/linux-generic/odp_classification.c | 2 +- platform/linux-generic/odp_packet.c | 293 ++++++++++++--------- 3 files changed, 193 insertions(+), 126 deletions(-) -- 2.7.4