Lines Matching +full:timeout +full:- +full:ulp +full:- +full:ms
1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
77 * +--- TAILQ(struct ip6q, packets) *q6; tailq entries holding
81 * +--- TAILQ(struct ip6asfrag, ip6q_frags) *af6; tailq entries of IPv6
90 #define IP6REASS_HMASK (IP6REASS_NHASH - 1)
120 /* Maximum and current packets in per-VNET reassembly queue. */
126 /* Maximum per-VNET reassembly timeout (milliseconds) */
130 /* Maximum per-VNET reassembly queues per bucket and fragments per packet. */
136 /* Per-VNET reassembly queue buckets. */
156 * multiplier to reach a 100-item limit.)
157 * The 100-item limit was chosen as brief testing seems to show that
189 "a value of -1 means no limit");
198 if (error != 0 || !req->newptr) in sysctl_ip6_maxfragpackets()
209 "a value of -1 means no limit");
213 "Per-VNET number of IPv6 fragments across all reassembly queues.");
222 frag6_milli_to_callout_ticks(int ms) in frag6_milli_to_callout_ticks() argument
224 return (ms / IP6_CALLOUT_INTERVAL_MS); in frag6_milli_to_callout_ticks()
228 frag6_callout_ticks_to_milli(int ms) in frag6_callout_ticks_to_milli() argument
230 return (ms * IP6_CALLOUT_INTERVAL_MS); in frag6_callout_ticks_to_milli()
233 _Static_assert(sizeof(((struct ip6q *)NULL)->ip6q_ttl) >= 2,
243 if (error != 0 || !req->newptr) in sysctl_ip6_fraglifetime()
276 KASSERT(m->m_len >= offset + sizeof(struct ip6_frag), in ip6_deletefraghdr()
278 "offset %d + %zu\n", __func__, m, m->m_len, offset, in ip6_deletefraghdr()
284 m->m_data += sizeof(struct ip6_frag); in ip6_deletefraghdr()
285 m->m_len -= sizeof(struct ip6_frag); in ip6_deletefraghdr()
286 m->m_flags |= M_FRAGMENTED; in ip6_deletefraghdr()
297 V_ip6qb[bucket].count--; in frag6_rmqueue()
317 while ((af6 = TAILQ_FIRST(&q6->ip6q_frags)) != NULL) { in frag6_freef()
318 m = af6->ip6af_m; in frag6_freef()
319 TAILQ_REMOVE(&q6->ip6q_frags, af6, ip6af_tq); in frag6_freef()
325 if (af6->ip6af_off == 0 && m->m_pkthdr.rcvif != NULL) { in frag6_freef()
330 ip6->ip6_src = q6->ip6q_src; in frag6_freef()
331 ip6->ip6_dst = q6->ip6q_dst; in frag6_freef()
341 atomic_subtract_int(&frag6_nfrags, q6->ip6q_nfrag); in frag6_freef()
359 CURVNET_SET_QUIET(ifp->if_vnet); in frag6_cleanup()
376 TAILQ_FOREACH(af6, &q6->ip6q_frags, ip6af_tq) { in frag6_cleanup()
378 if (af6->ip6af_m->m_pkthdr.rcvif == ifp) in frag6_cleanup()
379 af6->ip6af_m->m_pkthdr.rcvif = NULL; in frag6_cleanup()
397 * after the Per-Fragment headers of the original packet.
398 * -> next header field is same for all fragments
401 * The Next Header field of the last header of the Per-Fragment
404 * -> should grab it from the first fragment only
406 * The following note also contradicts with fragment rule - no one is going to
413 * -> should grab it from the first fragment only
432 sizeof(ip6f->ip6f_ident)) / sizeof(uint32_t)]; in frag6_input()
448 if (m->m_len < offset + sizeof(struct ip6_frag)) { in frag6_input()
460 ia6 = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */, false); in frag6_input()
462 dstifp = ia6->ia_ifp; in frag6_input()
465 if (ip6->ip6_plen == 0) { in frag6_input()
479 if ((ip6f->ip6f_offlg & IP6F_MORE_FRAG) && in frag6_input()
480 (((ntohs(ip6->ip6_plen) - offset) & 0x7) != 0)) { in frag6_input()
497 if ((ip6f->ip6f_offlg & ~IP6F_RESERVED_MASK) == 0) { in frag6_input()
499 nxt = ip6f->ip6f_nxt; in frag6_input()
501 * Set nxt(-hdr field value) to the original value. in frag6_input()
502 * We cannot just set ip6->ip6_nxt as there might be in frag6_input()
508 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - in frag6_input()
512 m->m_pkthdr.len -= sizeof(struct ip6_frag); in frag6_input()
521 /* Get fragment length and discard 0-byte fragments. */ in frag6_input()
522 frgpartlen = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen) - offset; in frag6_input()
535 * If maxfrag is -1, accept all fragments without limitation. in frag6_input()
543 * Validate that a full header chain to the ULP is present in the in frag6_input()
547 * (3) Extension headers, if any, and the Upper-Layer header. These in frag6_input()
550 fragoff = ntohs(ip6f->ip6f_offlg & IP6F_OFF_MASK); in frag6_input()
555 srcifp = m->m_pkthdr.rcvif; in frag6_input()
559 memcpy(hashkeyp, &ip6->ip6_src, sizeof(struct in6_addr)); in frag6_input()
561 memcpy(hashkeyp, &ip6->ip6_dst, sizeof(struct in6_addr)); in frag6_input()
563 *hashkeyp = ip6f->ip6f_ident; in frag6_input()
570 if (ip6f->ip6f_ident == q6->ip6q_ident && in frag6_input()
571 IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &q6->ip6q_src) && in frag6_input()
572 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &q6->ip6q_dst) in frag6_input()
588 * If maxfragpackets is -1, accept all fragments without in frag6_input()
612 TAILQ_INIT(&q6->ip6q_frags); in frag6_input()
613 q6->ip6q_ident = ip6f->ip6f_ident; in frag6_input()
614 q6->ip6q_ttl = frag6_milli_to_callout_ticks(V_ip6_fraglifetime); in frag6_input()
615 q6->ip6q_src = ip6->ip6_src; in frag6_input()
616 q6->ip6q_dst = ip6->ip6_dst; in frag6_input()
617 q6->ip6q_ecn = IPV6_ECN(ip6); in frag6_input()
618 q6->ip6q_unfrglen = -1; /* The 1st fragment has not arrived. */ in frag6_input()
633 if (fragoff == 0 && q6->ip6q_unfrglen == -1) { in frag6_input()
634 q6->ip6q_unfrglen = offset - sizeof(struct ip6_hdr) - in frag6_input()
636 q6->ip6q_nxt = ip6f->ip6f_nxt; in frag6_input()
645 if (q6->ip6q_unfrglen >= 0) { in frag6_input()
647 if (q6->ip6q_unfrglen + fragoff + frgpartlen > IPV6_MAXPACKET) { in frag6_input()
652 offset - sizeof(struct ip6_frag) + in frag6_input()
662 offset - sizeof(struct ip6_frag) + in frag6_input()
673 TAILQ_FOREACH_SAFE(af6, &q6->ip6q_frags, ip6af_tq, af6tmp) { in frag6_input()
674 if (q6->ip6q_unfrglen + af6->ip6af_off + in frag6_input()
675 af6->ip6af_frglen > IPV6_MAXPACKET) { in frag6_input()
680 merr = af6->ip6af_m; in frag6_input()
681 erroff = af6->ip6af_offset; in frag6_input()
684 TAILQ_REMOVE(&q6->ip6q_frags, af6, ip6af_tq); in frag6_input()
685 q6->ip6q_nfrag--; in frag6_input()
690 merr->m_pkthdr.rcvif = srcifp; in frag6_input()
699 ip6err->ip6_src = q6->ip6q_src; in frag6_input()
700 ip6err->ip6_dst = q6->ip6q_dst; in frag6_input()
704 erroff - sizeof(struct ip6_frag) + in frag6_input()
714 ip6af->ip6af_mff = (ip6f->ip6f_offlg & IP6F_MORE_FRAG) ? true : false; in frag6_input()
715 ip6af->ip6af_off = fragoff; in frag6_input()
716 ip6af->ip6af_frglen = frgpartlen; in frag6_input()
717 ip6af->ip6af_offset = offset; in frag6_input()
718 ip6af->ip6af_m = m; in frag6_input()
722 * Do a manual insert rather than a hard-to-understand cast in frag6_input()
725 TAILQ_INSERT_HEAD(&q6->ip6q_frags, ip6af, ip6af_tq); in frag6_input()
733 * Drop if CE and not-ECT are mixed for the same packet. in frag6_input()
736 ecn0 = q6->ip6q_ecn; in frag6_input()
743 q6->ip6q_ecn = IPTOS_ECN_CE; in frag6_input()
751 TAILQ_FOREACH(af6, &q6->ip6q_frags, ip6af_tq) in frag6_input()
752 if (af6->ip6af_off > ip6af->ip6af_off) in frag6_input()
766 af6tmp = TAILQ_LAST(&q6->ip6q_frags, ip6fraghead); in frag6_input()
768 if (af6tmp->ip6af_off + af6tmp->ip6af_frglen - in frag6_input()
769 ip6af->ip6af_off > 0) { in frag6_input()
770 if (af6tmp->ip6af_off != ip6af->ip6af_off || in frag6_input()
771 af6tmp->ip6af_frglen != ip6af->ip6af_frglen) in frag6_input()
778 if (ip6af->ip6af_off + ip6af->ip6af_frglen - in frag6_input()
779 af6->ip6af_off > 0) { in frag6_input()
780 if (af6->ip6af_off != ip6af->ip6af_off || in frag6_input()
781 af6->ip6af_frglen != ip6af->ip6af_frglen) in frag6_input()
800 TAILQ_INSERT_TAIL(&q6->ip6q_frags, ip6af, ip6af_tq); in frag6_input()
803 q6->ip6q_nfrag++; in frag6_input()
806 TAILQ_FOREACH(af6, &q6->ip6q_frags, ip6af_tq) { in frag6_input()
807 if (af6->ip6af_off != plen) { in frag6_input()
808 if (q6->ip6q_nfrag > V_ip6_maxfragsperpacket) { in frag6_input()
809 IP6STAT_ADD(ip6s_fragdropped, q6->ip6q_nfrag); in frag6_input()
816 plen += af6->ip6af_frglen; in frag6_input()
818 af6 = TAILQ_LAST(&q6->ip6q_frags, ip6fraghead); in frag6_input()
819 if (af6->ip6af_mff) { in frag6_input()
820 if (q6->ip6q_nfrag > V_ip6_maxfragsperpacket) { in frag6_input()
821 IP6STAT_ADD(ip6s_fragdropped, q6->ip6q_nfrag); in frag6_input()
830 ip6af = TAILQ_FIRST(&q6->ip6q_frags); in frag6_input()
831 t = m = ip6af->ip6af_m; in frag6_input()
832 TAILQ_REMOVE(&q6->ip6q_frags, ip6af, ip6af_tq); in frag6_input()
833 while ((af6 = TAILQ_FIRST(&q6->ip6q_frags)) != NULL) { in frag6_input()
834 m->m_pkthdr.csum_flags &= in frag6_input()
835 af6->ip6af_m->m_pkthdr.csum_flags; in frag6_input()
836 m->m_pkthdr.csum_data += in frag6_input()
837 af6->ip6af_m->m_pkthdr.csum_data; in frag6_input()
839 TAILQ_REMOVE(&q6->ip6q_frags, af6, ip6af_tq); in frag6_input()
841 m_adj(af6->ip6af_m, af6->ip6af_offset); in frag6_input()
842 m_demote_pkthdr(af6->ip6af_m); in frag6_input()
843 m_cat(t, af6->ip6af_m); in frag6_input()
847 while (m->m_pkthdr.csum_data & 0xffff0000) in frag6_input()
848 m->m_pkthdr.csum_data = (m->m_pkthdr.csum_data & 0xffff) + in frag6_input()
849 (m->m_pkthdr.csum_data >> 16); in frag6_input()
852 offset = ip6af->ip6af_offset - sizeof(struct ip6_frag); in frag6_input()
854 if ((u_int)plen + (u_int)offset - sizeof(struct ip6_hdr) > in frag6_input()
860 ip6->ip6_plen = htons((u_short)plen + offset - sizeof(struct ip6_hdr)); in frag6_input()
861 if (q6->ip6q_ecn == IPTOS_ECN_CE) in frag6_input()
862 ip6->ip6_flow |= htonl(IPTOS_ECN_CE << 20); in frag6_input()
863 nxt = q6->ip6q_nxt; in frag6_input()
867 /* Set nxt(-hdr field value) to the original value. */ in frag6_input()
874 atomic_subtract_int(&frag6_nfrags, q6->ip6q_nfrag); in frag6_input()
877 if (m->m_flags & M_PKTHDR) { /* Isn't it always true? */ in frag6_input()
880 for (t = m; t; t = t->m_next) in frag6_input()
881 plen += t->m_len; in frag6_input()
882 m->m_pkthdr.len = plen; in frag6_input()
884 m->m_pkthdr.rcvif = srcifp; in frag6_input()
894 ip6dc->ip6dc_nxt = nxt; in frag6_input()
895 ip6dc->ip6dc_off = offset; in frag6_input()
952 if (--q6->ip6q_ttl == 0) { in frag6_slowtimo()
954 q6->ip6q_nfrag); in frag6_slowtimo()
971 IP6STAT_ADD(ip6s_fragoverflow, q6->ip6q_nfrag); in frag6_slowtimo()
988 IP6STAT_ADD(ip6s_fragoverflow, q6->ip6q_nfrag); in frag6_slowtimo()