svn commit: r274175 - in head/sys: net netinet netinet6 sys
Alexander V. Chernikov
melifaro at FreeBSD.org
Thu Nov 6 13:13:13 UTC 2014
Author: melifaro
Date: Thu Nov 6 13:13:09 2014
New Revision: 274175
URL: https://svnweb.freebsd.org/changeset/base/274175
Log:
Make checks for rt_mtu generic:
Some virtual if drivers has (ab)used ifa ifa_rtrequest hook to enforce
route MTU to be not bigger that interface MTU. While ifa_rtrequest hooking
might be an option in some situation, it is not feasible to do MTU checks
there: generic (or per-domain) routing code is perfectly capable of doing
this.
We currrently have 3 places where MTU is altered:
1) route addition.
In this case domain overrides radix _addroute callback (in[6]_addroute)
and all necessary checks/fixes are/can be done there.
2) route change (especially, GW change).
In this case, there are no explicit per-domain calls, but one can
override rte by setting ifa_rtrequest hook to domain handler
(inet6 does this).
3) ifconfig ifaceX mtu YYYY
In this case, we have no callbacks, but ip[6]_output performes runtime
checks and decreases rt_mtu if necessary.
Generally, the goals are to be able to handle all MTU changes in
control plane, not in runtime part, and properly deal with increased
interface MTU.
This commit changes the following:
* removes hooks setting MTU from drivers side
* adds proper per-doman MTU checks for case 1)
* adds generic MTU check for case 2)
* The latter is done by using new dom_ifmtu callback since
if_mtu denotes L3 interface MTU, e.g. maximum trasmitted _packet_ size.
However, IPv6 mtu might be different from if_mtu one (e.g. default 1280)
for some cases, so we need an abstract way to know maximum MTU size
for given interface and domain.
* moves rt_setmetrics() before MTU/ifa_rtrequest hooks since it copies
user-supplied data which must be checked.
* removes RT_LOCK_ASSERT() from other ifa_rtrequest hooks to be able to
use this functions on new non-inserted rte.
More changes will follow soon.
MFC after: 1 month
Sponsored by: Yandex LLC
Modified:
head/sys/net/if.c
head/sys/net/if_disc.c
head/sys/net/if_faith.c
head/sys/net/if_loop.c
head/sys/net/if_stf.c
head/sys/net/if_var.h
head/sys/net/route.c
head/sys/netinet/in_rmx.c
head/sys/netinet6/in6.c
head/sys/netinet6/in6_proto.c
head/sys/netinet6/in6_rmx.c
head/sys/netinet6/in6_var.h
head/sys/netinet6/nd6.c
head/sys/sys/domain.h
Modified: head/sys/net/if.c
==============================================================================
--- head/sys/net/if.c Thu Nov 6 13:12:12 2014 (r274174)
+++ head/sys/net/if.c Thu Nov 6 13:13:09 2014 (r274175)
@@ -2009,8 +2009,6 @@ link_rtrequest(int cmd, struct rtentry *
struct sockaddr *dst;
struct ifnet *ifp;
- RT_LOCK_ASSERT(rt);
-
if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
return;
@@ -3759,6 +3757,19 @@ if_getmtu(if_t ifp)
}
int
+if_getmtu_family(if_t ifp, int family)
+{
+ struct domain *dp;
+
+ for (dp = domains; dp; dp = dp->dom_next) {
+ if (dp->dom_family == family && dp->dom_ifmtu != NULL)
+ return (dp->dom_ifmtu((struct ifnet *)ifp));
+ }
+
+ return (((struct ifnet *)ifp)->if_mtu);
+}
+
+int
if_setsoftc(if_t ifp, void *softc)
{
((struct ifnet *)ifp)->if_softc = softc;
Modified: head/sys/net/if_disc.c
==============================================================================
--- head/sys/net/if_disc.c Thu Nov 6 13:12:12 2014 (r274174)
+++ head/sys/net/if_disc.c Thu Nov 6 13:13:09 2014 (r274175)
@@ -67,7 +67,6 @@ struct disc_softc {
static int discoutput(struct ifnet *, struct mbuf *,
const struct sockaddr *, struct route *);
-static void discrtrequest(int, struct rtentry *, struct rt_addrinfo *);
static int discioctl(struct ifnet *, u_long, caddr_t);
static int disc_clone_create(struct if_clone *, int, caddr_t);
static void disc_clone_destroy(struct ifnet *);
@@ -198,31 +197,19 @@ discoutput(struct ifnet *ifp, struct mbu
return (0);
}
-/* ARGSUSED */
-static void
-discrtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info)
-{
-
- RT_LOCK_ASSERT(rt);
- rt->rt_mtu = DSMTU;
-}
-
/*
* Process an ioctl request.
*/
static int
discioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct ifaddr *ifa;
struct ifreq *ifr = (struct ifreq *)data;
int error = 0;
switch (cmd) {
case SIOCSIFADDR:
ifp->if_flags |= IFF_UP;
- ifa = (struct ifaddr *)data;
- if (ifa != 0)
- ifa->ifa_rtrequest = discrtrequest;
+
/*
* Everything else is done at a higher level.
*/
Modified: head/sys/net/if_faith.c
==============================================================================
--- head/sys/net/if_faith.c Thu Nov 6 13:12:12 2014 (r274174)
+++ head/sys/net/if_faith.c Thu Nov 6 13:13:09 2014 (r274175)
@@ -87,7 +87,6 @@ struct faith_softc {
static int faithioctl(struct ifnet *, u_long, caddr_t);
static int faithoutput(struct ifnet *, struct mbuf *, const struct sockaddr *,
struct route *);
-static void faithrtrequest(int, struct rtentry *, struct rt_addrinfo *);
#ifdef INET6
static int faithprefix(struct in6_addr *);
#endif
@@ -238,17 +237,6 @@ faithoutput(struct ifnet *ifp, struct mb
return (0);
}
-/* ARGSUSED */
-static void
-faithrtrequest(cmd, rt, info)
- int cmd;
- struct rtentry *rt;
- struct rt_addrinfo *info;
-{
- RT_LOCK_ASSERT(rt);
- rt->rt_mtu = rt->rt_ifp->if_mtu;
-}
-
/*
* Process an ioctl request.
*/
@@ -259,7 +247,6 @@ faithioctl(ifp, cmd, data)
u_long cmd;
caddr_t data;
{
- struct ifaddr *ifa;
struct ifreq *ifr = (struct ifreq *)data;
int error = 0;
@@ -268,8 +255,7 @@ faithioctl(ifp, cmd, data)
case SIOCSIFADDR:
ifp->if_flags |= IFF_UP;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
- ifa = (struct ifaddr *)data;
- ifa->ifa_rtrequest = faithrtrequest;
+
/*
* Everything else is done at a higher level.
*/
Modified: head/sys/net/if_loop.c
==============================================================================
--- head/sys/net/if_loop.c Thu Nov 6 13:12:12 2014 (r274174)
+++ head/sys/net/if_loop.c Thu Nov 6 13:13:09 2014 (r274175)
@@ -88,7 +88,6 @@
CSUM_SCTP_VALID)
int loioctl(struct ifnet *, u_long, caddr_t);
-static void lortrequest(int, struct rtentry *, struct rt_addrinfo *);
int looutput(struct ifnet *ifp, struct mbuf *m,
const struct sockaddr *dst, struct route *ro);
static int lo_clone_create(struct if_clone *, int, caddr_t);
@@ -364,15 +363,6 @@ if_simloop(struct ifnet *ifp, struct mbu
return (0);
}
-/* ARGSUSED */
-static void
-lortrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info)
-{
-
- RT_LOCK_ASSERT(rt);
- rt->rt_mtu = rt->rt_ifp->if_mtu;
-}
-
/*
* Process an ioctl request.
*/
@@ -380,7 +370,6 @@ lortrequest(int cmd, struct rtentry *rt,
int
loioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct ifaddr *ifa;
struct ifreq *ifr = (struct ifreq *)data;
int error = 0, mask;
@@ -388,8 +377,6 @@ loioctl(struct ifnet *ifp, u_long cmd, c
case SIOCSIFADDR:
ifp->if_flags |= IFF_UP;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
- ifa = (struct ifaddr *)data;
- ifa->ifa_rtrequest = lortrequest;
/*
* Everything else is done at a higher level.
*/
Modified: head/sys/net/if_stf.c
==============================================================================
--- head/sys/net/if_stf.c Thu Nov 6 13:12:12 2014 (r274174)
+++ head/sys/net/if_stf.c Thu Nov 6 13:13:09 2014 (r274175)
@@ -179,7 +179,6 @@ static int stf_checkaddr4(struct stf_sof
struct ifnet *);
static int stf_checkaddr6(struct stf_softc *, struct in6_addr *,
struct ifnet *);
-static void stf_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
static int stf_ioctl(struct ifnet *, u_long, caddr_t);
static int stf_clone_match(struct if_clone *, const char *);
@@ -722,17 +721,6 @@ in_stf_input(struct mbuf **mp, int *offp
return (IPPROTO_DONE);
}
-/* ARGSUSED */
-static void
-stf_rtrequest(cmd, rt, info)
- int cmd;
- struct rtentry *rt;
- struct rt_addrinfo *info;
-{
- RT_LOCK_ASSERT(rt);
- rt->rt_mtu = rt->rt_ifp->if_mtu;
-}
-
static int
stf_ioctl(ifp, cmd, data)
struct ifnet *ifp;
@@ -764,7 +752,6 @@ stf_ioctl(ifp, cmd, data)
break;
}
- ifa->ifa_rtrequest = stf_rtrequest;
ifp->if_flags |= IFF_UP;
break;
Modified: head/sys/net/if_var.h
==============================================================================
--- head/sys/net/if_var.h Thu Nov 6 13:12:12 2014 (r274174)
+++ head/sys/net/if_var.h Thu Nov 6 13:13:09 2014 (r274175)
@@ -556,6 +556,7 @@ void *if_getsoftc(if_t ifp);
int if_setflags(if_t ifp, int flags);
int if_setmtu(if_t ifp, int mtu);
int if_getmtu(if_t ifp);
+int if_getmtu_family(if_t ifp, int family);
int if_setflagbits(if_t ifp, int set, int clear);
int if_getflags(if_t ifp);
int if_sendq_empty(if_t ifp);
Modified: head/sys/net/route.c
==============================================================================
--- head/sys/net/route.c Thu Nov 6 13:12:12 2014 (r274174)
+++ head/sys/net/route.c Thu Nov 6 13:13:09 2014 (r274175)
@@ -1279,6 +1279,8 @@ rtrequest1_fib(int req, struct rt_addrin
rt->rt_ifp = ifa->ifa_ifp;
rt->rt_weight = 1;
+ rt_setmetrics(info, rt);
+
#ifdef RADIX_MPATH
/* do not permit exactly the same dst/mask/gw pair */
if (rn_mpath_capable(rnh) &&
@@ -1373,8 +1375,6 @@ rtrequest1_fib(int req, struct rt_addrin
if (ifa->ifa_rtrequest)
ifa->ifa_rtrequest(req, rt, info);
- rt_setmetrics(info, rt);
-
/*
* actually return a resultant rtentry and
* give the caller a single reference.
@@ -1412,6 +1412,7 @@ rtrequest1_fib_change(struct radix_node_
struct rtentry *rt = NULL;
int error = 0;
int free_ifa = 0;
+ int family, mtu;
rt = (struct rtentry *)rnh->rnh_lookup(info->rti_info[RTAX_DST],
info->rti_info[RTAX_NETMASK], rnh);
@@ -1433,6 +1434,8 @@ rtrequest1_fib_change(struct radix_node_
RT_LOCK(rt);
+ rt_setmetrics(info, rt);
+
/*
* New gateway could require new ifaddr, ifp;
* flags may also be different; ifp may be specified
@@ -1480,7 +1483,13 @@ rtrequest1_fib_change(struct radix_node_
if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest != NULL)
rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, info);
- rt_setmetrics(info, rt);
+ /* Ensure route MTU is not bigger than interface MTU */
+ 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)
+ rt->rt_mtu = mtu;
+ }
if (ret_nrt) {
*ret_nrt = rt;
Modified: head/sys/netinet/in_rmx.c
==============================================================================
--- head/sys/netinet/in_rmx.c Thu Nov 6 13:12:12 2014 (r274174)
+++ head/sys/netinet/in_rmx.c Thu Nov 6 13:13:09 2014 (r274175)
@@ -94,8 +94,18 @@ in_addroute(void *v_arg, void *n_arg, st
if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
rt->rt_flags |= RTF_MULTICAST;
- if (rt->rt_mtu == 0 && rt->rt_ifp != NULL)
- rt->rt_mtu = rt->rt_ifp->if_mtu;
+ if (rt->rt_ifp != NULL) {
+
+ /*
+ * Check route MTU:
+ * inherit interface MTU if not set or
+ * check if MTU is too large.
+ */
+ if (rt->rt_mtu == 0) {
+ rt->rt_mtu = rt->rt_ifp->if_mtu;
+ } else if (rt->rt_mtu > rt->rt_ifp->if_mtu)
+ rt->rt_mtu = rt->rt_ifp->if_mtu;
+ }
return (rn_addroute(v_arg, n_arg, head, treenodes));
}
Modified: head/sys/netinet6/in6.c
==============================================================================
--- head/sys/netinet6/in6.c Thu Nov 6 13:12:12 2014 (r274174)
+++ head/sys/netinet6/in6.c Thu Nov 6 13:13:09 2014 (r274175)
@@ -2367,6 +2367,13 @@ in6_domifattach(struct ifnet *ifp)
return ext;
}
+int
+in6_domifmtu(struct ifnet *ifp)
+{
+
+ return (IN6_LINKMTU(ifp));
+}
+
void
in6_domifdetach(struct ifnet *ifp, void *aux)
{
Modified: head/sys/netinet6/in6_proto.c
==============================================================================
--- head/sys/netinet6/in6_proto.c Thu Nov 6 13:12:12 2014 (r274174)
+++ head/sys/netinet6/in6_proto.c Thu Nov 6 13:13:09 2014 (r274175)
@@ -382,7 +382,8 @@ struct domain inet6domain = {
.dom_rtoffset = offsetof(struct sockaddr_in6, sin6_addr) << 3,
.dom_maxrtkey = sizeof(struct sockaddr_in6),
.dom_ifattach = in6_domifattach,
- .dom_ifdetach = in6_domifdetach
+ .dom_ifdetach = in6_domifdetach,
+ .dom_ifmtu = in6_domifmtu
};
VNET_DOMAIN_SET(inet6);
Modified: head/sys/netinet6/in6_rmx.c
==============================================================================
--- head/sys/netinet6/in6_rmx.c Thu Nov 6 13:12:12 2014 (r274174)
+++ head/sys/netinet6/in6_rmx.c Thu Nov 6 13:13:09 2014 (r274175)
@@ -136,8 +136,18 @@ in6_addroute(void *v_arg, void *n_arg, s
}
}
- if (!rt->rt_mtu && rt->rt_ifp)
- rt->rt_mtu = IN6_LINKMTU(rt->rt_ifp);
+ if (rt->rt_ifp != NULL) {
+
+ /*
+ * Check route MTU:
+ * inherit interface MTU if not set or
+ * check if MTU is too large.
+ */
+ if (rt->rt_mtu == 0) {
+ rt->rt_mtu = IN6_LINKMTU(rt->rt_ifp);
+ } else if (rt->rt_mtu > IN6_LINKMTU(rt->rt_ifp))
+ rt->rt_mtu = IN6_LINKMTU(rt->rt_ifp);
+ }
ret = rn_addroute(v_arg, n_arg, head, treenodes);
if (ret == NULL) {
Modified: head/sys/netinet6/in6_var.h
==============================================================================
--- head/sys/netinet6/in6_var.h Thu Nov 6 13:12:12 2014 (r274174)
+++ head/sys/netinet6/in6_var.h Thu Nov 6 13:13:09 2014 (r274175)
@@ -807,6 +807,7 @@ int in6if_do_dad(struct ifnet *);
void in6_savemkludge(struct in6_ifaddr *);
void *in6_domifattach(struct ifnet *);
void in6_domifdetach(struct ifnet *, void *);
+int in6_domifmtu(struct ifnet *);
void in6_setmaxmtu(void);
int in6_if2idlen(struct ifnet *);
struct in6_ifaddr *in6ifa_ifpforlinklocal(struct ifnet *, int);
Modified: head/sys/netinet6/nd6.c
==============================================================================
--- head/sys/netinet6/nd6.c Thu Nov 6 13:12:12 2014 (r274174)
+++ head/sys/netinet6/nd6.c Thu Nov 6 13:13:09 2014 (r274175)
@@ -1188,7 +1188,6 @@ nd6_rtrequest(int req, struct rtentry *r
struct nd_defrouter *dr;
struct ifnet *ifp;
- RT_LOCK_ASSERT(rt);
gateway = (struct sockaddr_in6 *)rt->rt_gateway;
ifp = rt->rt_ifp;
Modified: head/sys/sys/domain.h
==============================================================================
--- head/sys/sys/domain.h Thu Nov 6 13:12:12 2014 (r274174)
+++ head/sys/sys/domain.h Thu Nov 6 13:13:09 2014 (r274175)
@@ -64,6 +64,7 @@ struct domain {
int dom_maxrtkey; /* for routing layer */
void *(*dom_ifattach)(struct ifnet *);
void (*dom_ifdetach)(struct ifnet *, void *);
+ int (*dom_ifmtu)(struct ifnet *);
/* af-dependent data on ifnet */
};
More information about the svn-src-head
mailing list