Module Name:    src
Committed By:   knakahara
Date:           Wed Oct 30 03:45:59 UTC 2019

Modified Files:
        src/sys/net: if_gif.c if_gif.h
        src/sys/netinet6: in6.h in6_gif.c in6_gif.h

Log Message:
Add sysctl nodes to control fragmentation with IPv[46] over IPv6 gif(4).

New sysctl node "net.inet6.ip6.gifpmtu" means
    - 0 (default)
      Fragment by IPV6_MMTU. All packets reach the destination certainly,
      however the long packet performance is poor.
      This is same behavior as before.
    - 1
      Fragment by outer interface's MTU. The long packet performance would
      be good, however the packets may be dropped in some network paths
      whose path MTU less than the interface's MTU.
    - others
      undefined yet

New sysctl node "net.interfaces.gif*.pmtu" means
    - -1 (default)
      Use system default value (net.inet6.ip6.gifpmtu).
    - 0
      Fragment by IPV6_MMTU for this gif(4) tunnel.
    - 1
      Fragment by outer interface's MTU for this gif(4) tunnel.
    - others
      undefined yet

See RFC4459 for more information and other solutions.


To generate a diff of this commit:
cvs rdiff -u -r1.149 -r1.150 src/sys/net/if_gif.c
cvs rdiff -u -r1.33 -r1.34 src/sys/net/if_gif.h
cvs rdiff -u -r1.96 -r1.97 src/sys/netinet6/in6.h
cvs rdiff -u -r1.94 -r1.95 src/sys/netinet6/in6_gif.c
cvs rdiff -u -r1.17 -r1.18 src/sys/netinet6/in6_gif.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/net/if_gif.c
diff -u src/sys/net/if_gif.c:1.149 src/sys/net/if_gif.c:1.150
--- src/sys/net/if_gif.c:1.149	Thu Sep 19 06:07:24 2019
+++ src/sys/net/if_gif.c	Wed Oct 30 03:45:59 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_gif.c,v 1.149 2019/09/19 06:07:24 knakahara Exp $	*/
+/*	$NetBSD: if_gif.c,v 1.150 2019/10/30 03:45:59 knakahara Exp $	*/
 /*	$KAME: if_gif.c,v 1.76 2001/08/20 02:01:02 kjc Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.149 2019/09/19 06:07:24 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.150 2019/10/30 03:45:59 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -142,6 +142,58 @@ static int max_gif_nesting = MAX_GIF_NES
 
 static struct sysctllog *gif_sysctl;
 
+#ifdef INET6
+static int
+sysctl_gif_pmtu_global(SYSCTLFN_ARGS)
+{
+	int error, pmtu;
+	struct sysctlnode node = *rnode;
+
+	pmtu = ip6_gif_pmtu;
+	node.sysctl_data = &pmtu;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error || newp == NULL)
+		return error;
+
+	switch (pmtu) {
+	case GIF_PMTU_MINMTU:
+	case GIF_PMTU_OUTERMTU:
+		ip6_gif_pmtu = pmtu;
+		break;
+	default:
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+sysctl_gif_pmtu_perif(SYSCTLFN_ARGS)
+{
+	int error, pmtu;
+	struct sysctlnode node = *rnode;
+	struct gif_softc *sc = (struct gif_softc *)node.sysctl_data;
+
+	pmtu = sc->gif_pmtu;
+	node.sysctl_data = &pmtu;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error || newp == NULL)
+		return error;
+
+	switch (pmtu) {
+	case GIF_PMTU_SYSDEFAULT:
+	case GIF_PMTU_MINMTU:
+	case GIF_PMTU_OUTERMTU:
+		sc->gif_pmtu = pmtu;
+		break;
+	default:
+		return EINVAL;
+	}
+
+	return 0;
+}
+#endif
+
 static void
 gif_sysctl_setup(void)
 {
@@ -196,6 +248,52 @@ gif_sysctl_setup(void)
 		       NULL, 0, &ip6_gif_hlim, 0,
 		       CTL_NET, PF_INET6, IPPROTO_IPV6,
 		       IPV6CTL_GIF_HLIM, CTL_EOL);
+
+	sysctl_createv(&gif_sysctl, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "gifpmtu",
+		       SYSCTL_DESCR("Default Path MTU setting for gif tunnels"),
+		       sysctl_gif_pmtu_global, 0, NULL, 0,
+		       CTL_NET, PF_INET6, IPPROTO_IPV6,
+		       IPV6CTL_GIF_PMTU, CTL_EOL);
+#endif
+}
+
+static void
+gif_perif_sysctl_setup(struct sysctllog **clog, struct gif_softc *sc)
+{
+#ifdef INET6
+	const struct sysctlnode *cnode, *rnode;
+	struct ifnet *ifp = &sc->gif_if;
+	const char *ifname = ifp->if_xname;
+	int rv;
+
+	/*
+	 * Already created in sysctl_sndq_setup().
+	 */
+	sysctl_createv(clog, 0, NULL, &rnode,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_NODE, "interfaces",
+		       SYSCTL_DESCR("Per-interface controls"),
+		       NULL, 0, NULL, 0,
+		       CTL_NET, CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, &rnode, &rnode,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_NODE, ifname,
+		       SYSCTL_DESCR("Interface controls"),
+		       NULL, 0, NULL, 0,
+		       CTL_CREATE, CTL_EOL);
+
+	rv = sysctl_createv(clog, 0, &rnode, &cnode,
+			    CTLFLAG_PERMANENT,
+			    CTLTYPE_INT, "pmtu",
+			    SYSCTL_DESCR("Path MTU setting for this gif tunnel"),
+			    sysctl_gif_pmtu_perif, 0, (void *)sc, 0,
+			    CTL_CREATE, CTL_EOL);
+	if (rv != 0)
+		log(LOG_WARNING, "%s: could not attach sysctl node pmtu\n", ifname);
+
+	sc->gif_pmtu = GIF_PMTU_SYSDEFAULT;
 #endif
 }
 
