Commit e58c2548 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller

[IPSEC]: Store MTU at each xfrm_dst

Finally this is the patch that sets the MTU values of each xfrm_dst
and keeps it up-to-date.

To recap, at this point we've obtained accurate MTU values at each
xfrm_dst.  The next step would be to start using it as
dst_pmtu(xfrm_dst).
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1ffd2743
......@@ -512,6 +512,8 @@ struct xfrm_dst
struct rt6_info rt6;
} u;
struct dst_entry *route;
u32 route_mtu_cached;
u32 child_mtu_cached;
};
/* Decapsulation state, used by the input to store data during
......@@ -860,6 +862,7 @@ extern void xfrm_policy_flush(void);
extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
extern int xfrm_flush_bundles(void);
extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family);
extern void xfrm_init_pmtu(struct dst_entry *dst);
extern wait_queue_head_t km_waitq;
extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
......
......@@ -153,6 +153,8 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
header_len -= x->u.dst.xfrm->props.header_len;
trailer_len -= x->u.dst.xfrm->props.trailer_len;
}
xfrm_init_pmtu(dst);
return 0;
error:
......
......@@ -167,6 +167,8 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
header_len -= x->u.dst.xfrm->props.header_len;
trailer_len -= x->u.dst.xfrm->props.trailer_len;
}
xfrm_init_pmtu(dst);
return 0;
error:
......
......@@ -1115,26 +1115,87 @@ int xfrm_flush_bundles(void)
return 0;
}
void xfrm_init_pmtu(struct dst_entry *dst)
{
do {
struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
u32 pmtu, route_mtu_cached;
pmtu = dst_pmtu(dst->child);
xdst->child_mtu_cached = pmtu;
pmtu = xfrm_state_mtu(dst->xfrm, pmtu);
route_mtu_cached = dst_pmtu(xdst->route);
xdst->route_mtu_cached = route_mtu_cached;
if (pmtu > route_mtu_cached)
pmtu = route_mtu_cached;
dst->metrics[RTAX_MTU-1] = pmtu;
} while ((dst = dst->next));
}
EXPORT_SYMBOL(xfrm_init_pmtu);
/* Check that the bundle accepts the flow and its components are
* still valid.
*/
int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family)
int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family)
{
struct dst_entry *dst = &xdst->u.dst;
struct dst_entry *dst = &first->u.dst;
struct xfrm_dst *last;
u32 mtu;
if (dst->path->obsolete > 0 ||
(dst->dev && !netif_running(dst->dev)))
return 0;
last = NULL;
do {
struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family))
return 0;
if (dst->xfrm->km.state != XFRM_STATE_VALID)
return 0;
mtu = dst_pmtu(dst->child);
if (xdst->child_mtu_cached != mtu) {
last = xdst;
xdst->child_mtu_cached = mtu;
}
mtu = dst_pmtu(xdst->route);
if (xdst->route_mtu_cached != mtu) {
last = xdst;
xdst->route_mtu_cached = mtu;
}
dst = dst->child;
} while (dst->xfrm);
if (likely(!last))
return 1;
mtu = last->child_mtu_cached;
for (;;) {
dst = &last->u.dst;
mtu = xfrm_state_mtu(dst->xfrm, mtu);
if (mtu > last->route_mtu_cached)
mtu = last->route_mtu_cached;
dst->metrics[RTAX_MTU-1] = mtu;
if (last == first)
break;
last = last->u.next;
last->child_mtu_cached = mtu;
}
return 1;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment