The branch main has been updated by melifaro:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=e32221a15f089282e5dfe18891c5312b26cbe3ba

commit e32221a15f089282e5dfe18891c5312b26cbe3ba
Author:     Alexander V. Chernikov <melif...@freebsd.org>
AuthorDate: 2023-06-01 12:04:49 +0000
Commit:     Alexander V. Chernikov <melif...@freebsd.org>
CommitDate: 2023-06-01 12:04:49 +0000

    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
---
 sys/netinet/ip6.h                    |  2 +-
 sys/netinet6/frag6.c                 | 64 +++++++++++++++++++++++++++++++++---
 sys/netinet6/ip6_var.h               |  2 +-
 tests/sys/netinet6/frag6/frag6.subr  | 10 ++++--
 tests/sys/netinet6/frag6/frag6_01.py |  2 +-
 tests/sys/netinet6/frag6/frag6_05.py |  2 +-
 tests/sys/netinet6/frag6/frag6_07.py |  2 +-
 tests/sys/netinet6/frag6/frag6_08.py |  2 +-
 tests/sys/netinet6/frag6/frag6_09.py |  2 +-
 tests/sys/netinet6/frag6/frag6_10.py |  2 +-
 tests/sys/netinet6/frag6/frag6_11.py |  2 +-
 tests/sys/netinet6/frag6/frag6_12.py |  2 +-
 tests/sys/netinet6/frag6/frag6_13.py |  2 +-
 tests/sys/netinet6/frag6/frag6_14.py |  2 +-
 tests/sys/netinet6/frag6/frag6_20.py |  2 +-
 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:

Reply via email to