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 ...@@ -512,6 +512,8 @@ struct xfrm_dst
struct rt6_info rt6; struct rt6_info rt6;
} u; } u;
struct dst_entry *route; struct dst_entry *route;
u32 route_mtu_cached;
u32 child_mtu_cached;
}; };
/* Decapsulation state, used by the input to store data during /* Decapsulation state, used by the input to store data during
...@@ -860,6 +862,7 @@ extern void xfrm_policy_flush(void); ...@@ -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_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
extern int xfrm_flush_bundles(void); extern int xfrm_flush_bundles(void);
extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family); 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 wait_queue_head_t km_waitq;
extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); 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 ...@@ -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; header_len -= x->u.dst.xfrm->props.header_len;
trailer_len -= x->u.dst.xfrm->props.trailer_len; trailer_len -= x->u.dst.xfrm->props.trailer_len;
} }
xfrm_init_pmtu(dst);
return 0; return 0;
error: error:
......
...@@ -167,6 +167,8 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int ...@@ -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; header_len -= x->u.dst.xfrm->props.header_len;
trailer_len -= x->u.dst.xfrm->props.trailer_len; trailer_len -= x->u.dst.xfrm->props.trailer_len;
} }
xfrm_init_pmtu(dst);
return 0; return 0;
error: error:
......
...@@ -1115,26 +1115,87 @@ int xfrm_flush_bundles(void) ...@@ -1115,26 +1115,87 @@ int xfrm_flush_bundles(void)
return 0; 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 /* Check that the bundle accepts the flow and its components are
* still valid. * 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 || if (dst->path->obsolete > 0 ||
(dst->dev && !netif_running(dst->dev))) (dst->dev && !netif_running(dst->dev)))
return 0; return 0;
last = NULL;
do { do {
struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family)) if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family))
return 0; return 0;
if (dst->xfrm->km.state != XFRM_STATE_VALID) if (dst->xfrm->km.state != XFRM_STATE_VALID)
return 0; 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; dst = dst->child;
} while (dst->xfrm); } 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; 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