On Fri, Dec 15, 2017 at 04:33:25PM +0530, Anoob Joseph wrote: > Hi Nelio, > > > On 12/15/2017 03:09 PM, Nelio Laranjeiro wrote: > > Hi Anoob, > > > > On Fri, Dec 15, 2017 at 08:43:16AM +0000, Anoob Joseph wrote: > > > Adding support for inline protocol processing > > > > > > In ingress side, application will receive regular IP packets, without > > > any IPsec related info. Application will do a selector check (SP-SA > > > check) by making use of the metadata from the packet. The > > > device-specific metadata in mbuf would aid in determing the security > > > session which processed the packet. > > This means that your devices removes the tunnel header? What happens > > for packets which could not be decrypted correctly, is also the header > > removed? > > Anyway this description is wrong as it is not true for all inline > > devices. > This is particularly for inline protocol processed packets. For inline > crypto, tunnel headers will be present, but for inline protocol tunnel > headers need not be present.
Ok, my bad, I did not see the RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL additional flag. Sorry, > > In addition, in ingress, the same result can be archived by using a mark > > id to identify the flow and thus its security association. > > > > > In egress side, the plain packet would be submitted to the driver. The > > > packet will have optional metadata, which could be used to identify the > > > security session associated with the packet. > > Not true for all inline devices, some only need the next-proto for the > > ESP part. > This is more or less existing behavior for inline crypto. Inline protocol > shares most of it's behavior with inline crypto. > > > > > Signed-off-by: Anoob Joseph <anoob.jos...@caviumnetworks.com> > > > --- > > > v5: > > > * Fixed checkpatch reported warnings > > > > > > v4: > > > * Directly using rte_mbuf.udata64 as the metadata from the packet > > > * Removed usage of rte_security_get_pkt_metadata API > > > > > > v3: > > > * Using (void *)userdata instead of 64 bit metadata in conf > > > * Changes parallel to the change in API > > > > > > v2: > > > * Using get_pkt_metadata API instead of get_session & get_cookie APIs > > > > > > examples/ipsec-secgw/esp.c | 6 +- > > > examples/ipsec-secgw/ipsec-secgw.c | 42 ++++++++++++- > > > examples/ipsec-secgw/ipsec.c | 121 > > > +++++++++++++++++++++++++++++++------ > > > 3 files changed, 147 insertions(+), 22 deletions(-) > > > > > > diff --git a/examples/ipsec-secgw/esp.c b/examples/ipsec-secgw/esp.c > > > index c3efe52..561f873 100644 > > > --- a/examples/ipsec-secgw/esp.c > > > +++ b/examples/ipsec-secgw/esp.c > > > @@ -178,7 +178,8 @@ esp_inbound_post(struct rte_mbuf *m, struct ipsec_sa > > > *sa, > > > RTE_ASSERT(sa != NULL); > > > RTE_ASSERT(cop != NULL); > > > - if (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) { > > > + if ((sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL) || > > > + (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO)) { > > > if (m->ol_flags & PKT_RX_SEC_OFFLOAD) { > > > if (m->ol_flags & PKT_RX_SEC_OFFLOAD_FAILED) > > > cop->status = > > > RTE_CRYPTO_OP_STATUS_ERROR; > > > @@ -474,7 +475,8 @@ esp_outbound_post(struct rte_mbuf *m, > > > RTE_ASSERT(m != NULL); > > > RTE_ASSERT(sa != NULL); > > > - if (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) { > > > + if ((sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL) || > > > + (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO)) { > > > m->ol_flags |= PKT_TX_SEC_OFFLOAD; > > > } else { > > > RTE_ASSERT(cop != NULL); > > > diff --git a/examples/ipsec-secgw/ipsec-secgw.c > > > b/examples/ipsec-secgw/ipsec-secgw.c > > > index c98454a..8254056 100644 > > > --- a/examples/ipsec-secgw/ipsec-secgw.c > > > +++ b/examples/ipsec-secgw/ipsec-secgw.c > > > @@ -265,6 +265,40 @@ prepare_one_packet(struct rte_mbuf *pkt, struct > > > ipsec_traffic *t) > > > RTE_LOG(ERR, IPSEC, "Unsupported packet type\n"); > > > rte_pktmbuf_free(pkt); > > > } > > > + > > > + /* Check if the packet has been processed inline. For inline protocol > > > + * processed packets, the metadata in the mbuf can be used to identify > > > + * the security processing done on the packet. The metadata will be > > > + * used to retrieve the application registered userdata associated > > > + * with the security session. > > > + */ > > > + > > > + if (pkt->ol_flags & PKT_RX_SEC_OFFLOAD) { > > > + struct ipsec_sa *sa; > > > + struct ipsec_mbuf_metadata *priv; > > > + struct rte_security_ctx *ctx = (struct rte_security_ctx *) > > > + rte_eth_dev_get_sec_ctx( > > > + pkt->port); > > > + > > > + /* Retrieve the userdata registered. Here, the userdata > > > + * registered is the SA pointer. > > > + */ > > > + > > > + sa = (struct ipsec_sa *) > > > + rte_security_get_userdata(ctx, pkt->udata64); > > > + > > > + if (sa == NULL) { > > > + /* userdata could not be retrieved */ > > > + return; > > > + } > > > + > > > + /* Save SA as priv member in mbuf. This will be used in the > > > + * IPsec selector(SP-SA) check. > > > + */ > > > + > > > + priv = get_priv(pkt); > > > + priv->sa = sa; > > > + } > > You must verify the function exists on all drivers, those who don't > > support such userdata to be inserted won't implement it. > That check is there in library. It will return NULL and then the function > would exit > > > > What happens on security session where the application don't set such > > information? How the application knows the pointer is set correctly? > Application is the one who sets and gets the pointer. If application doesn't > set it correctly, application will not able to use it. If application > doesn't set this, for inline protocol, the application won't have any > information which it can use to identify the security processing done. > > > > > } > > > static inline void > > > @@ -401,11 +435,17 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, > > > struct traffic_type *ip, > > > ip->pkts[j++] = m; > > > continue; > > > } > > > - if (res & DISCARD || i < lim) { > > > + if (res & DISCARD) { > > > rte_pktmbuf_free(m); > > > continue; > > > } > > > + > > > /* Only check SPI match for processed IPSec packets */ > > > + if (i < lim && ((m->ol_flags & PKT_RX_SEC_OFFLOAD) == 0)) { > > > + rte_pktmbuf_free(m); > > > + continue; > > > + } > > > + > > > sa_idx = ip->res[i] & PROTECT_MASK; > > > if (sa_idx == 0 || !inbound_sa_check(sa, m, sa_idx)) { > > > rte_pktmbuf_free(m); > > > diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c > > > index 70ed227..bd68ec6 100644 > > > --- a/examples/ipsec-secgw/ipsec.c > > > +++ b/examples/ipsec-secgw/ipsec.c > > > @@ -46,6 +46,27 @@ > > > #include "ipsec.h" > > > #include "esp.h" > > > +static inline void > > > +set_ipsec_conf(struct ipsec_sa *sa, struct rte_security_ipsec_xform > > > *ipsec) > > > +{ > > > + if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) { > > > + struct rte_security_ipsec_tunnel_param *tunnel = > > > + &ipsec->tunnel; > > > + if (sa->flags == IP4_TUNNEL) { > > > + tunnel->type = > > > + RTE_SECURITY_IPSEC_TUNNEL_IPV4; > > > + tunnel->ipv4.ttl = IPDEFTTL; > > > + > > > + memcpy((uint8_t *)&tunnel->ipv4.src_ip, > > > + (uint8_t *)&sa->src.ip.ip4, 4); > > > + > > > + memcpy((uint8_t *)&tunnel->ipv4.dst_ip, > > > + (uint8_t *)&sa->dst.ip.ip4, 4); > > > + } > > > + /* TODO support for Transport and IPV6 tunnel */ > > > + } > > > +} > > > + > > > static inline int > > > create_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa) > > > { > > > @@ -95,7 +116,8 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct > > > ipsec_sa *sa) > > > > > > RTE_SECURITY_IPSEC_SA_MODE_TUNNEL : > > > > > > RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT, > > > } }, > > > - .crypto_xform = sa->xforms > > > + .crypto_xform = sa->xforms, > > > + .userdata = NULL, > > > }; > > > @@ -104,23 +126,8 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct > > > ipsec_sa *sa) > > > > > > rte_cryptodev_get_sec_ctx( > > > > > > ipsec_ctx->tbl[cdev_id_qp].id); > > > - if (sess_conf.ipsec.mode == > > > - RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) { > > > - struct rte_security_ipsec_tunnel_param *tunnel = > > > - &sess_conf.ipsec.tunnel; > > > - if (sa->flags == IP4_TUNNEL) { > > > - tunnel->type = > > > - RTE_SECURITY_IPSEC_TUNNEL_IPV4; > > > - tunnel->ipv4.ttl = IPDEFTTL; > > > - > > > - memcpy((uint8_t *)&tunnel->ipv4.src_ip, > > > - (uint8_t *)&sa->src.ip.ip4, 4); > > > - > > > - memcpy((uint8_t *)&tunnel->ipv4.dst_ip, > > > - (uint8_t *)&sa->dst.ip.ip4, 4); > > > - } > > > - /* TODO support for Transport and IPV6 tunnel */ > > > - } > > > + /* Set IPsec parameters in conf */ > > > + set_ipsec_conf(sa, &(sess_conf.ipsec)); > > > sa->sec_session = > > > rte_security_session_create(ctx, > > > &sess_conf, > > > ipsec_ctx->session_pool); > > > @@ -206,6 +213,70 @@ create_session(struct ipsec_ctx *ipsec_ctx, struct > > > ipsec_sa *sa) > > > err.message); > > > return -1; > > > } > > > + } else if (sa->type == > > > + RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL) { > > > + struct rte_security_ctx *ctx = > > > + (struct rte_security_ctx *) > > > + rte_eth_dev_get_sec_ctx(sa->portid); > > > + const struct rte_security_capability *sec_cap; > > > + > > > + if (ctx == NULL) { > > > + RTE_LOG(ERR, IPSEC, > > > + "Ethernet device doesn't have security features > > > registered\n"); > > > + return -1; > > > + } > > > + > > > + /* Set IPsec parameters in conf */ > > > + set_ipsec_conf(sa, &(sess_conf.ipsec)); > > > + > > > + /* Save SA as userdata for the security session. When > > > + * the packet is received, this userdata will be > > > + * retrieved using the metadata from the packet. > > > + * > > > + * This is required only for inbound SAs. > > > + */ > > Again not true for all inline devices. > Should be valid for all inline protocol devices. May be addition of > capability would look better? > > > > > + > > > + if (sa->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) > > > + sess_conf.userdata = (void *) sa; > > > + > > > + sa->sec_session = rte_security_session_create(ctx, > > > + &sess_conf, ipsec_ctx->session_pool); > > > + if (sa->sec_session == NULL) { > > > + RTE_LOG(ERR, IPSEC, > > > + "SEC Session init failed: err: %d\n", ret); > > > + return -1; > > > + } > > > + > > > + sec_cap = rte_security_capabilities_get(ctx); > > > + > > > + if (sec_cap == NULL) { > > > + RTE_LOG(ERR, IPSEC, > > > + "No capabilities registered\n"); > > > + return -1; > > > + } > > > + > > > + /* iterate until ESP tunnel*/ > > > + while (sec_cap->action != > > > + RTE_SECURITY_ACTION_TYPE_NONE) { > > > + > > > + if (sec_cap->action == sa->type && > > > + sec_cap->protocol == > > > + RTE_SECURITY_PROTOCOL_IPSEC && > > > + sec_cap->ipsec.mode == > > > + RTE_SECURITY_IPSEC_SA_MODE_TUNNEL && > > > + sec_cap->ipsec.direction == sa->direction) > > > + break; > > > + sec_cap++; > > > + } > > > + > > > + if (sec_cap->action == RTE_SECURITY_ACTION_TYPE_NONE) { > > > + RTE_LOG(ERR, IPSEC, > > > + "No suitable security capability found\n"); > > > + return -1; > > > + } > > > + > > > + sa->ol_flags = sec_cap->ol_flags; > > > + sa->security_ctx = ctx; > > > } > > > } else { > > > sa->crypto_session = rte_cryptodev_sym_session_create( > > > @@ -323,7 +394,19 @@ ipsec_enqueue(ipsec_xform_fn xform_func, struct > > > ipsec_ctx *ipsec_ctx, > > > } > > > break; > > > case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL: > > > - break; > > > + if ((unlikely(sa->sec_session == NULL)) && > > > + create_session(ipsec_ctx, sa)) { > > > + rte_pktmbuf_free(pkts[i]); > > > + continue; > > > + } > > > + > > > + cqp = &ipsec_ctx->tbl[sa->cdev_id_qp]; > > > + cqp->ol_pkts[cqp->ol_pkts_cnt++] = pkts[i]; > > > + if (sa->ol_flags & RTE_SECURITY_TX_OLOAD_NEED_MDATA) > > > + rte_security_set_pkt_metadata( > > > + sa->security_ctx, > > > + sa->sec_session, pkts[i], NULL); > > > + continue; > > > case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO: > > > priv->cop.type = RTE_CRYPTO_OP_TYPE_SYMMETRIC; > > > priv->cop.status = > > > RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; > > > -- > > > 2.7.4 > > > > > Thanks, > > > Thanks, > Anoob -- Nélio Laranjeiro 6WIND