@@ -248,6 +346,7 @@ gif_clone_create(struct if_clone *ifc, i
 {
 	struct gif_softc *sc;
 	struct gif_variant *var;
+	struct ifnet *ifp;
 	int rv;
 
 	sc = kmem_zalloc(sizeof(struct gif_softc), KM_SLEEP);
@@ -260,6 +359,9 @@ gif_clone_create(struct if_clone *ifc, i
 		return rv;
 	}
 
+	ifp = &sc->gif_if;
+	gif_perif_sysctl_setup(&ifp->if_sysctl_log, sc);
+
 	var = kmem_zalloc(sizeof(*var), KM_SLEEP);
 	var->gv_softc = sc;
 	psref_target_init(&var->gv_psref, gv_psref_class);

Index: src/sys/net/if_gif.h
diff -u src/sys/net/if_gif.h:1.33 src/sys/net/if_gif.h:1.34
--- src/sys/net/if_gif.h:1.33	Thu Sep 19 06:07:24 2019
+++ src/sys/net/if_gif.h	Wed Oct 30 03:45:59 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_gif.h,v 1.33 2019/09/19 06:07:24 knakahara Exp $	*/
+/*	$NetBSD: if_gif.h,v 1.34 2019/10/30 03:45:59 knakahara Exp $	*/
 /*	$KAME: if_gif.h,v 1.23 2001/07/27 09:21:42 itojun Exp $	*/
 
 /*
@@ -76,6 +76,8 @@ struct gif_softc {
 	kmutex_t gif_lock;		/* writer lock for gif_var */
 	pserialize_t gif_psz;
 
+	int gif_pmtu;
+
 	LIST_ENTRY(gif_softc) gif_list;	/* list of all gifs */
 };
 #define GIF_ROUTE_TTL	10

Index: src/sys/netinet6/in6.h
diff -u src/sys/netinet6/in6.h:1.96 src/sys/netinet6/in6.h:1.97
--- src/sys/netinet6/in6.h:1.96	Thu Sep  5 20:17:27 2019
+++ src/sys/netinet6/in6.h	Wed Oct 30 03:45:59 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6.h,v 1.96 2019/09/05 20:17:27 kamil Exp $	*/
+/*	$NetBSD: in6.h,v 1.97 2019/10/30 03:45:59 knakahara Exp $	*/
 /*	$KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $	*/
 
 /*
@@ -536,6 +536,7 @@ struct ip6_mtuinfo {
 					/* via router advertisement */
 #define IPV6CTL_RTADV_NUMROUTES 44	/* current number of routes */
 					/* via router advertisement */
+#define IPV6CTL_GIF_PMTU	45	/* gif(4) Path MTU setting */
 #endif /* _NETBSD_SOURCE */
 
 #ifdef _KERNEL

Index: src/sys/netinet6/in6_gif.c
diff -u src/sys/netinet6/in6_gif.c:1.94 src/sys/netinet6/in6_gif.c:1.95
--- src/sys/netinet6/in6_gif.c:1.94	Thu Sep 19 06:07:25 2019
+++ src/sys/netinet6/in6_gif.c	Wed Oct 30 03:45:59 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_gif.c,v 1.94 2019/09/19 06:07:25 knakahara Exp $	*/
+/*	$NetBSD: in6_gif.c,v 1.95 2019/10/30 03:45:59 knakahara Exp $	*/
 /*	$KAME: in6_gif.c,v 1.62 2001/07/29 04:27:25 itojun Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.94 2019/09/19 06:07:25 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_gif.c,v 1.95 2019/10/30 03:45:59 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -73,6 +73,7 @@ static int gif_validate6(const struct ip
 	struct ifnet *);
 
 int	ip6_gif_hlim = GIF_HLIM;
+int	ip6_gif_pmtu = 0;
 
 static const struct encapsw in6_gif_encapsw;
 
@@ -198,12 +199,54 @@ in6_gif_output(struct gif_variant *var, 
 	rtcache_unref(rt, ro_pc);
 
 #ifdef IPV6_MINMTU
+	int flags;
+
 	/*
-	 * force fragmentation to minimum MTU, to avoid path MTU discovery.
-	 * it is too painful to ask for resend of inner packet, to achieve
+	 * - GIF_PMTU_MINMTU
+	 *   Force fragmentation to minimum MTU to avoid path MTU discovery
+	 * - GIF_PMTU_OUTERMTU
+	 *   Trust outer MTU is large enough to send all packets
+	 *
+	 * It is too painful to ask for resend of inner packet, to achieve
 	 * path MTU discovery for encapsulated packets.
+	 *
+	 * See RFC4459.
 	 */
-	error = ip6_output(m, 0, ro_pc, IPV6_MINMTU, NULL, NULL, NULL);
+	if (sc->gif_pmtu == GIF_PMTU_SYSDEFAULT) {
+		switch (ip6_gif_pmtu) {
+		case GIF_PMTU_MINMTU:
+			flags = IPV6_MINMTU;
+			break;
+		case GIF_PMTU_OUTERMTU:
+			flags = 0;
+			break;
+		default:
+#ifdef DEBUG
+			log(LOG_DEBUG, "%s: ignore unexpected ip6_gif_pmtu %d\n",
+			    __func__, ip6_gif_pmtu);
+#endif
+			flags = IPV6_MINMTU;
+			break;
+		}
+	} else {
+		switch (sc->gif_pmtu) {
+		case GIF_PMTU_MINMTU:
+			flags = IPV6_MINMTU;
+			break;
+		case GIF_PMTU_OUTERMTU:
+			flags = 0;
+			break;
+		default:
+#ifdef DEBUG
+			log(LOG_DEBUG, "%s: ignore unexpected gif_pmtu of %s %d\n",
+			    __func__, ifp->if_xname, sc->gif_pmtu);
+#endif
+			flags = IPV6_MINMTU;
+			break;
+		}
+	}
+
+	error = ip6_output(m, 0, ro_pc, flags, NULL, NULL, NULL);
 #else
 	error = ip6_output(m, 0, ro_pc, 0, NULL, NULL, NULL);
 #endif

Index: src/sys/netinet6/in6_gif.h
diff -u src/sys/netinet6/in6_gif.h:1.17 src/sys/netinet6/in6_gif.h:1.18
--- src/sys/netinet6/in6_gif.h:1.17	Mon Nov 27 05:02:22 2017
+++ src/sys/netinet6/in6_gif.h	Wed Oct 30 03:45:59 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_gif.h,v 1.17 2017/11/27 05:02:22 knakahara Exp $	*/
+/*	$NetBSD: in6_gif.h,v 1.18 2019/10/30 03:45:59 knakahara Exp $	*/
 /*	$KAME: in6_gif.h,v 1.7 2001/07/26 06:53:16 jinmei Exp $	*/
 
 /*
@@ -35,6 +35,11 @@
 
 #define GIF_HLIM	30
 extern int	ip6_gif_hlim;		/* Hop limit for gif encap packet */
+extern int	ip6_gif_pmtu;		/* Default Path MTU setting for gif tunnels */
+
+#define GIF_PMTU_SYSDEFAULT	-1	/* Use system default value (ip6_gif_pmtu) */
+#define GIF_PMTU_MINMTU		0	/* Fragmented by IPV6_MINMTU */
+#define GIF_PMTU_OUTERMTU	1	/* Fragmented by Path MTU of outer path */
 
 struct gif_variant;
 struct sockaddr;

Reply via email to