Page MenuHomeFreeBSD

D1125.diff
No OneTemporary

D1125.diff

Index: sbin/route/route.c
===================================================================
--- sbin/route/route.c
+++ sbin/route/route.c
@@ -1590,7 +1590,7 @@
"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE"
"\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE"
"\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3"
- "\025PINNED\026LOCAL\027BROADCAST\030MULTICAST\035STICKY";
+ "\024FIXEDMTU\025PINNED\026LOCAL\027BROADCAST\030MULTICAST\035STICKY";
static const char ifnetflags[] =
"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP"
"\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1"
Index: sys/net/if.c
===================================================================
--- sys/net/if.c
+++ sys/net/if.c
@@ -2526,6 +2526,7 @@
#ifdef INET6
nd6_setmtu(ifp);
#endif
+ rt_updatemtu(ifp);
}
break;
}
Index: sys/net/route.h
===================================================================
--- sys/net/route.h
+++ sys/net/route.h
@@ -151,7 +151,7 @@
/* 0x10000 unused, was RTF_PRCLONING */
/* 0x20000 unused, was RTF_WASCLONED */
#define RTF_PROTO3 0x40000 /* protocol specific routing flag */
-/* 0x80000 unused */
+#define RTF_FIXEDMTU 0x80000 /* MTU was explicitly specified */
#define RTF_PINNED 0x100000 /* route is immutable */
#define RTF_LOCAL 0x200000 /* route represents a local address */
#define RTF_BROADCAST 0x400000 /* route represents a bcast address */
@@ -378,6 +378,7 @@
int rt_expunge(struct radix_node_head *, struct rtentry *);
void rtfree(struct rtentry *);
int rt_check(struct rtentry **, struct rtentry **, struct sockaddr *);
+void rt_updatemtu(struct ifnet *);
/* XXX MRT COMPAT VERSIONS THAT SET UNIVERSE to 0 */
/* Thes are used by old code not yet converted to use multiple FIBS */
Index: sys/net/route.c
===================================================================
--- sys/net/route.c
+++ sys/net/route.c
@@ -141,6 +141,14 @@
struct rtentry **, u_int);
static void rt_setmetrics(const struct rt_addrinfo *, struct rtentry *);
+struct if_mtuinfo
+{
+ struct ifnet *ifp;
+ int mtu;
+};
+
+static int if_updatemtu_cb(struct radix_node *, void *);
+
/*
* handler for net.my_fibnum
*/
@@ -947,6 +955,55 @@
return (error);
}
+static int
+if_updatemtu_cb(struct radix_node *rn, void *arg)
+{
+ struct rtentry *rt;
+ struct if_mtuinfo *ifmtu;
+
+ rt = (struct rtentry *)rn;
+ ifmtu = (struct if_mtuinfo *)arg;
+
+
+ if (rt->rt_ifp != ifmtu->ifp)
+ return (0);
+
+ if (rt->rt_mtu != ifmtu->mtu && (rt->rt_flags & RTF_FIXEDMTU) == 0) {
+ /* We are safe to update route MTU */
+ rt->rt_mtu = ifmtu->mtu;
+ }
+
+ return (0);
+}
+
+void
+rt_updatemtu(struct ifnet *ifp)
+{
+ struct if_mtuinfo ifmtu;
+ struct radix_node_head *rnh;
+ int i, j;
+
+ ifmtu.ifp = ifp;
+
+ /*
+ * Try to update rt_mtu for all routes using this interface
+ * Unfortunately the only way to do this is to traverse all
+ * routing tables in all fibs/domains.
+ */
+ for (i = 1; i <= AF_MAX; i++) {
+ ifmtu.mtu = if_getmtu_family(ifp, i);
+ for (j = 0; j < rt_numfibs; j++) {
+ rnh = rt_tables_get_rnh(j, i);
+ if (rnh == NULL)
+ continue;
+ RADIX_NODE_HEAD_LOCK(rnh);
+ rnh->rnh_walktree(rnh, if_updatemtu_cb, &ifmtu);
+ RADIX_NODE_HEAD_UNLOCK(rnh);
+ }
+ }
+}
+
+
#if 0
int p_sockaddr(char *buf, int buflen, struct sockaddr *s);
int rt_print(char *buf, int buflen, struct rtentry *rt);
@@ -1482,7 +1539,7 @@
if (rt->rt_ifp != NULL) {
family = info->rti_info[RTAX_DST]->sa_family;
mtu = if_getmtu_family(rt->rt_ifp, family);
- if (rt->rt_mtu > mtu)
+ if (rt->rt_mtu == 0 || rt->rt_mtu > mtu)
rt->rt_mtu = mtu;
}
@@ -1501,8 +1558,24 @@
rt_setmetrics(const struct rt_addrinfo *info, struct rtentry *rt)
{
- if (info->rti_mflags & RTV_MTU)
- rt->rt_mtu = info->rti_rmx->rmx_mtu;
+ if (info->rti_mflags & RTV_MTU) {
+ if (info->rti_rmx->rmx_mtu != 0) {
+
+ /*
+ * MTU was explicitly provided by user.
+ * Keep it.
+ */
+ rt->rt_flags |= RTF_FIXEDMTU;
+ rt->rt_mtu = info->rti_rmx->rmx_mtu;
+ } else {
+
+ /*
+ * User explicitly sets MTU to 0.
+ * Assume rollback to default.
+ */
+ rt->rt_flags &= ~RTF_FIXEDMTU;
+ }
+ }
if (info->rti_mflags & RTV_WEIGHT)
rt->rt_weight = info->rti_rmx->rmx_weight;
/* Kernel -> userland timebase conversion. */
Index: sys/netinet/ip_output.c
===================================================================
--- sys/netinet/ip_output.c
+++ sys/netinet/ip_output.c
@@ -322,20 +322,10 @@
* Calculate MTU. If we have a route that is up, use that,
* otherwise use the interface's MTU.
*/
- if (rte != NULL && (rte->rt_flags & (RTF_UP|RTF_HOST))) {
- /*
- * This case can happen if the user changed the MTU
- * of an interface after enabling IP on it. Because
- * most netifs don't keep track of routes pointing to
- * them, there is no way for one to update all its
- * routes when the MTU is changed.
- */
- if (rte->rt_mtu > ifp->if_mtu)
- rte->rt_mtu = ifp->if_mtu;
+ if (rte != NULL && (rte->rt_flags & (RTF_UP|RTF_HOST)))
mtu = rte->rt_mtu;
- } else {
+ else
mtu = ifp->if_mtu;
- }
/* Catch a possible divide by zero later. */
KASSERT(mtu > 0, ("%s: mtu %d <= 0, rte=%p (rt_flags=0x%08x) ifp=%p",
__func__, mtu, rte, (rte != NULL) ? rte->rt_flags : 0, ifp));
Index: sys/netinet6/ip6_output.c
===================================================================
--- sys/netinet6/ip6_output.c
+++ sys/netinet6/ip6_output.c
@@ -1275,17 +1275,6 @@
*/
alwaysfrag = 1;
mtu = IPV6_MMTU;
- } else if (mtu > ifmtu) {
- /*
- * The MTU on the route is larger than the MTU on
- * the interface! This shouldn't happen, unless the
- * MTU of the interface has been changed after the
- * interface was brought up. Change the MTU in the
- * route to match the interface MTU (as long as the
- * field isn't locked).
- */
- mtu = ifmtu;
- ro_pmtu->ro_rt->rt_mtu = mtu;
}
} else if (ifp) {
mtu = IN6_LINKMTU(ifp);

File Metadata

Mime Type
text/plain
Expires
Sun, Apr 19, 12:31 PM (10 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31766866
Default Alt Text
D1125.diff (5 KB)

Event Timeline