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
This commit is contained in:
parent
0c2beef72d
commit
e32221a15f
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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__':
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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__':
|
||||
|
@ -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__':
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user