example/ipsec_crypto/odp_ipsec.c
static
pkt_disposition_e do_ipsec_out_classify(odp_packet_t pkt,
					pkt_ctx_t *ctx,
					odp_bool_t *skip)
{
	uint8_t *buf = odp_packet_data(pkt);
	odph_ipv4hdr_t *ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
	uint16_t ip_data_len = ipv4_data_len(ip);
	uint8_t *ip_data = ipv4_data_p(ip);
	ipsec_cache_entry_t *entry;
	odp_crypto_packet_op_param_t params;
	int hdr_len = 0;
	int trl_len = 0;
	odph_ahhdr_t *ah = NULL;
	odph_esphdr_t *esp = NULL;

	/* Default to skip IPsec */
	*skip = TRUE;

	/* Find record */
	entry = find_ipsec_cache_entry_out(odp_be_to_cpu_32(ip->src_addr),
					   odp_be_to_cpu_32(ip->dst_addr),
					   ip->proto);
	if (!entry)
		return PKT_CONTINUE;

	/* Save IPv4 stuff */
	ctx->ipsec.ip_tos = ip->tos;
	ctx->ipsec.ip_frag_offset = odp_be_to_cpu_16(ip->frag_offset);
	ctx->ipsec.ip_ttl = ip->ttl;

	/* Initialize parameters block */
	memset(&params, 0, sizeof(params));
	params.session = entry->state.session;

	if (entry->mode == IPSEC_SA_MODE_TUNNEL) {
		hdr_len += sizeof(odph_ipv4hdr_t);
		ip_data = (uint8_t *)ip;
		ip_data_len += sizeof(odph_ipv4hdr_t);
	}
	/* Compute ah and esp, determine length of headers, move the data */
	if (entry->ah.alg) {
		ah = (odph_ahhdr_t *)(ip_data + hdr_len);
		hdr_len += sizeof(odph_ahhdr_t);
		hdr_len += entry->ah.icv_len;
	}
	if (entry->esp.alg) {
		esp = (odph_esphdr_t *)(ip_data + hdr_len);
		hdr_len += sizeof(odph_esphdr_t);
		hdr_len += entry->esp.iv_len;
	}
	memmove(ip_data + hdr_len, ip_data, ip_data_len);
	ip_data += hdr_len;

	/* update outer header in tunnel mode */
	if (entry->mode == IPSEC_SA_MODE_TUNNEL) {
		/* tunnel addresses */
		ip->src_addr = odp_cpu_to_be_32(entry->tun_src_ip);
		ip->dst_addr = odp_cpu_to_be_32(entry->tun_dst_ip);
	}

	/* For cipher, compute encrypt length, build headers and request */
	if (esp) {
		uint32_t encrypt_len;
		odph_esptrl_t *esp_t;

		encrypt_len = ESP_ENCODE_LEN(ip_data_len +
					     sizeof(*esp_t),
					     entry->esp.block_len);
		trl_len = encrypt_len - ip_data_len;

		esp->spi = odp_cpu_to_be_32(entry->esp.spi);
		memcpy(esp + 1, entry->state.iv, entry->esp.iv_len);

		esp_t = (odph_esptrl_t *)(ip_data + encrypt_len) - 1;
		esp_t->pad_len     = trl_len - sizeof(*esp_t);
		if (entry->mode == IPSEC_SA_MODE_TUNNEL)
			esp_t->next_header = ODPH_IPV4;
		else
			esp_t->next_header = ip->proto;
		ip->proto = ODPH_IPPROTO_ESP;

		params.cipher_range.offset = ip_data - buf;
		params.cipher_range.length = encrypt_len;
	}

	/* For authentication, build header clear mutables and build request */
	if (ah) {
		memset(ah, 0, sizeof(*ah) + entry->ah.icv_len);
		ah->spi = odp_cpu_to_be_32(entry->ah.spi);
		ah->ah_len = 1 + (entry->ah.icv_len / 4);
		if (entry->mode == IPSEC_SA_MODE_TUNNEL && !esp)
			ah->next_header = ODPH_IPV4;
		else
			ah->next_header = ip->proto;
		ip->proto = ODPH_IPPROTO_AH;

		ip->chksum = 0;
		ip->tos = 0;
		ip->frag_offset = 0;
		ip->ttl = 0;

		params.auth_range.offset = ((uint8_t *)ip) - buf;
		params.auth_range.length =
			odp_be_to_cpu_16(ip->tot_len) + (hdr_len + trl_len);
		params.hash_result_offset = ah->icv - buf;
	}

	/* Set IPv4 length before authentication */
	ipv4_adjust_len(ip, hdr_len + trl_len);
	if (!odp_packet_push_tail(pkt, hdr_len + trl_len))
		return PKT_DROP;

	/* Save remaining context */
	ctx->ipsec.hdr_len = hdr_len;
	ctx->ipsec.trl_len = trl_len;
	ctx->ipsec.ah_offset = ah ? ((uint8_t *)ah) - buf : 0;
	ctx->ipsec.esp_offset = esp ? ((uint8_t *)esp) - buf : 0;
	ctx->ipsec.tun_hdr_offset = (entry->mode == IPSEC_SA_MODE_TUNNEL) ?
				       ((uint8_t *)ip - buf) : 0;
	ctx->ipsec.ah_seq = &entry->state.ah_seq;
	ctx->ipsec.esp_seq = &entry->state.esp_seq;
	ctx->ipsec.tun_hdr_id = &entry->state.tun_hdr_id;
	memcpy(&ctx->ipsec.params, &params, sizeof(params));

	*skip = FALSE;

	return PKT_POSTED;
}
/**
 * Packet Processing - Output IPsec packet classification
 *
 * Verify the outbound packet has a match in the IPsec cache,
 * if so issue prepend IPsec headers and prepare parameters
 * for crypto API call.  Post the packet to ATOMIC queue so
 * that sequence numbers can be applied in packet order as
 * the next processing step.
 *
 * @param pkt   Packet to classify
 * @param ctx   Packet process context
 * @param skip  Pointer to return "skip" indication
 *
 * @return PKT_CONTINUE if done else PKT_POSTED
 */
