return t->dst;
 }
 
+/* Calculate max payload size given a MTU, or the total overhead if
+ * given MTU is zero
+ */
+static inline __u32 sctp_mtu_payload(const struct sctp_sock *sp,
+                                    __u32 mtu, __u32 extra)
+{
+       __u32 overhead = sizeof(struct sctphdr) + extra;
+
+       if (sp)
+               overhead += sp->pf->af->net_header_len;
+       else
+               overhead += sizeof(struct ipv6hdr);
+
+       if (WARN_ON_ONCE(mtu && mtu <= overhead))
+               mtu = overhead;
+
+       return mtu ? mtu - overhead : overhead;
+}
+
 static inline bool sctp_transport_pmtu_check(struct sctp_transport *t)
 {
        __u32 pmtu = max_t(size_t, SCTP_TRUNC4(dst_mtu(t->dst)),
 
 {
        struct sctp_transport *tp = packet->transport;
        struct sctp_association *asoc = tp->asoc;
+       struct sctp_sock *sp = NULL;
        struct sock *sk;
-       size_t overhead = sizeof(struct ipv6hdr) + sizeof(struct sctphdr);
 
        pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag);
        packet->vtag = vtag;
 
        /* set packet max_size with pathmtu, then calculate overhead */
        packet->max_size = tp->pathmtu;
+
        if (asoc) {
-               struct sctp_sock *sp = sctp_sk(asoc->base.sk);
-               struct sctp_af *af = sp->pf->af;
-
-               overhead = af->net_header_len +
-                          af->ip_options_len(asoc->base.sk);
-               overhead += sizeof(struct sctphdr);
-               packet->overhead = overhead;
-               packet->size = overhead;
-       } else {
-               packet->overhead = overhead;
-               packet->size = overhead;
-               return;
+               sk = asoc->base.sk;
+               sp = sctp_sk(sk);
        }
+       packet->overhead = sctp_mtu_payload(sp, 0, 0);
+       packet->size = packet->overhead;
+
+       if (!asoc)
+               return;
 
        /* update dst or transport pathmtu if in need */
-       sk = asoc->base.sk;
        if (!sctp_transport_dst_check(tp)) {
-               sctp_transport_route(tp, NULL, sctp_sk(sk));
+               sctp_transport_route(tp, NULL, sp);
                if (asoc->param_flags & SPP_PMTUD_ENABLE)
                        sctp_assoc_sync_pmtu(asoc);
        } else if (!sctp_transport_pmtu_check(tp)) {
 
        if (val) {
                int min_len, max_len;
 
-               min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len;
-               min_len -= af->ip_options_len(sk);
-               min_len -= sizeof(struct sctphdr) +
-                          sizeof(struct sctp_data_chunk);
-
+               min_len = sctp_mtu_payload(sp, SCTP_DEFAULT_MINSEGMENT,
+                                          sizeof(struct sctp_data_chunk));
                max_len = SCTP_MAX_CHUNK_LEN - sizeof(struct sctp_data_chunk);
 
                if (val < min_len || val > max_len)