platform/linux-generic/odp_packet.c
int packet_parse_common(packet_parser_t *prs, const uint8_t *ptr,
			uint32_t frame_len, uint32_t seg_len,
			odp_pktio_parser_layer_t layer)
{
	uint32_t offset;
	uint16_t ethtype;
	const uint8_t *parseptr;
	uint8_t  ip_proto;
	const _odp_ethhdr_t *eth;
	uint16_t macaddr0, macaddr2, macaddr4;
	const _odp_vlanhdr_t *vlan;

	if (layer == ODP_PKTIO_PARSER_LAYER_NONE)
		return 0;

	/* We only support Ethernet for now */
	prs->input_flags.eth = 1;
	/* Assume valid L2 header, no CRC/FCS check in SW */
	prs->input_flags.l2 = 1;
	/* Detect jumbo frames */
	if (frame_len > _ODP_ETH_LEN_MAX)
		prs->input_flags.jumbo = 1;

	offset = sizeof(_odp_ethhdr_t);
	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;
		}
		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);
	}

	if (layer == ODP_PKTIO_PARSER_LAYER_L2)
		return prs->error_flags.all != 0;

	/* Set l3_offset+flag only for known ethtypes */
	prs->l3_offset = offset;
	prs->input_flags.l3 = 1;

	/* 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;

	case _ODP_ETHTYPE_IPV6:
		prs->input_flags.ipv6 = 1;
		ip_proto = parse_ipv6(prs, &parseptr, &offset, frame_len,
				      seg_len);
		break;

	case _ODP_ETHTYPE_ARP:
		prs->input_flags.arp = 1;
		ip_proto = 255;  /* Reserved invalid by IANA */
		break;

	default:
		prs->input_flags.l3 = 0;
		prs->l3_offset = ODP_PACKET_OFFSET_INVALID;
		ip_proto = 255;  /* Reserved invalid by IANA */
	}

	if (layer == ODP_PKTIO_PARSER_LAYER_L3)
		return prs->error_flags.all != 0;

	/* Set l4_offset+flag only for known ip_proto */
	prs->l4_offset = offset;
	prs->input_flags.l4 = 1;

	/* Parse Layer 4 headers */
	switch (ip_proto) {
	case _ODP_IPPROTO_ICMPv4:
	/* Fall through */

	case _ODP_IPPROTO_ICMPv6:
		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;

	case _ODP_IPPROTO_SCTP:
		prs->input_flags.sctp = 1;
		break;

	default:
		prs->input_flags.l4 = 0;
		prs->l4_offset = ODP_PACKET_OFFSET_INVALID;
		break;
	}
parse_exit:
	return prs->error_flags.all != 0;
}
/**
 * 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.
 */
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.
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,
			odp_pktio_parser_layer_t layer)
{
	uint32_t offset;
	uint16_t ethtype;
	const uint8_t *parseptr;
	uint8_t  ip_proto;
	const _odp_ethhdr_t *eth;
	uint16_t macaddr0, macaddr2, macaddr4;
	const _odp_vlanhdr_t *vlan;
	if (layer == ODP_PKTIO_PARSER_LAYER_NONE)
		return 0;
	prs->input_flags.eth = 1;
	prs->input_flags.l2 = 1;
	if (frame_len > _ODP_ETH_LEN_MAX)
		prs->input_flags.jumbo = 1;
	offset = sizeof(_odp_ethhdr_t);
	eth = (const _odp_ethhdr_t *)ptr;
	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(eth->type);
	parseptr = (const uint8_t *)(eth + 1);
	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;
		}
		ethtype = odp_be_to_cpu_16(*((const uint16_t *)(uintptr_t)
					     (parseptr + 6)));
		offset   += 8;
		parseptr += 8;
	}
	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);
	}
	if (layer == ODP_PKTIO_PARSER_LAYER_L2)
		return prs->error_flags.all != 0;
	prs->l3_offset = offset;
	prs->input_flags.l3 = 1;
	switch (ethtype) {
	case _ODP_ETHTYPE_IPV4:
		prs->input_flags.ipv4 = 1;
		ip_proto = parse_ipv4(prs, &parseptr, &offset, frame_len);
		break;
	case _ODP_ETHTYPE_IPV6:
		prs->input_flags.ipv6 = 1;
		ip_proto = parse_ipv6(prs, &parseptr, &offset, frame_len,
				      seg_len);
		break;
	case _ODP_ETHTYPE_ARP:
		prs->input_flags.arp = 1;
		ip_proto = 255;  
		break;
	default:
		prs->input_flags.l3 = 0;
		prs->l3_offset = ODP_PACKET_OFFSET_INVALID;
		ip_proto = 255;  
	}
	if (layer == ODP_PKTIO_PARSER_LAYER_L3)
		return prs->error_flags.all != 0;
	prs->l4_offset = offset;
	prs->input_flags.l4 = 1;
	switch (ip_proto) {
	case _ODP_IPPROTO_ICMPv4:
	case _ODP_IPPROTO_ICMPv6:
		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;
	case _ODP_IPPROTO_SCTP:
		prs->input_flags.sctp = 1;
		break;
	default:
		prs->input_flags.l4 = 0;
		prs->l4_offset = ODP_PACKET_OFFSET_INVALID;
		break;
	}
