Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Add sysctl nodes to control fragmentation with IPv[46] o...



details:   https://anonhg.NetBSD.org/src/rev/771e141ce5b7
branches:  trunk
changeset: 460655:771e141ce5b7
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Wed Oct 30 03:45:59 2019 +0000

description:
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.

diffstat:

 sys/net/if_gif.c       |  106 ++++++++++++++++++++++++++++++++++++++++++++++++-
 sys/net/if_gif.h       |    4 +-
 sys/netinet6/in6.h     |    3 +-
 sys/netinet6/in6_gif.c |   53 ++++++++++++++++++++++--
 sys/netinet6/in6_gif.h |    7 ++-
 5 files changed, 163 insertions(+), 10 deletions(-)

diffs (288 lines):

diff -r a0316b0fb718 -r 771e141ce5b7 sys/net/if_gif.c
--- a/sys/net/if_gif.c  Wed Oct 30 02:44:29 2019 +0000
+++ b/sys/net/if_gif.c  Wed Oct 30 03:45:59 2019 +0000
@@ -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 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 @@
                       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 @@
 {
        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 @@
                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);
diff -r a0316b0fb718 -r 771e141ce5b7 sys/net/if_gif.h
--- a/sys/net/if_gif.h  Wed Oct 30 02:44:29 2019 +0000
+++ b/sys/net/if_gif.h  Wed Oct 30 03:45:59 2019 +0000
@@ -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 @@
        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
diff -r a0316b0fb718 -r 771e141ce5b7 sys/netinet6/in6.h
--- a/sys/netinet6/in6.h        Wed Oct 30 02:44:29 2019 +0000
+++ b/sys/netinet6/in6.h        Wed Oct 30 03:45:59 2019 +0000
@@ -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 @@
                                        /* 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
diff -r a0316b0fb718 -r 771e141ce5b7 sys/netinet6/in6_gif.c
--- a/sys/netinet6/in6_gif.c    Wed Oct 30 02:44:29 2019 +0000
+++ b/sys/netinet6/in6_gif.c    Wed Oct 30 03:45:59 2019 +0000
@@ -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 @@
        struct ifnet *);
 
 int    ip6_gif_hlim = GIF_HLIM;
+int    ip6_gif_pmtu = 0;
 
 static const struct encapsw in6_gif_encapsw;
 
@@ -198,12 +199,54 @@
        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
diff -r a0316b0fb718 -r 771e141ce5b7 sys/netinet6/in6_gif.h
--- a/sys/netinet6/in6_gif.h    Wed Oct 30 02:44:29 2019 +0000
+++ b/sys/netinet6/in6_gif.h    Wed Oct 30 03:45:59 2019 +0000
@@ -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;



Home | Main Index | Thread Index | Old Index