aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2023-06-01 12:04:49 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2023-06-01 12:04:49 +0000
commite32221a15f089282e5dfe18891c5312b26cbe3ba (patch)
treed72efb2ddbe464c7877272a37e5aa542a1ea27a5
parent0c2beef72d1a493d7bf9fe901f91aba35cc3b6e1 (diff)
downloadsrc-e32221a15f089282e5dfe18891c5312b26cbe3ba.tar.gz
src-e32221a15f089282e5dfe18891c5312b26cbe3ba.zip
netinet6: make IPv6 fragment TTL per-VNET configurable.
Having it configurable adds more flexibility, especially for the systems with low amount of memory. Additionally, it allows to speedup frag6/ tests execution. Reviewed by: kp, markj, bz Differential Revision: https://reviews.freebsd.org/D35755 MFC after: 2 weeks
-rw-r--r--sys/netinet/ip6.h2
-rw-r--r--sys/netinet6/frag6.c64
-rw-r--r--sys/netinet6/ip6_var.h2
-rw-r--r--tests/sys/netinet6/frag6/frag6.subr10
-rw-r--r--tests/sys/netinet6/frag6/frag6_01.py2
-rw-r--r--tests/sys/netinet6/frag6/frag6_05.py2
-rw-r--r--tests/sys/netinet6/frag6/frag6_07.py2
-rw-r--r--tests/sys/netinet6/frag6/frag6_08.py2
-rw-r--r--tests/sys/netinet6/frag6/frag6_09.py2
-rw-r--r--tests/sys/netinet6/frag6/frag6_10.py2
-rw-r--r--tests/sys/netinet6/frag6/frag6_11.py2
-rw-r--r--tests/sys/netinet6/frag6/frag6_12.py2
-rw-r--r--tests/sys/netinet6/frag6/frag6_13.py2
-rw-r--r--tests/sys/netinet6/frag6/frag6_14.py2
-rwxr-xr-xtests/sys/netinet6/frag6/frag6_20.py2
15 files changed, 79 insertions, 21 deletions
diff --git a/sys/netinet/ip6.h b/sys/netinet/ip6.h
index 6617e1ca7d00..30482c6985cf 100644
--- a/sys/netinet/ip6.h
+++ b/sys/netinet/ip6.h
@@ -254,7 +254,7 @@ struct ip6_frag {
*/
#define IPV6_MAXHLIM 255 /* maximum hoplimit */
#define IPV6_DEFHLIM 64 /* default hlim */
-#define IPV6_FRAGTTL 120 /* ttl for fragment packets, in slowtimo tick */
+#define IPV6_DEFFRAGTTL 60000 /* Default fragment packets lifetime, in milliseconds */
#define IPV6_HLIMDEC 1 /* subtracted when forwarding */
#define IPV6_MMTU 1280 /* minimal MTU and reassembly. 1024 + 256 */
diff --git a/sys/netinet6/frag6.c b/sys/netinet6/frag6.c
index d634f869acd5..5acdc1b20981 100644
--- a/sys/netinet6/frag6.c
+++ b/sys/netinet6/frag6.c
@@ -125,6 +125,10 @@ VNET_DEFINE_STATIC(volatile u_int, frag6_nfragpackets);
#define V_ip6_maxfragpackets VNET(ip6_maxfragpackets)
#define V_frag6_nfragpackets VNET(frag6_nfragpackets)
+/* Maximum per-VNET reassembly timeout (milliseconds) */
+VNET_DEFINE_STATIC(u_int, ip6_fraglifetime) = IPV6_DEFFRAGTTL;
+#define V_ip6_fraglifetime VNET(ip6_fraglifetime)
+
/* Maximum per-VNET reassembly queues per bucket and fragments per packet. */
VNET_DEFINE_STATIC(int, ip6_maxfragbucketsize);
VNET_DEFINE_STATIC(int, ip6_maxfragsperpacket);
@@ -159,6 +163,9 @@ VNET_DEFINE_STATIC(uint32_t, ip6qb_hashseed);
#define IP6_MAXFRAGS (nmbclusters / 32)
#define IP6_MAXFRAGPACKETS (imin(IP6_MAXFRAGS, IP6REASS_NHASH * 50))
+/* Interval between periodic reassembly queue inspections */
+#define IP6_CALLOUT_INTERVAL_MS 500
+
/*
* Sysctls and helper function.
*/
@@ -213,6 +220,53 @@ SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGBUCKETSIZE, maxfragbucketsize,
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_maxfragbucketsize), 0,
"Maximum number of reassembly queues per hash bucket");
+static int
+frag6_milli_to_callout_ticks(int ms)
+{
+ return (ms / IP6_CALLOUT_INTERVAL_MS);
+}
+
+static int
+frag6_callout_ticks_to_milli(int ms)
+{
+ return (ms * IP6_CALLOUT_INTERVAL_MS);
+}
+
+_Static_assert(sizeof(((struct ip6q *)NULL)->ip6q_ttl) >= 2,
+ "ip6q_ttl field is not large enough");
+
+static int
+sysctl_ip6_fraglifetime(SYSCTL_HANDLER_ARGS)
+{
+ int error, val;
+
+ val = V_ip6_fraglifetime;
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error != 0 || !req->newptr)
+ return (error);
+ if (val <= 0)
+ val = IPV6_DEFFRAGTTL;
+
+ if (frag6_milli_to_callout_ticks(val) >= 65536)
+ val = frag6_callout_ticks_to_milli(65535);
+#ifdef VIMAGE
+ if (!IS_DEFAULT_VNET(curvnet)) {
+ CURVNET_SET(vnet0);
+ int host_val = V_ip6_fraglifetime;
+ CURVNET_RESTORE();
+
+ if (val > host_val)
+ val = host_val;
+ }
+#endif
+ V_ip6_fraglifetime = val;
+ return (0);
+}
+SYSCTL_PROC(_net_inet6_ip6, OID_AUTO, fraglifetime_ms,
+ CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
+ NULL, 0, sysctl_ip6_fraglifetime, "I",
+ "Fragment lifetime, in milliseconds");
+
/*
* Remove the IPv6 fragmentation header from the mbuf.
*/
@@ -552,7 +606,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
/* ip6q_nxt will be filled afterwards, from 1st fragment. */
TAILQ_INIT(&q6->ip6q_frags);
q6->ip6q_ident = ip6f->ip6f_ident;
- q6->ip6q_ttl = IPV6_FRAGTTL;
+ q6->ip6q_ttl = frag6_milli_to_callout_ticks(V_ip6_fraglifetime);
q6->ip6q_src = ip6->ip6_src;
q6->ip6q_dst = ip6->ip6_dst;
q6->ip6q_ecn = IPV6_ECN(ip6);
@@ -952,8 +1006,8 @@ frag6_slowtimo(void *arg __unused)
}
VNET_LIST_RUNLOCK_NOSLEEP();
done:
- callout_reset_sbt(&frag6_callout, SBT_1MS * 500, SBT_1MS * 10,
- frag6_slowtimo, NULL, 0);
+ callout_reset_sbt(&frag6_callout, SBT_1MS * IP6_CALLOUT_INTERVAL_MS,
+ SBT_1MS * 10, frag6_slowtimo, NULL, 0);
}
static void
@@ -961,8 +1015,8 @@ frag6_slowtimo_init(void *arg __unused)
{
callout_init(&frag6_callout, 1);
- callout_reset_sbt(&frag6_callout, SBT_1MS * 500, SBT_1MS * 10,
- frag6_slowtimo, NULL, 0);
+ callout_reset_sbt(&frag6_callout, SBT_1MS * IP6_CALLOUT_INTERVAL_MS,
+ SBT_1MS * 10, frag6_slowtimo, NULL, 0);
}
SYSINIT(frag6, SI_SUB_VNET_DONE, SI_ORDER_ANY, frag6_slowtimo_init, NULL);
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
index c267503d7151..bc409780feec 100644
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -81,7 +81,7 @@ struct ip6q {
u_int32_t ip6q_ident;
u_int8_t ip6q_nxt;
u_int8_t ip6q_ecn;
- u_int8_t ip6q_ttl;
+ u_int16_t ip6q_ttl;
struct in6_addr ip6q_src, ip6q_dst;
TAILQ_ENTRY(ip6q) ip6q_tq;
int ip6q_unfrglen; /* len of unfragmentable part */
diff --git a/tests/sys/netinet6/frag6/frag6.subr b/tests/sys/netinet6/frag6/frag6.subr
index 1ea947c72de5..6f7d0799642c 100644
--- a/tests/sys/netinet6/frag6/frag6.subr
+++ b/tests/sys/netinet6/frag6/frag6.subr
@@ -59,13 +59,17 @@ frag6_body()
jname="v6t-${id}-${yl}-${xl}"
vnet_mkjail ${jname} ${epair}b
+ jexec ${jname} sysctl net.inet6.ip6.dad_count=0
jexec ${jname} ifconfig ${epair}b up
jexec ${jname} ifconfig ${epair}b inet6 ${ip6b}/64
+ # Set max fragment reassembly time to 2 seconds
+ jexec ${jname} sysctl net.inet6.ip6.fraglifetime_ms=2000
+
# Let IPv6 ND do its thing.
- #ping6 -q -c 1 ff02::1%${epair}a
- #ping6 -q -c 1 ${ip6b}
- sleep 3
+ while [ `ifconfig ${epair}a inet6 | grep -c tentative` != "0" ]; do
+ sleep 0.1
+ done
# We need to try to make sure all expiry happened, otherwise there might
# be global fragments queued. (This still does not rule out that there
diff --git a/tests/sys/netinet6/frag6/frag6_01.py b/tests/sys/netinet6/frag6/frag6_01.py
index efa99ce65759..db6cabc1a84a 100644
--- a/tests/sys/netinet6/frag6/frag6_01.py
+++ b/tests/sys/netinet6/frag6/frag6_01.py
@@ -105,7 +105,7 @@ def main():
# We should only need to sleep 0.10 but it seems scapy
# takes time for this one.
- sleep(75)
+ sleep(3)
sniffer.setEnd()
sniffer.join()
if not sniffer.foundCorrectPacket:
diff --git a/tests/sys/netinet6/frag6/frag6_05.py b/tests/sys/netinet6/frag6/frag6_05.py
index f9bc947d5465..9c98ea1aaf2e 100644
--- a/tests/sys/netinet6/frag6/frag6_05.py
+++ b/tests/sys/netinet6/frag6/frag6_05.py
@@ -79,7 +79,7 @@ def main():
sp.sendp(ip6f01, iface=args.sendif[0], verbose=False)
# Wait for possible expiry to happen.
- sleep(75)
+ sleep(3)
sys.exit(0)
if __name__ == '__main__':
diff --git a/tests/sys/netinet6/frag6/frag6_07.py b/tests/sys/netinet6/frag6/frag6_07.py
index 231f49eac2e0..540c5012e524 100644
--- a/tests/sys/netinet6/frag6/frag6_07.py
+++ b/tests/sys/netinet6/frag6/frag6_07.py
@@ -168,7 +168,7 @@ def main():
sys.exit(1)
# Wait for expiry from first test run.
- sleep(75)
+ sleep(3)
sniffer2.setEnd()
sniffer2.join()
if not sniffer2.foundCorrectPacket:
diff --git a/tests/sys/netinet6/frag6/frag6_08.py b/tests/sys/netinet6/frag6/frag6_08.py
index 25f57f702e71..74d7495f43cb 100644
--- a/tests/sys/netinet6/frag6/frag6_08.py
+++ b/tests/sys/netinet6/frag6/frag6_08.py
@@ -142,7 +142,7 @@ def main():
sniffer.join()
if not sniffer.foundCorrectPacket:
sys.exit(1)
- sleep(75)
+ sleep(3)
sniffer2.setEnd()
sniffer2.join()
if not sniffer2.foundCorrectPacket:
diff --git a/tests/sys/netinet6/frag6/frag6_09.py b/tests/sys/netinet6/frag6/frag6_09.py
index 63ec646e1175..b5c519040292 100644
--- a/tests/sys/netinet6/frag6/frag6_09.py
+++ b/tests/sys/netinet6/frag6/frag6_09.py
@@ -99,7 +99,7 @@ def main():
sp.sendp(ip6f01, iface=args.sendif[0], verbose=False)
# Wait for ICMPv6 error generation on timeout.
- sleep(75)
+ sleep(3)
sniffer.setEnd()
sniffer.join()
if not sniffer.foundCorrectPacket:
diff --git a/tests/sys/netinet6/frag6/frag6_10.py b/tests/sys/netinet6/frag6/frag6_10.py
index fcd331190c02..191e3fc3e075 100644
--- a/tests/sys/netinet6/frag6/frag6_10.py
+++ b/tests/sys/netinet6/frag6/frag6_10.py
@@ -75,7 +75,7 @@ def main():
# We do not generate ICMPv6 for non-off=0-segments.
# Wait for expiry.
- sleep(75)
+ sleep(3)
sys.exit(0)
diff --git a/tests/sys/netinet6/frag6/frag6_11.py b/tests/sys/netinet6/frag6/frag6_11.py
index 6b9643337597..be50a766ab1a 100644
--- a/tests/sys/netinet6/frag6/frag6_11.py
+++ b/tests/sys/netinet6/frag6/frag6_11.py
@@ -75,7 +75,7 @@ def main():
# Wait for expiration to happen. We will not see an ICMPv6 as there
# is no frag with offset=0.
- sleep(75)
+ sleep(3)
sys.exit(0)
diff --git a/tests/sys/netinet6/frag6/frag6_12.py b/tests/sys/netinet6/frag6/frag6_12.py
index a683782f2b69..d82610a0f75b 100644
--- a/tests/sys/netinet6/frag6/frag6_12.py
+++ b/tests/sys/netinet6/frag6/frag6_12.py
@@ -101,7 +101,7 @@ def main():
sp.sendp(ip6f01, iface=args.sendif[0], verbose=False)
# Wait for ICMPv6 error generation on timeout.
- sleep(75)
+ sleep(3)
sniffer.setEnd()
sniffer.join()
if not sniffer.foundCorrectPacket:
diff --git a/tests/sys/netinet6/frag6/frag6_13.py b/tests/sys/netinet6/frag6/frag6_13.py
index e377a4272fa1..a8717c2c795c 100644
--- a/tests/sys/netinet6/frag6/frag6_13.py
+++ b/tests/sys/netinet6/frag6/frag6_13.py
@@ -117,7 +117,7 @@ def main():
sp.sendp(ip6f02, iface=args.sendif[0], verbose=False)
# Wait for expiry.
- sleep(75)
+ sleep(3)
sys.exit(0)
if __name__ == '__main__':
diff --git a/tests/sys/netinet6/frag6/frag6_14.py b/tests/sys/netinet6/frag6/frag6_14.py
index b53a65e67529..49fae50f4bae 100644
--- a/tests/sys/netinet6/frag6/frag6_14.py
+++ b/tests/sys/netinet6/frag6/frag6_14.py
@@ -132,7 +132,7 @@ def main():
sp.sendp(ip6f02, iface=args.sendif[0], verbose=False)
# Wait for expiry.
- sleep(75)
+ sleep(3)
sys.exit(0)
if __name__ == '__main__':
diff --git a/tests/sys/netinet6/frag6/frag6_20.py b/tests/sys/netinet6/frag6/frag6_20.py
index 6dd4c2379357..4a68b242a23e 100755
--- a/tests/sys/netinet6/frag6/frag6_20.py
+++ b/tests/sys/netinet6/frag6/frag6_20.py
@@ -127,7 +127,7 @@ def main():
sp.sendp(ip6f01, iface=args.sendif[0], verbose=False)
sp.sendp(ip6f02, iface=args.sendif[0], verbose=False)
- sleep(75)
+ sleep(3)
sniffer.setEnd()
sniffer.join()
if not sniffer.foundCorrectPacket: