+static inline int
+inline_ipsec_event_esn_overflow(struct rte_security_ctx *ctx, uint64_t md)
+{
+ struct ipsec_sa *sa;
+
+ /* For inline protocol processing, the metadata in the event will
+ * uniquely identify the security session which raised the event.
+ * Application would then need the userdata it had registered with the
+ * security session to process the event.
+ */
+
+ sa = (struct ipsec_sa *)rte_security_get_userdata(ctx, md);
+
+ if (sa == NULL) {
+ /* userdata could not be retrieved */
+ return -1;
+ }
+
+ /* Sequence number over flow. SA need to be re-established */
+ RTE_SET_USED(sa);
+ return 0;
+}
+
+static int
+inline_ipsec_event_callback(uint16_t port_id, enum rte_eth_event_type type,
+ void *param, void *ret_param)
+{
+ uint64_t md;
+ struct rte_eth_event_ipsec_desc *event_desc = NULL;
+ struct rte_security_ctx *ctx = (struct rte_security_ctx *)
+ rte_eth_dev_get_sec_ctx(port_id);
+
+ RTE_SET_USED(param);
+
+ if (type != RTE_ETH_EVENT_IPSEC)
+ return -1;
+
+ event_desc = ret_param;
+ if (event_desc == NULL) {
+ printf("Event descriptor not set\n");
+ return -1;
+ }
+
+ md = event_desc->metadata;
+
+ if (event_desc->subtype == RTE_ETH_EVENT_IPSEC_ESN_OVERFLOW)
+ return inline_ipsec_event_esn_overflow(ctx, md);
+ else if (event_desc->subtype >= RTE_ETH_EVENT_IPSEC_MAX) {
+ printf("Invalid IPsec event reported\n");
+ return -1;
+ }
+
+ return -1;
+}
+
+static uint16_t
+rx_callback(__rte_unused uint16_t port, __rte_unused uint16_t queue,
+ struct rte_mbuf *pkt[], uint16_t nb_pkts,
+ __rte_unused uint16_t max_pkts, void *user_param)
+{
+ uint64_t tm;
+ uint32_t i, k;
+ struct lcore_conf *lc;
+ struct rte_mbuf *mb;
+ struct rte_ether_hdr *eth;
+
+ lc = user_param;
+ k = 0;
+ tm = 0;
+
+ for (i = 0; i != nb_pkts; i++) {
+
+ mb = pkt[i];
+ eth = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
+ if (eth->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
+
+ struct rte_ipv4_hdr *iph;
+
+ iph = (struct rte_ipv4_hdr *)(eth + 1);
+ if (rte_ipv4_frag_pkt_is_fragmented(iph)) {
+
+ mb->l2_len = sizeof(*eth);
+ mb->l3_len = sizeof(*iph);
+ tm = (tm != 0) ? tm : rte_rdtsc();
+ mb = rte_ipv4_frag_reassemble_packet(
+ lc->frag.tbl, &lc->frag.dr,
+ mb, tm, iph);
+
+ if (mb != NULL) {
+ /* fix ip cksum after reassemble. */
+ iph = rte_pktmbuf_mtod_offset(mb,
+ struct rte_ipv4_hdr *,
+ mb->l2_len);
+ iph->hdr_checksum = 0;
+ iph->hdr_checksum = rte_ipv4_cksum(iph);
+ }
+ }
+ } else if (eth->ether_type ==
+ rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) {
+
+ struct rte_ipv6_hdr *iph;
+ struct ipv6_extension_fragment *fh;
+
+ iph = (struct rte_ipv6_hdr *)(eth + 1);
+ fh = rte_ipv6_frag_get_ipv6_fragment_header(iph);
+ if (fh != NULL) {
+ mb->l2_len = sizeof(*eth);
+ mb->l3_len = (uintptr_t)fh - (uintptr_t)iph +
+ sizeof(*fh);
+ tm = (tm != 0) ? tm : rte_rdtsc();
+ mb = rte_ipv6_frag_reassemble_packet(
+ lc->frag.tbl, &lc->frag.dr,
+ mb, tm, iph, fh);
+ if (mb != NULL)
+ /* fix l3_len after reassemble. */
+ mb->l3_len = mb->l3_len - sizeof(*fh);
+ }
+ }
+
+ pkt[k] = mb;
+ k += (mb != NULL);
+ }
+
+ /* some fragments were encountered, drain death row */
+ if (tm != 0)
+ rte_ip_frag_free_death_row(&lc->frag.dr, 0);
+
+ return k;
+}
+
+
+static int
+reassemble_lcore_init(struct lcore_conf *lc, uint32_t cid)
+{
+ int32_t sid;
+ uint32_t i;
+ uint64_t frag_cycles;
+ const struct lcore_rx_queue *rxq;
+ const struct rte_eth_rxtx_callback *cb;
+
+ /* create fragment table */
+ sid = rte_lcore_to_socket_id(cid);
+ frag_cycles = (rte_get_tsc_hz() + MS_PER_S - 1) /
+ MS_PER_S * FRAG_TTL_MS;
+
+ lc->frag.tbl = rte_ip_frag_table_create(frag_tbl_sz,
+ FRAG_TBL_BUCKET_ENTRIES, frag_tbl_sz, frag_cycles, sid);
+ if (lc->frag.tbl == NULL) {
+ printf("%s(%u): failed to create fragment table of size: %u, "
+ "error code: %d\n",
+ __func__, cid, frag_tbl_sz, rte_errno);
+ return -ENOMEM;
+ }
+
+ /* setup reassemble RX callbacks for all queues */
+ for (i = 0; i != lc->nb_rx_queue; i++) {
+
+ rxq = lc->rx_queue_list + i;
+ cb = rte_eth_add_rx_callback(rxq->port_id, rxq->queue_id,
+ rx_callback, lc);
+ if (cb == NULL) {
+ printf("%s(%u): failed to install RX callback for "
+ "portid=%u, queueid=%u, error code: %d\n",
+ __func__, cid,
+ rxq->port_id, rxq->queue_id, rte_errno);
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+static int
+reassemble_init(void)
+{
+ int32_t rc;
+ uint32_t i, lc;
+
+ rc = 0;
+ for (i = 0; i != nb_lcore_params; i++) {
+ lc = lcore_params[i].lcore_id;
+ rc = reassemble_lcore_init(lcore_conf + lc, lc);
+ if (rc != 0)
+ break;
+ }
+
+ return rc;
+}
+