Packet Processing - Output IPsec packet classification
Verify the outbound packet has a match in the IPsec cache,
if so issue prepend IPsec headers and prepare parameters
for crypto API call.  Post the packet to ATOMIC queue so
that sequence numbers can be applied in packet order as
the next processing step.

@param pkt   Packet to classify
@param ctx   Packet process context
@param skip  Pointer to return "skip" indication


Packet Processing - Output IPsec packet classification Verify the outbound packet has a match in the IPsec cache if so issue prepend IPsec headers and prepare parameters for crypto API call . Post the packet to ATOMIC queue so that sequence numbers can be applied in packet order as the next processing step . @param pkt Packet to classify @param ctx Packet process context @param skip Pointer to return " skip " indication
static
pkt_disposition_e do_ipsec_out_classify(odp_packet_t pkt,
					pkt_ctx_t *ctx,
					odp_bool_t *skip)
{
	uint8_t *buf = odp_packet_data(pkt);
	odph_ipv4hdr_t *ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
	uint16_t ip_data_len = ipv4_data_len(ip);
	uint8_t *ip_data = ipv4_data_p(ip);
	ipsec_cache_entry_t *entry;
	odp_crypto_packet_op_param_t params;
	int hdr_len = 0;
	int trl_len = 0;
	odph_ahhdr_t *ah = NULL;
	odph_esphdr_t *esp = NULL;
	*skip = TRUE;
	entry = find_ipsec_cache_entry_out(odp_be_to_cpu_32(ip->src_addr),
					   odp_be_to_cpu_32(ip->dst_addr),
					   ip->proto);
	if (!entry)
		return PKT_CONTINUE;
	ctx->ipsec.ip_tos = ip->tos;
	ctx->ipsec.ip_frag_offset = odp_be_to_cpu_16(ip->frag_offset);
	ctx->ipsec.ip_ttl = ip->ttl;
	memset(&params, 0, sizeof(params));
	params.session = entry->state.session;
	if (entry->mode == IPSEC_SA_MODE_TUNNEL) {
		hdr_len += sizeof(odph_ipv4hdr_t);
		ip_data = (uint8_t *)ip;
		ip_data_len += sizeof(odph_ipv4hdr_t);
	}
	if (entry->ah.alg) {
		ah = (odph_ahhdr_t *)(ip_data + hdr_len);
		hdr_len += sizeof(odph_ahhdr_t);
		hdr_len += entry->ah.icv_len;
	}
	if (entry->esp.alg) {
		esp = (odph_esphdr_t *)(ip_data + hdr_len);
		hdr_len += sizeof(odph_esphdr_t);
		hdr_len += entry->esp.iv_len;
	}
	memmove(ip_data + hdr_len, ip_data, ip_data_len);
	ip_data += hdr_len;
	if (entry->mode == IPSEC_SA_MODE_TUNNEL) {
		ip->src_addr = odp_cpu_to_be_32(entry->tun_src_ip);
		ip->dst_addr = odp_cpu_to_be_32(entry->tun_dst_ip);
	}
	if (esp) {
		uint32_t encrypt_len;
		odph_esptrl_t *esp_t;
		encrypt_len = ESP_ENCODE_LEN(ip_data_len +
					     sizeof(*esp_t),
					     entry->esp.block_len);
		trl_len = encrypt_len - ip_data_len;
		esp->spi = odp_cpu_to_be_32(entry->esp.spi);
		memcpy(esp + 1, entry->state.iv, entry->esp.iv_len);
		esp_t = (odph_esptrl_t *)(ip_data + encrypt_len) - 1;
		esp_t->pad_len     = trl_len - sizeof(*esp_t);
		if (entry->mode == IPSEC_SA_MODE_TUNNEL)
			esp_t->next_header = ODPH_IPV4;
		else
			esp_t->next_header = ip->proto;
		ip->proto = ODPH_IPPROTO_ESP;
		params.cipher_range.offset = ip_data - buf;
		params.cipher_range.length = encrypt_len;
	}
	if (ah) {
		memset(ah, 0, sizeof(*ah) + entry->ah.icv_len);
		ah->spi = odp_cpu_to_be_32(entry->ah.spi);
		ah->ah_len = 1 + (entry->ah.icv_len / 4);
		if (entry->mode == IPSEC_SA_MODE_TUNNEL && !esp)
			ah->next_header = ODPH_IPV4;
		else
			ah->next_header = ip->proto;
		ip->proto = ODPH_IPPROTO_AH;
		ip->chksum = 0;
		ip->tos = 0;
		ip->frag_offset = 0;
		ip->ttl = 0;
		params.auth_range.offset = ((uint8_t *)ip) - buf;
		params.auth_range.length =
			odp_be_to_cpu_16(ip->tot_len) + (hdr_len + trl_len);
		params.hash_result_offset = ah->icv - buf;
	}
	ipv4_adjust_len(ip, hdr_len + trl_len);
	if (!odp_packet_push_tail(pkt, hdr_len + trl_len))
		return PKT_DROP;
	ctx->ipsec.hdr_len = hdr_len;
	ctx->ipsec.trl_len = trl_len;
	ctx->ipsec.ah_offset = ah ? ((uint8_t *)ah) - buf : 0;
	ctx->ipsec.esp_offset = esp ? ((uint8_t *)esp) - buf : 0;
	ctx->ipsec.tun_hdr_offset = (entry->mode == IPSEC_SA_MODE_TUNNEL) ?
				       ((uint8_t *)ip - buf) : 0;
	ctx->ipsec.ah_seq = &entry->state.ah_seq;
	ctx->ipsec.esp_seq = &entry->state.esp_seq;
	ctx->ipsec.tun_hdr_id = &entry->state.tun_hdr_id;
	memcpy(&ctx->ipsec.params, &params, sizeof(params));
	*skip = FALSE;
	return PKT_POSTED;
}
static pkt_disposition_e do_ipsec_out_classify ( odp_packet_t pkt , pkt_ctx_t * ctx , odp_bool_t * skip ) { uint8_t * buf = odp_packet_data ( pkt ) ; odph_ipv4hdr_t * ip = ( odph_ipv4hdr_t * ) odp_packet_l3_ptr ( pkt , NULL ) ; uint16_t ip_data_len = ipv4_data_len ( ip ) ; uint8_t * ip_data = ipv4_data_p ( ip ) ; ipsec_cache_entry_t * entry ; odp_crypto_packet_op_param_t params ; int hdr_len = 0 ; int trl_len = 0 ; odph_ahhdr_t * ah = NULL ; odph_esphdr_t * esp = NULL ; * skip = TRUE ; entry = find_ipsec_cache_entry_out ( odp_be_to_cpu_32 ( ip -> src_addr ) , odp_be_to_cpu_32 ( ip -> dst_addr ) , ip -> proto ) ; if ( ! entry ) return PKT_CONTINUE ; ctx -> ipsec . ip_tos = ip -> tos ; ctx -> ipsec . ip_frag_offset = odp_be_to_cpu_16 ( ip -> frag_offset ) ; ctx -> ipsec . ip_ttl = ip -> ttl ; memset ( & params , 0 , sizeof ( params ) ) ; params . session = entry -> state . session ; if ( entry -> mode == IPSEC_SA_MODE_TUNNEL ) { hdr_len += sizeof ( odph_ipv4hdr_t ) ; ip_data = ( uint8_t * ) ip ; ip_data_len += sizeof ( odph_ipv4hdr_t ) ; } if ( entry -> ah . alg ) { ah = ( odph_ahhdr_t * ) ( ip_data + hdr_len ) ; hdr_len += sizeof ( odph_ahhdr_t ) ; hdr_len += entry -> ah . icv_len ; } if ( entry -> esp . alg ) { esp = ( odph_esphdr_t * ) ( ip_data + hdr_len ) ; hdr_len += sizeof ( odph_esphdr_t ) ; hdr_len += entry -> esp . iv_len ; } memmove ( ip_data + hdr_len , ip_data , ip_data_len ) ; ip_data += hdr_len ; if ( entry -> mode == IPSEC_SA_MODE_TUNNEL ) { ip -> src_addr = odp_cpu_to_be_32 ( entry -> tun_src_ip ) ; ip -> dst_addr = odp_cpu_to_be_32 ( entry -> tun_dst_ip ) ; } if ( esp ) { uint32_t encrypt_len ; odph_esptrl_t * esp_t ; encrypt_len = ESP_ENCODE_LEN ( ip_data_len + sizeof ( * esp_t ) , entry -> esp . block_len ) ; trl_len = encrypt_len - ip_data_len ; esp -> spi = odp_cpu_to_be_32 ( entry -> esp . spi ) ; memcpy ( esp + 1 , entry -> state . iv , entry -> esp . iv_len ) ; esp_t = ( odph_esptrl_t * ) ( ip_data + encrypt_len ) - 1 ; esp_t -> pad_len = trl_len - sizeof ( * esp_t ) ; if ( entry -> mode == IPSEC_SA_MODE_TUNNEL ) esp_t -> next_header = ODPH_IPV4 ; else esp_t -> next_header = ip -> proto ; ip -> proto = ODPH_IPPROTO_ESP ; params . cipher_range . offset = ip_data - buf ; params . cipher_range . length = encrypt_len ; } if ( ah ) { memset ( ah , 0 , sizeof ( * ah ) + entry -> ah . icv_len ) ; ah -> spi = odp_cpu_to_be_32 ( entry -> ah . spi ) ; ah -> ah_len = 1 + ( entry -> ah . icv_len / 4 ) ; if ( entry -> mode == IPSEC_SA_MODE_TUNNEL && ! esp ) ah -> next_header = ODPH_IPV4 ; else ah -> next_header = ip -> proto ; ip -> proto = ODPH_IPPROTO_AH ; ip -> chksum = 0 ; ip -> tos = 0 ; ip -> frag_offset = 0 ; ip -> ttl = 0 ; params . auth_range . offset = ( ( uint8_t * ) ip ) - buf ; params . auth_range . length = odp_be_to_cpu_16 ( ip -> tot_len ) + ( hdr_len + trl_len ) ; params . hash_result_offset = ah -> icv - buf ; } ipv4_adjust_len ( ip , hdr_len + trl_len ) ; if ( ! odp_packet_push_tail ( pkt , hdr_len + trl_len ) ) return PKT_DROP ; ctx -> ipsec . hdr_len = hdr_len ; ctx -> ipsec . trl_len = trl_len ; ctx -> ipsec . ah_offset = ah ? ( ( uint8_t * ) ah ) - buf : 0 ; ctx -> ipsec . esp_offset = esp ? ( ( uint8_t * ) esp ) - buf : 0 ; ctx -> ipsec . tun_hdr_offset = ( entry -> mode == IPSEC_SA_MODE_TUNNEL ) ? ( ( uint8_t * ) ip - buf ) : 0 ; ctx -> ipsec . ah_seq = & entry -> state . ah_seq ; ctx -> ipsec . esp_seq = & entry -> state . esp_seq ; ctx -> ipsec . tun_hdr_id = & entry -> state . tun_hdr_id ; memcpy ( & ctx -> ipsec . params , & params , sizeof ( params ) ) ; * skip = FALSE ; return PKT_POSTED ; }
Packet Processing - Output IPsec packet classification
 Verify the outbound packet has a match in the IPsec cache,
 if so issue prepend IPsec headers and prepare parameters
 for crypto API call.
Packet Processing - Output IPsec packet classification Verify the outbound packet has a match in the IPsec cache if so issue prepend IPsec headers and prepare parameters for crypto API call .
/* Default to skip IPsec */ /* Find record */ /* Save IPv4 stuff */ /* Initialize parameters block */ /* Compute ah and esp, determine length of headers, move the data */ /* update outer header in tunnel mode */ /* tunnel addresses */ /* For cipher, compute encrypt length, build headers and request */ /* For authentication, build header clear mutables and build request */ /* Set IPv4 length before authentication */ /* Save remaining context */