On Sat, Oct 23, 2021 at 03:08:29PM +0200, Tobias Heider wrote:
> Now that we have removed all the legacy crypto offloading drivers we can
> simplify the crypto framework API by ripping out the async callbacks.
>
> The diff below removes crypto_dispatch() and crypto_done() and replaces
> them with crypto_invoke() which is blocking and only returns after the
> operation has completed or an error occured.
> The former callback functions are invoked directly by the consumer
> (e.g. IPsec and softraid) instead of the crypto driver.
>
> The plan is to clean up the callers in a follow-up diff to remove
> the callback functions alltogether.
>
> ok?
OK bluhm@
> diff --git a/sys/arch/amd64/amd64/aesni.c b/sys/arch/amd64/amd64/aesni.c
> index 12ed40b37a8..86b3b1947ed 100644
> --- a/sys/arch/amd64/amd64/aesni.c
> +++ b/sys/arch/amd64/amd64/aesni.c
> @@ -699,7 +699,6 @@ aesni_process(struct cryptop *crp)
> out:
> smr_read_leave();
> crp->crp_etype = err;
> - crypto_done(crp);
> return (err);
> }
>
> diff --git a/sys/arch/amd64/amd64/via.c b/sys/arch/amd64/amd64/via.c
> index d6f04c3a88c..bb677399e01 100644
> --- a/sys/arch/amd64/amd64/via.c
> +++ b/sys/arch/amd64/amd64/via.c
> @@ -460,7 +460,6 @@ viac3_crypto_process(struct cryptop *crp)
> }
> out:
> crp->crp_etype = err;
> - crypto_done(crp);
> return (err);
> }
>
> diff --git a/sys/arch/arm64/arm64/cryptox.c b/sys/arch/arm64/arm64/cryptox.c
> index 0b4ff183f04..82def0b8702 100644
> --- a/sys/arch/arm64/arm64/cryptox.c
> +++ b/sys/arch/arm64/arm64/cryptox.c
> @@ -486,6 +486,5 @@ cryptox_process(struct cryptop *crp)
> out:
> smr_read_leave();
> crp->crp_etype = err;
> - crypto_done(crp);
> return (err);
> }
> diff --git a/sys/arch/i386/i386/via.c b/sys/arch/i386/i386/via.c
> index 9822bec8519..a627c9cb19c 100644
> --- a/sys/arch/i386/i386/via.c
> +++ b/sys/arch/i386/i386/via.c
> @@ -468,7 +468,6 @@ viac3_crypto_process(struct cryptop *crp)
> }
> out:
> crp->crp_etype = err;
> - crypto_done(crp);
> return (err);
> }
>
> diff --git a/sys/arch/i386/pci/glxsb.c b/sys/arch/i386/pci/glxsb.c
> index 2dca0de55fb..212a343ecc2 100644
> --- a/sys/arch/i386/pci/glxsb.c
> +++ b/sys/arch/i386/pci/glxsb.c
> @@ -825,7 +825,6 @@ glxsb_crypto_process(struct cryptop *crp)
>
> out:
> crp->crp_etype = err;
> - crypto_done(crp);
> splx(s);
> return (err);
> }
> diff --git a/sys/arch/octeon/dev/octcrypto.c b/sys/arch/octeon/dev/octcrypto.c
> index 26449679790..dbfdc2a0ac1 100644
> --- a/sys/arch/octeon/dev/octcrypto.c
> +++ b/sys/arch/octeon/dev/octcrypto.c
> @@ -658,7 +658,6 @@ out:
> smr_read_leave();
>
> crp->crp_etype = error;
> - crypto_done(crp);
> return error;
> }
>
> diff --git a/sys/crypto/crypto.c b/sys/crypto/crypto.c
> index c4bc6064a9b..dc1a34f0c38 100644
> --- a/sys/crypto/crypto.c
> +++ b/sys/crypto/crypto.c
> @@ -376,33 +376,6 @@ crypto_unregister(u_int32_t driverid, int alg)
> return 0;
> }
>
> -/*
> - * Add crypto request to a queue, to be processed by a kernel thread.
> - */
> -void
> -crypto_dispatch(struct cryptop *crp)
> -{
> - int lock = 1, s;
> - u_int32_t hid;
> -
> - s = splvm();
> - hid = (crp->crp_sid >> 32) & 0xffffffff;
> - if (hid < crypto_drivers_num) {
> - if (crypto_drivers[hid].cc_flags & CRYPTOCAP_F_MPSAFE)
> - lock = 0;
> - }
> - splx(s);
> -
> - /* XXXSMP crypto_invoke() is not MP safe */
> - lock = 1;
> -
> - if (lock)
> - KERNEL_LOCK();
> - crypto_invoke(crp);
> - if (lock)
> - KERNEL_UNLOCK();
> -}
> -
> /*
> * Dispatch a crypto request to the appropriate crypto devices.
> */
> @@ -416,7 +389,6 @@ crypto_invoke(struct cryptop *crp)
>
> /* Sanity checks. */
> KASSERT(crp != NULL);
> - KASSERT(crp->crp_callback != NULL);
>
> KERNEL_ASSERT_LOCKED();
>
> @@ -466,7 +438,6 @@ crypto_invoke(struct cryptop *crp)
>
> crp->crp_etype = EAGAIN;
> done:
> - crypto_done(crp);
> splx(s);
> }
>
> @@ -518,14 +489,3 @@ crypto_init(void)
> pool_init(&cryptop_pool, sizeof(struct cryptop), 0, IPL_VM, 0,
> "cryptop", NULL);
> }
> -
> -/*
> - * Invoke the callback on behalf of the driver.
> - */
> -void
> -crypto_done(struct cryptop *crp)
> -{
> - crp->crp_flags |= CRYPTO_F_DONE;
> -
> - crp->crp_callback(crp);
> -}
> diff --git a/sys/crypto/cryptodev.h b/sys/crypto/cryptodev.h
> index 5caa5125a46..7a7b6ed78ca 100644
> --- a/sys/crypto/cryptodev.h
> +++ b/sys/crypto/cryptodev.h
> @@ -169,18 +169,14 @@ struct cryptop {
> #define CRYPTO_F_IMBUF 0x0001 /* Input/output are mbuf chains,
> otherwise contig */
> #define CRYPTO_F_IOV 0x0002 /* Input/output are uio */
> #define CRYPTO_F_MPSAFE 0x0004 /* Do not use kernel lock for callback
> */
> -#define CRYPTO_F_DONE 0x0010 /* request completed */
>
> void *crp_buf; /* Data to be processed */
> - void *crp_opaque; /* Opaque pointer, passed along */
>
> struct cryptodesc *crp_desc; /* List of processing descriptors */
> struct cryptodesc crp_sdesc[2]; /* Static array for small ops */
> int crp_ndesc; /* Amount of descriptors to use */
> int crp_ndescalloc;/* Amount of descriptors allocated */
>
> - void (*crp_callback)(struct cryptop *); /* Callback function */
> -
> caddr_t crp_mac;
> };
>
> @@ -214,14 +210,12 @@ void crypto_init(void);
>
> int crypto_newsession(u_int64_t *, struct cryptoini *, int);
> int crypto_freesession(u_int64_t);
> -void crypto_dispatch(struct cryptop *);
> int crypto_register(u_int32_t, int *,
> int (*)(u_int32_t *, struct cryptoini *), int (*)(u_int64_t),
> int (*)(struct cryptop *));
> int crypto_unregister(u_int32_t, int);
> int32_t crypto_get_driverid(u_int8_t);
> void crypto_invoke(struct cryptop *);
> -void crypto_done(struct cryptop *);
>
> void cuio_copydata(struct uio *, int, int, caddr_t);
> void cuio_copyback(struct uio *, int, int, const void *);
> diff --git a/sys/crypto/cryptosoft.c b/sys/crypto/cryptosoft.c
> index 3fc7e3ca8f0..fe60a1b5da2 100644
> --- a/sys/crypto/cryptosoft.c
> +++ b/sys/crypto/cryptosoft.c
> @@ -1129,7 +1129,6 @@ swcr_process(struct cryptop *crp)
> }
>
> done:
> - crypto_done(crp);
> return 0;
> }
>
> diff --git a/sys/dev/softraid_crypto.c b/sys/dev/softraid_crypto.c
> index 867e9f61df5..1bded7b9ffb 100644
> --- a/sys/dev/softraid_crypto.c
> +++ b/sys/dev/softraid_crypto.c
> @@ -87,13 +87,13 @@ int
> sr_crypto_meta_opt_handler_internal(struct sr_discipline *,
> struct sr_crypto *, struct sr_meta_opt_hdr *);
> int sr_crypto_meta_opt_handler(struct sr_discipline *,
> struct sr_meta_opt_hdr *);
> -void sr_crypto_write(struct cryptop *);
> +void sr_crypto_write(struct sr_crypto_wu *);
> int sr_crypto_rw(struct sr_workunit *);
> int sr_crypto_dev_rw(struct sr_workunit *, struct sr_crypto_wu *);
> void sr_crypto_done_internal(struct sr_workunit *,
> struct sr_crypto *);
> void sr_crypto_done(struct sr_workunit *);
> -void sr_crypto_read(struct cryptop *);
> +void sr_crypto_read(struct sr_crypto_wu *);
> void sr_crypto_calculate_check_hmac_sha1(u_int8_t *, int,
> u_int8_t *, int, u_char *);
> void sr_crypto_hotplug(struct sr_discipline *, struct disk *, int);
> @@ -322,7 +322,6 @@ sr_crypto_prepare(struct sr_workunit *wu, struct
> sr_crypto *mdd_crypto,
> keyndx = blkno >> SR_CRYPTO_KEY_BLKSHIFT;
> crwu->cr_crp->crp_sid = mdd_crypto->scr_sid[keyndx];
>
> - crwu->cr_crp->crp_opaque = crwu;
> crwu->cr_crp->crp_ilen = xs->datalen;
> crwu->cr_crp->crp_alloctype = M_DEVBUF;
> crwu->cr_crp->crp_flags = CRYPTO_F_IOV;
> @@ -1168,8 +1167,10 @@ sr_crypto_rw(struct sr_workunit *wu)
> if (wu->swu_xs->flags & SCSI_DATA_OUT) {
> mdd_crypto = &wu->swu_dis->mds.mdd_crypto;
> crwu = sr_crypto_prepare(wu, mdd_crypto, 1);
> - crwu->cr_crp->crp_callback = sr_crypto_write;
> - crypto_dispatch(crwu->cr_crp);
> + KERNEL_LOCK();
> + crypto_invoke(crwu->cr_crp);
> + KERNEL_UNLOCK();
> + sr_crypto_write(crwu);
> rv = crwu->cr_crp->crp_etype;
> } else
> rv = sr_crypto_dev_rw(wu, NULL);
> @@ -1178,16 +1179,15 @@ sr_crypto_rw(struct sr_workunit *wu)
> }
>
> void
> -sr_crypto_write(struct cryptop *crp)
> +sr_crypto_write(struct sr_crypto_wu *crwu)
> {
> - struct sr_crypto_wu *crwu = crp->crp_opaque;
> struct sr_workunit *wu = &crwu->cr_wu;
> int s;
>
> DNPRINTF(SR_D_INTR, "%s: sr_crypto_write: wu %p xs: %p\n",
> DEVNAME(wu->swu_dis->sd_sc), wu, wu->swu_xs);
>
> - if (crp->crp_etype) {
> + if (crwu->cr_crp->crp_etype) {
> /* fail io */
> wu->swu_xs->error = XS_DRIVER_STUFFUP;
> s = splbio();
> @@ -1246,10 +1246,12 @@ sr_crypto_done_internal(struct sr_workunit *wu,
> struct sr_crypto *mdd_crypto)
> /* If this was a successful read, initiate decryption of the data. */
> if (ISSET(xs->flags, SCSI_DATA_IN) && xs->error == XS_NOERROR) {
> crwu = sr_crypto_prepare(wu, mdd_crypto, 0);
> - crwu->cr_crp->crp_callback = sr_crypto_read;
> - DNPRINTF(SR_D_INTR, "%s: sr_crypto_done: crypto_dispatch %p\n",
> + DNPRINTF(SR_D_INTR, "%s: sr_crypto_done: crypto_invoke %p\n",
> DEVNAME(wu->swu_dis->sd_sc), crwu->cr_crp);
> - crypto_dispatch(crwu->cr_crp);
> + KERNEL_LOCK();
> + crypto_invoke(crwu->cr_crp);
> + KERNEL_UNLOCK();
> + sr_crypto_read(crwu);
> return;
> }
>
> @@ -1266,16 +1268,15 @@ sr_crypto_done(struct sr_workunit *wu)
> }
>
> void
> -sr_crypto_read(struct cryptop *crp)
> +sr_crypto_read(struct sr_crypto_wu *crwu)
> {
> - struct sr_crypto_wu *crwu = crp->crp_opaque;
> struct sr_workunit *wu = &crwu->cr_wu;
> int s;
>
> DNPRINTF(SR_D_INTR, "%s: sr_crypto_read: wu %p xs: %p\n",
> DEVNAME(wu->swu_dis->sd_sc), wu, wu->swu_xs);
>
> - if (crp->crp_etype)
> + if (crwu->cr_crp->crp_etype)
> wu->swu_xs->error = XS_DRIVER_STUFFUP;
>
> s = splbio();
> diff --git a/sys/dev/softraid_raid1c.c b/sys/dev/softraid_raid1c.c
> index d23323bc5e4..77b2f1142b2 100644
> --- a/sys/dev/softraid_raid1c.c
> +++ b/sys/dev/softraid_raid1c.c
> @@ -58,7 +58,7 @@ void sr_raid1c_free_resources(struct sr_discipline
> *sd);
> int sr_raid1c_ioctl(struct sr_discipline *sd, struct bioc_discipline *bd);
> int sr_raid1c_meta_opt_handler(struct sr_discipline *,
> struct sr_meta_opt_hdr *);
> -void sr_raid1c_write(struct cryptop *);
> +void sr_raid1c_write(struct sr_crypto_wu *);
> int sr_raid1c_rw(struct sr_workunit *);
> int sr_raid1c_dev_rw(struct sr_workunit *, struct sr_crypto_wu *);
> void sr_raid1c_done(struct sr_workunit *wu);
> @@ -312,16 +312,15 @@ bad:
> }
>
> void
> -sr_raid1c_write(struct cryptop *crp)
> +sr_raid1c_write(struct sr_crypto_wu *crwu)
> {
> - struct sr_crypto_wu *crwu = crp->crp_opaque;
> struct sr_workunit *wu = &crwu->cr_wu;
> int s;
>
> DNPRINTF(SR_D_INTR, "%s: sr_raid1c_write: wu %p xs: %p\n",
> DEVNAME(wu->swu_dis->sd_sc), wu, wu->swu_xs);
>
> - if (crp->crp_etype) {
> + if (crwu->cr_crp->crp_etype) {
> /* fail io */
> wu->swu_xs->error = XS_DRIVER_STUFFUP;
> s = splbio();
> @@ -358,8 +357,10 @@ sr_raid1c_rw(struct sr_workunit *wu)
> !ISSET(wu->swu_flags, SR_WUF_REBUILD)) {
> mdd_raid1c = &wu->swu_dis->mds.mdd_raid1c;
> crwu = sr_crypto_prepare(wu, &mdd_raid1c->sr1c_crypto, 1);
> - crwu->cr_crp->crp_callback = sr_raid1c_write;
> - crypto_dispatch(crwu->cr_crp);
> + KERNEL_LOCK();
> + crypto_invoke(crwu->cr_crp);
> + KERNEL_UNLOCK();
> + sr_raid1c_write(crwu);
> rv = crwu->cr_crp->crp_etype;
> } else
> rv = sr_raid1c_dev_rw(wu, NULL);
> diff --git a/sys/netinet/ip_ah.c b/sys/netinet/ip_ah.c
> index a10c2a7b7ba..7ce83a9730e 100644
> --- a/sys/netinet/ip_ah.c
> +++ b/sys/netinet/ip_ah.c
> @@ -531,7 +531,7 @@ ah_input(struct mbuf *m, struct tdb *tdb, int skip, int
> protoff)
> struct tdb_crypto *tc = NULL;
> u_int32_t btsx, esn;
> u_int8_t hl;
> - int error, rplen;
> + int error, rplen, clen;
> u_int64_t ibytes;
> #ifdef ENCDEBUG
> char buf[INET6_ADDRSTRLEN];
> @@ -686,9 +686,7 @@ ah_input(struct mbuf *m, struct tdb *tdb, int skip, int
> protoff)
> crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */
> crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_MPSAFE;
> crp->crp_buf = (caddr_t)m;
> - crp->crp_callback = ipsec_input_cb;
> crp->crp_sid = tdb->tdb_cryptoid;
> - crp->crp_opaque = (caddr_t)tc;
>
> /* These are passed as-is to the callback. */
> tc->tc_skip = skip;
> @@ -699,7 +697,36 @@ ah_input(struct mbuf *m, struct tdb *tdb, int skip, int
> protoff)
> memcpy(&tc->tc_dst, &tdb->tdb_dst, sizeof(union sockaddr_union));
> tc->tc_rpl = tdb->tdb_rpl;
>
> - crypto_dispatch(crp);
> + KERNEL_LOCK();
> + crypto_invoke(crp);
> + while (crp->crp_etype == EAGAIN) {
> + /* Reset the session ID */
> + if (tdb->tdb_cryptoid != 0)
> + tdb->tdb_cryptoid = crp->crp_sid;
> + crypto_invoke(crp);
> + }
> + KERNEL_UNLOCK();
> + if (crp->crp_etype) {
> + DPRINTF("crypto error %d", crp->crp_etype);
> + ipsecstat_inc(ipsec_noxform);
> + ipsecstat_inc(ipsec_idrops);
> + tdb->tdb_idrops++;
> + error = crp->crp_etype;
> + goto drop;
> + }
> +
> + /* Length of data after processing */
> + clen = crp->crp_olen;
> +
> + /* Release the crypto descriptors */
> + crypto_freereq(crp);
> +
> + error = ah_input_cb(tdb, tc, m, clen);
> + if (error) {
> + ipsecstat_inc(ipsec_idrops);
> + tdb->tdb_idrops++;
> + }
> +
> return 0;
>
> drop:
> @@ -893,7 +920,7 @@ ah_output(struct mbuf *m, struct tdb *tdb, int skip, int
> protoff)
> struct cryptop *crp = NULL;
> u_int64_t replay64;
> u_int16_t iplen;
> - int error, rplen, roff;
> + int error, rplen, roff, ilen, olen;
> u_int8_t prot;
> struct ah *ah;
> #if NBPFILTER > 0
> @@ -1133,9 +1160,7 @@ ah_output(struct mbuf *m, struct tdb *tdb, int skip,
> int protoff)
> crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */
> crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_MPSAFE;
> crp->crp_buf = (caddr_t)m;
> - crp->crp_callback = ipsec_output_cb;
> crp->crp_sid = tdb->tdb_cryptoid;
> - crp->crp_opaque = (caddr_t)tc;
>
> /* These are passed as-is to the callback. */
> tc->tc_skip = skip;
> @@ -1145,7 +1170,36 @@ ah_output(struct mbuf *m, struct tdb *tdb, int skip,
> int protoff)
> tc->tc_rdomain = tdb->tdb_rdomain;
> memcpy(&tc->tc_dst, &tdb->tdb_dst, sizeof(union sockaddr_union));
>
> - crypto_dispatch(crp);
> + KERNEL_LOCK();
> + crypto_invoke(crp);
> + while (crp->crp_etype == EAGAIN) {
> + /* Reset the session ID */
> + if (tdb->tdb_cryptoid != 0)
> + tdb->tdb_cryptoid = crp->crp_sid;
> + crypto_invoke(crp);
> + }
> + KERNEL_UNLOCK();
> + if (crp->crp_etype) {
> + DPRINTF("crypto error %d", crp->crp_etype);
> + ipsecstat_inc(ipsec_noxform);
> + ipsecstat_inc(ipsec_odrops);
> + tdb->tdb_odrops++;
> + error = crp->crp_etype;
> + goto drop;
> + }
> +
> + ilen = crp->crp_ilen;
> + olen = crp->crp_olen;
> +
> + /* Release the crypto descriptors */
> + crypto_freereq(crp);
> +
> + error = ah_output_cb(tdb, tc, m, ilen, olen);
> + if (error) {
> + ipsecstat_inc(ipsec_odrops);
> + tdb->tdb_odrops++;
> + }
> +
> return 0;
>
> drop:
> diff --git a/sys/netinet/ip_esp.c b/sys/netinet/ip_esp.c
> index 1b96a2b942d..1e4cfaafdcf 100644
> --- a/sys/netinet/ip_esp.c
> +++ b/sys/netinet/ip_esp.c
> @@ -347,7 +347,7 @@ esp_input(struct mbuf *m, struct tdb *tdb, int skip, int
> protoff)
> struct cryptodesc *crde = NULL, *crda = NULL;
> struct cryptop *crp = NULL;
> struct tdb_crypto *tc = NULL;
> - int plen, alen, hlen, error;
> + int plen, alen, hlen, error, clen;
> u_int32_t btsx, esn;
> #ifdef ENCDEBUG
> char buf[INET6_ADDRSTRLEN];
> @@ -498,9 +498,7 @@ esp_input(struct mbuf *m, struct tdb *tdb, int skip, int
> protoff)
> crp->crp_ilen = m->m_pkthdr.len; /* Total input length */
> crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_MPSAFE;
> crp->crp_buf = (caddr_t)m;
> - crp->crp_callback = ipsec_input_cb;
> crp->crp_sid = tdb->tdb_cryptoid;
> - crp->crp_opaque = (caddr_t)tc;
>
> /* These are passed as-is to the callback */
> tc->tc_skip = skip;
> @@ -526,7 +524,35 @@ esp_input(struct mbuf *m, struct tdb *tdb, int skip, int
> protoff)
> crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen);
> }
>
> - crypto_dispatch(crp);
> + KERNEL_LOCK();
> + crypto_invoke(crp);
> + while (crp->crp_etype == EAGAIN) {
> + /* Reset the session ID */
> + if (tdb->tdb_cryptoid != 0)
> + tdb->tdb_cryptoid = crp->crp_sid;
> + crypto_invoke(crp);
> + }
> + KERNEL_UNLOCK();
> + if (crp->crp_etype) {
> + DPRINTF("crypto error %d", crp->crp_etype);
> + ipsecstat_inc(ipsec_noxform);
> + ipsecstat_inc(ipsec_idrops);
> + tdb->tdb_idrops++;
> + error = crp->crp_etype;
> + goto drop;
> + }
> +
> + clen = crp->crp_olen;
> +
> + /* Release the crypto descriptors */
> + crypto_freereq(crp);
> +
> + error = esp_input_cb(tdb, tc, m, clen);
> + if (error) {
> + ipsecstat_inc(ipsec_idrops);
> + tdb->tdb_idrops++;
> + }
> +
> return 0;
>
> drop:
> @@ -742,7 +768,7 @@ esp_output(struct mbuf *m, struct tdb *tdb, int skip, int
> protoff)
> {
> const struct enc_xform *espx = tdb->tdb_encalgxform;
> const struct auth_hash *esph = tdb->tdb_authalgxform;
> - int ilen, hlen, rlen, padding, blks, alen, roff, error;
> + int ilen, olen, hlen, rlen, padding, blks, alen, roff, error;
> u_int64_t replay64;
> u_int32_t replay;
> struct mbuf *mi, *mo = (struct mbuf *) NULL;
> @@ -980,8 +1006,6 @@ esp_output(struct mbuf *m, struct tdb *tdb, int skip,
> int protoff)
> crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */
> crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_MPSAFE;
> crp->crp_buf = (caddr_t)m;
> - crp->crp_callback = ipsec_output_cb;
> - crp->crp_opaque = (caddr_t)tc;
> crp->crp_sid = tdb->tdb_cryptoid;
>
> if (esph) {
> @@ -1010,7 +1034,36 @@ esp_output(struct mbuf *m, struct tdb *tdb, int skip,
> int protoff)
> crda->crd_len = m->m_pkthdr.len - (skip + alen);
> }
>
> - crypto_dispatch(crp);
> + KERNEL_LOCK();
> + crypto_invoke(crp);
> + while (crp->crp_etype == EAGAIN) {
> + /* Reset the session ID */
> + if (tdb->tdb_cryptoid != 0)
> + tdb->tdb_cryptoid = crp->crp_sid;
> + crypto_invoke(crp);
> + }
> + KERNEL_UNLOCK();
> + if (crp->crp_etype) {
> + DPRINTF("crypto error %d", crp->crp_etype);
> + ipsecstat_inc(ipsec_noxform);
> + ipsecstat_inc(ipsec_odrops);
> + tdb->tdb_odrops++;
> + error = crp->crp_etype;
> + goto drop;
> + }
> +
> + ilen = crp->crp_ilen;
> + olen = crp->crp_olen;
> +
> + /* Release the crypto descriptors */
> + crypto_freereq(crp);
> +
> + error = esp_output_cb(tdb, tc, m, ilen, olen);
> + if (error) {
> + ipsecstat_inc(ipsec_odrops);
> + tdb->tdb_odrops++;
> + }
> +
> return 0;
>
> drop:
> diff --git a/sys/netinet/ip_ipcomp.c b/sys/netinet/ip_ipcomp.c
> index 902955c9d6e..4837429fee6 100644
> --- a/sys/netinet/ip_ipcomp.c
> +++ b/sys/netinet/ip_ipcomp.c
> @@ -135,7 +135,7 @@ ipcomp_input(struct mbuf *m, struct tdb *tdb, int skip,
> int protoff)
> {
> const struct comp_algo *ipcompx = tdb->tdb_compalgxform;
> struct tdb_crypto *tc;
> - int hlen;
> + int hlen, error, clen;
>
> struct cryptodesc *crdc = NULL;
> struct cryptop *crp;
> @@ -172,9 +172,7 @@ ipcomp_input(struct mbuf *m, struct tdb *tdb, int skip,
> int protoff)
> crp->crp_ilen = m->m_pkthdr.len - (skip + hlen);
> crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_MPSAFE;
> crp->crp_buf = (caddr_t)m;
> - crp->crp_callback = ipsec_input_cb;
> crp->crp_sid = tdb->tdb_cryptoid;
> - crp->crp_opaque = (caddr_t)tc;
>
> /* These are passed as-is to the callback */
> tc->tc_skip = skip;
> @@ -184,7 +182,37 @@ ipcomp_input(struct mbuf *m, struct tdb *tdb, int skip,
> int protoff)
> tc->tc_rdomain = tdb->tdb_rdomain;
> tc->tc_dst = tdb->tdb_dst;
>
> - crypto_dispatch(crp);
> + KERNEL_LOCK();
> + crypto_invoke(crp);
> + while (crp->crp_etype == EAGAIN) {
> + /* Reset the session ID */
> + if (tdb->tdb_cryptoid != 0)
> + tdb->tdb_cryptoid = crp->crp_sid;
> + crypto_invoke(crp);
> + }
> + KERNEL_UNLOCK();
> + if (crp->crp_etype) {
> + DPRINTF("crypto error %d", crp->crp_etype);
> + ipsecstat_inc(ipsec_noxform);
> + ipsecstat_inc(ipsec_idrops);
> + tdb->tdb_idrops++;
> + free(tc, M_XDATA, 0);
> + m_freem(m);
> + crypto_freereq(crp);
> + return crp->crp_etype;
> + }
> +
> + clen = crp->crp_olen;
> +
> + /* Release the crypto descriptors */
> + crypto_freereq(crp);
> +
> + error = ipcomp_input_cb(tdb, tc, m, clen);
> + if (error) {
> + ipsecstat_inc(ipsec_idrops);
> + tdb->tdb_idrops++;
> + }
> +
> return 0;
> }
>
> @@ -319,7 +347,7 @@ int
> ipcomp_output(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
> {
> const struct comp_algo *ipcompx = tdb->tdb_compalgxform;
> - int error, hlen;
> + int error, hlen, ilen, olen;
> struct cryptodesc *crdc = NULL;
> struct cryptop *crp = NULL;
> struct tdb_crypto *tc;
> @@ -474,11 +502,40 @@ ipcomp_output(struct mbuf *m, struct tdb *tdb, int
> skip, int protoff)
> crp->crp_ilen = m->m_pkthdr.len; /* Total input length */
> crp->crp_flags = CRYPTO_F_IMBUF | CRYPTO_F_MPSAFE;
> crp->crp_buf = (caddr_t)m;
> - crp->crp_callback = ipsec_output_cb;
> - crp->crp_opaque = (caddr_t)tc;
> crp->crp_sid = tdb->tdb_cryptoid;
>
> - crypto_dispatch(crp);
> + KERNEL_LOCK();
> + crypto_invoke(crp);
> + while (crp->crp_etype == EAGAIN) {
> + /* Reset the session ID */
> + if (tdb->tdb_cryptoid != 0)
> + tdb->tdb_cryptoid = crp->crp_sid;
> + crypto_invoke(crp);
> + }
> + KERNEL_UNLOCK();
> + if (crp->crp_etype) {
> + DPRINTF("crypto error %d", crp->crp_etype);
> + ipsecstat_inc(ipsec_noxform);
> + ipsecstat_inc(ipsec_odrops);
> + free(tc, M_XDATA, 0);
> + tdb->tdb_odrops++;
> + m_freem(m);
> + crypto_freereq(crp);
> + return crp->crp_etype;
> + }
> +
> + ilen = crp->crp_ilen;
> + olen = crp->crp_olen;
> +
> + /* Release the crypto descriptors */
> + crypto_freereq(crp);
> +
> + error = ipcomp_output_cb(tdb, tc, m, crp->crp_ilen, crp->crp_olen);
> + if (error) {
> + ipsecstat_inc(ipsec_odrops);
> + tdb->tdb_odrops++;
> + }
> +
> return 0;
>
> drop:
> diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h
> index 9bb39465b57..63aea100e5d 100644
> --- a/sys/netinet/ip_ipsp.h
> +++ b/sys/netinet/ip_ipsp.h
> @@ -648,8 +648,6 @@ void ipsp_init(void);
> void ipsec_init(void);
> int ipsec_sysctl(int *, u_int, void *, size_t *, void *, size_t);
> int ipsec_common_input(struct mbuf *, int, int, int, int, int);
> -void ipsec_input_cb(struct cryptop *);
> -void ipsec_output_cb(struct cryptop *);
> int ipsec_common_input_cb(struct mbuf *, struct tdb *, int, int);
> int ipsec_delete_policy(struct ipsec_policy *);
> ssize_t ipsec_hdrsz(struct tdb *);
> diff --git a/sys/netinet/ipsec_input.c b/sys/netinet/ipsec_input.c
> index 2a9a378bde7..6fda85f24b7 100644
> --- a/sys/netinet/ipsec_input.c
> +++ b/sys/netinet/ipsec_input.c
> @@ -366,78 +366,6 @@ ipsec_common_input(struct mbuf *m, int skip, int
> protoff, int af, int sproto,
> return error;
> }
>
> -void
> -ipsec_input_cb(struct cryptop *crp)
> -{
> - struct tdb_crypto *tc = (struct tdb_crypto *) crp->crp_opaque;
> - struct mbuf *m = (struct mbuf *) crp->crp_buf;
> - struct tdb *tdb = NULL;
> - int clen, error;
> -
> - NET_ASSERT_LOCKED();
> -
> - if (m == NULL) {
> - DPRINTF("bogus returned buffer from crypto");
> - ipsecstat_inc(ipsec_crypto);
> - goto drop;
> - }
> -
> - tdb = gettdb(tc->tc_rdomain, tc->tc_spi, &tc->tc_dst, tc->tc_proto);
> - if (tdb == NULL) {
> - DPRINTF("TDB is expired while in crypto");
> - ipsecstat_inc(ipsec_notdb);
> - goto drop;
> - }
> -
> - /* Check for crypto errors */
> - if (crp->crp_etype) {
> - if (crp->crp_etype == EAGAIN) {
> - /* Reset the session ID */
> - if (tdb->tdb_cryptoid != 0)
> - tdb->tdb_cryptoid = crp->crp_sid;
> - crypto_dispatch(crp);
> - return;
> - }
> - DPRINTF("crypto error %d", crp->crp_etype);
> - ipsecstat_inc(ipsec_noxform);
> - goto drop;
> - }
> -
> - /* Length of data after processing */
> - clen = crp->crp_olen;
> -
> - /* Release the crypto descriptors */
> - crypto_freereq(crp);
> -
> - switch (tdb->tdb_sproto) {
> - case IPPROTO_ESP:
> - error = esp_input_cb(tdb, tc, m, clen);
> - break;
> - case IPPROTO_AH:
> - error = ah_input_cb(tdb, tc, m, clen);
> - break;
> - case IPPROTO_IPCOMP:
> - error = ipcomp_input_cb(tdb, tc, m, clen);
> - break;
> - default:
> - panic("%s: unknown/unsupported security protocol %d",
> - __func__, tdb->tdb_sproto);
> - }
> - if (error) {
> - ipsecstat_inc(ipsec_idrops);
> - tdb->tdb_idrops++;
> - }
> - return;
> -
> - drop:
> - m_freem(m);
> - free(tc, M_XDATA, 0);
> - crypto_freereq(crp);
> - ipsecstat_inc(ipsec_idrops);
> - if (tdb != NULL)
> - tdb->tdb_idrops++;
> -}
> -
> /*
> * IPsec input callback, called by the transform callback. Takes care of
> * filtering and other sanity checks on the processed packet.
> diff --git a/sys/netinet/ipsec_output.c b/sys/netinet/ipsec_output.c
> index ed11171b543..9962e521dad 100644
> --- a/sys/netinet/ipsec_output.c
> +++ b/sys/netinet/ipsec_output.c
> @@ -377,81 +377,6 @@ ipsp_process_packet(struct mbuf *m, struct tdb *tdb, int
> af, int tunalready)
> return error;
> }
>
> -/*
> - * IPsec output callback, called directly by the crypto driver.
> - */
> -void
> -ipsec_output_cb(struct cryptop *crp)
> -{
> - struct tdb_crypto *tc = (struct tdb_crypto *) crp->crp_opaque;
> - struct mbuf *m = (struct mbuf *) crp->crp_buf;
> - struct tdb *tdb = NULL;
> - int error, ilen, olen;
> -
> - NET_ASSERT_LOCKED();
> -
> - if (m == NULL) {
> - DPRINTF("bogus returned buffer from crypto");
> - ipsecstat_inc(ipsec_crypto);
> - goto drop;
> - }
> -
> - tdb = gettdb(tc->tc_rdomain, tc->tc_spi, &tc->tc_dst, tc->tc_proto);
> - if (tdb == NULL) {
> - DPRINTF("TDB is expired while in crypto");
> - ipsecstat_inc(ipsec_notdb);
> - goto drop;
> - }
> -
> - /* Check for crypto errors. */
> - if (crp->crp_etype) {
> - if (crp->crp_etype == EAGAIN) {
> - /* Reset the session ID */
> - if (tdb->tdb_cryptoid != 0)
> - tdb->tdb_cryptoid = crp->crp_sid;
> - crypto_dispatch(crp);
> - return;
> - }
> - DPRINTF("crypto error %d", crp->crp_etype);
> - ipsecstat_inc(ipsec_noxform);
> - goto drop;
> - }
> -
> - olen = crp->crp_olen;
> - ilen = crp->crp_ilen;
> -
> - /* Release crypto descriptors. */
> - crypto_freereq(crp);
> -
> - switch (tdb->tdb_sproto) {
> - case IPPROTO_ESP:
> - error = esp_output_cb(tdb, tc, m, ilen, olen);
> - break;
> - case IPPROTO_AH:
> - error = ah_output_cb(tdb, tc, m, ilen, olen);
> - break;
> - case IPPROTO_IPCOMP:
> - error = ipcomp_output_cb(tdb, tc, m, ilen, olen);
> - break;
> - default:
> - panic("%s: unhandled security protocol %d",
> - __func__, tdb->tdb_sproto);
> - }
> - if (error) {
> - ipsecstat_inc(ipsec_odrops);
> - tdb->tdb_odrops++;
> - }
> - return;
> -
> - drop:
> - m_freem(m);
> - free(tc, M_XDATA, 0);
> - crypto_freereq(crp);
> - ipsecstat_inc(ipsec_odrops);
> - if (tdb != NULL)
> - tdb->tdb_odrops++;
> -}
> -
> /*
> * Called by the IPsec output transform callbacks, to transmit the packet
> * or do further processing, as necessary.