parse_exit:
	return prs->error_flags.all != 0;
}
int packet_parse_common ( packet_parser_t * prs , const uint8_t * ptr , uint32_t frame_len , uint32_t seg_len , odp_pktio_parser_layer_t layer ) { uint32_t offset ; uint16_t ethtype ; const uint8_t * parseptr ; uint8_t ip_proto ; const _odp_ethhdr_t * eth ; uint16_t macaddr0 , macaddr2 , macaddr4 ; const _odp_vlanhdr_t * vlan ; if ( layer == ODP_PKTIO_PARSER_LAYER_NONE ) return 0 ; prs -> input_flags . eth = 1 ; prs -> input_flags . l2 = 1 ; if ( frame_len > _ODP_ETH_LEN_MAX ) prs -> input_flags . jumbo = 1 ; offset = sizeof ( _odp_ethhdr_t ) ; eth = ( const _odp_ethhdr_t * ) ptr ; 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 ( eth -> type ) ; parseptr = ( const uint8_t * ) ( eth + 1 ) ; 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 ; } ethtype = odp_be_to_cpu_16 ( * ( ( const uint16_t * ) ( uintptr_t ) ( parseptr + 6 ) ) ) ; offset += 8 ; parseptr += 8 ; } 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 ) ; } if ( layer == ODP_PKTIO_PARSER_LAYER_L2 ) return prs -> error_flags . all != 0 ; prs -> l3_offset = offset ; prs -> input_flags . l3 = 1 ; switch ( ethtype ) { case _ODP_ETHTYPE_IPV4 : prs -> input_flags . ipv4 = 1 ; ip_proto = parse_ipv4 ( prs , & parseptr , & offset , frame_len ) ; break ; case _ODP_ETHTYPE_IPV6 : prs -> input_flags . ipv6 = 1 ; ip_proto = parse_ipv6 ( prs , & parseptr , & offset , frame_len , seg_len ) ; break ; case _ODP_ETHTYPE_ARP : prs -> input_flags . arp = 1 ; ip_proto = 255 ; break ; default : prs -> input_flags . l3 = 0 ; prs -> l3_offset = ODP_PACKET_OFFSET_INVALID ; ip_proto = 255 ; } if ( layer == ODP_PKTIO_PARSER_LAYER_L3 ) return prs -> error_flags . all != 0 ; prs -> l4_offset = offset ; prs -> input_flags . l4 = 1 ; switch ( ip_proto ) { case _ODP_IPPROTO_ICMPv4 : case _ODP_IPPROTO_ICMPv6 : 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 ; case _ODP_IPPROTO_SCTP : prs -> input_flags . sctp = 1 ; break ; default : prs -> input_flags . l4 = 0 ; prs -> l4_offset = ODP_PACKET_OFFSET_INVALID ; break ; } parse_exit : return prs -> error_flags . all != 0 ; }
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.
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 .
/* We only support Ethernet for now */ /* Assume valid L2 header, no CRC/FCS check in SW */ /* Detect jumbo frames */ /* Handle Ethernet broadcast/multicast addresses */ /* Get Ethertype */ /* Check for SNAP vs. DIX */ /* Parse the VLAN header(s), if present */ /* Set l3_offset+flag only for known ethtypes */ /* Parse Layer 3 headers */ /* Reserved invalid by IANA */ /* Reserved invalid by IANA */ /* Set l4_offset+flag only for known ip_proto */ /* Parse Layer 4 headers */ /* Fall through */