Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[platform/kernel/linux-starfive.git] / net / tls / tls_sw.c
index 2bac576..f1777d6 100644 (file)
@@ -269,9 +269,6 @@ static int tls_do_decryption(struct sock *sk,
        }
        darg->async = false;
 
-       if (ret == -EBADMSG)
-               TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSDECRYPTERROR);
-
        return ret;
 }
 
@@ -1593,14 +1590,18 @@ static int decrypt_skb_update(struct sock *sk, struct sk_buff *skb,
        }
 
        err = decrypt_internal(sk, skb, dest, NULL, darg);
-       if (err < 0)
+       if (err < 0) {
+               if (err == -EBADMSG)
+                       TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSDECRYPTERROR);
                return err;
+       }
        if (darg->async)
                goto decrypt_next;
        /* If opportunistic TLS 1.3 ZC failed retry without ZC */
        if (unlikely(darg->zc && prot->version == TLS_1_3_VERSION &&
                     darg->tail != TLS_RECORD_TYPE_DATA)) {
                darg->zc = false;
+               TLS_INC_STATS(sock_net(sk), LINUX_MIN_TLSDECRYPTRETRY);
                return decrypt_skb_update(sk, skb, dest, darg);
        }
 
@@ -1737,6 +1738,24 @@ out:
        return copied ? : err;
 }
 
+static void
+tls_read_flush_backlog(struct sock *sk, struct tls_prot_info *prot,
+                      size_t len_left, size_t decrypted, ssize_t done,
+                      size_t *flushed_at)
+{
+       size_t max_rec;
+
+       if (len_left <= decrypted)
+               return;
+
+       max_rec = prot->overhead_size - prot->tail_size + TLS_MAX_PAYLOAD_SIZE;
+       if (done - *flushed_at < SZ_128K && tcp_inq(sk) > max_rec)
+               return;
+
+       *flushed_at = done;
+       sk_flush_backlog(sk);
+}
+
 int tls_sw_recvmsg(struct sock *sk,
                   struct msghdr *msg,
                   size_t len,
@@ -1749,6 +1768,7 @@ int tls_sw_recvmsg(struct sock *sk,
        struct sk_psock *psock;
        unsigned char control = 0;
        ssize_t decrypted = 0;
+       size_t flushed_at = 0;
        struct strp_msg *rxm;
        struct tls_msg *tlm;
        struct sk_buff *skb;
@@ -1787,7 +1807,7 @@ int tls_sw_recvmsg(struct sock *sk,
        timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
 
        zc_capable = !bpf_strp_enabled && !is_kvec && !is_peek &&
-                    prot->version != TLS_1_3_VERSION;
+               ctx->zc_capable;
        decrypted = 0;
        while (len && (decrypted + copied < target || ctx->recv_pkt)) {
                struct tls_decrypt_arg darg = {};
@@ -1838,6 +1858,10 @@ int tls_sw_recvmsg(struct sock *sk,
                if (err <= 0)
                        goto recv_end;
 
+               /* periodically flush backlog, and feed strparser */
+               tls_read_flush_backlog(sk, prot, len, to_decrypt,
+                                      decrypted + copied, &flushed_at);
+
                ctx->recv_pkt = NULL;
                __strp_unpause(&ctx->strp);
                __skb_queue_tail(&ctx->rx_list, skb);
@@ -2269,6 +2293,14 @@ void tls_sw_strparser_arm(struct sock *sk, struct tls_context *tls_ctx)
        strp_check_rcv(&rx_ctx->strp);
 }
 
+void tls_update_rx_zc_capable(struct tls_context *tls_ctx)
+{
+       struct tls_sw_context_rx *rx_ctx = tls_sw_ctx_rx(tls_ctx);
+
+       rx_ctx->zc_capable = tls_ctx->rx_no_pad ||
+               tls_ctx->prot_info.version != TLS_1_3_VERSION;
+}
+
 int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
 {
        struct tls_context *tls_ctx = tls_get_ctx(sk);
@@ -2504,12 +2536,10 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
        if (sw_ctx_rx) {
                tfm = crypto_aead_tfm(sw_ctx_rx->aead_recv);
 
-               if (crypto_info->version == TLS_1_3_VERSION)
-                       sw_ctx_rx->async_capable = 0;
-               else
-                       sw_ctx_rx->async_capable =
-                               !!(tfm->__crt_alg->cra_flags &
-                                  CRYPTO_ALG_ASYNC);
+               tls_update_rx_zc_capable(ctx);
+               sw_ctx_rx->async_capable =
+                       crypto_info->version != TLS_1_3_VERSION &&
+                       !!(tfm->__crt_alg->cra_flags & CRYPTO_ALG_ASYNC);
 
                /* Set up strparser */
                memset(&cb, 0, sizeof(cb));