]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
xfrm: Move dst->path into struct xfrm_dst
authorDavid Miller <davem@davemloft.net>
Tue, 28 Nov 2017 20:40:46 +0000 (15:40 -0500)
committerDavid S. Miller <davem@davemloft.net>
Thu, 30 Nov 2017 14:54:26 +0000 (09:54 -0500)
The first member of an IPSEC route bundle chain sets it's dst->path to
the underlying ipv4/ipv6 route that carries the bundle.

Stated another way, if one were to follow the xfrm_dst->child chain of
the bundle, the final non-NULL pointer would be the path and point to
either an ipv4 or an ipv6 route.

This is largely used to make sure that PMTU events propagate down to
the correct ipv4 or ipv6 route.

When we don't have the top of an IPSEC bundle 'dst->path == dst'.

Move it down into xfrm_dst and key off of dst->xfrm.

Signed-off-by: David S. Miller <davem@davemloft.net>
Reviewed-by: Eric Dumazet <edumazet@google.com>
include/net/dst.h
include/net/xfrm.h
net/bridge/br_nf_core.c
net/core/dst.c
net/ipv4/route.c
net/ipv6/ip6_output.c
net/ipv6/route.c
net/xfrm/xfrm_device.c
net/xfrm/xfrm_policy.c

index 13c839d8235ad75ecca1b0b2d7bda595cd3a03d4..424bff66f16d781b74bf480cea6c9aa96df80943 100644 (file)
@@ -38,7 +38,6 @@ struct dst_entry {
        struct  dst_ops         *ops;
        unsigned long           _metrics;
        unsigned long           expires;
-       struct dst_entry        *path;
 #ifdef CONFIG_XFRM
        struct xfrm_state       *xfrm;
 #else
@@ -87,7 +86,7 @@ struct dst_entry {
         * Align __refcnt to a 64 bytes alignment
         * (L1_CACHE_SIZE would be too much)
         */
-       long                    __pad_to_align_refcnt[4];
+       long                    __pad_to_align_refcnt[5];
 #endif
        /*
         * __refcnt wants to be on a different cache line from
index 0009dab615287dbfb79719c7d3c28436588c2dbe..1ec0c4760646d6242a93e4a13024ffb33a11ff06 100644 (file)
@@ -985,6 +985,7 @@ struct xfrm_dst {
        } u;
        struct dst_entry *route;
        struct dst_entry *child;
+       struct dst_entry *path;
        struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
        int num_pols, num_xfrms;
        u32 xfrm_genid;
@@ -995,6 +996,18 @@ struct xfrm_dst {
        u32 path_cookie;
 };
 
+static inline struct dst_entry *xfrm_dst_path(const struct dst_entry *dst)
+{
+#ifdef CONFIG_XFRM
+       if (dst->xfrm) {
+               const struct xfrm_dst *xdst = (const struct xfrm_dst *) dst;
+
+               return xdst->path;
+       }
+#endif
+       return (struct dst_entry *) dst;
+}
+
 static inline struct dst_entry *xfrm_dst_child(const struct dst_entry *dst)
 {
 #ifdef CONFIG_XFRM
@@ -1889,7 +1902,7 @@ static inline bool xfrm_dst_offload_ok(struct dst_entry *dst)
                return false;
 
        xdst = (struct xfrm_dst *) dst;
-       if (x->xso.offload_handle && (x->xso.dev == dst->path->dev) &&
+       if (x->xso.offload_handle && (x->xso.dev == xfrm_dst_path(dst)->dev) &&
            !xdst->child->xfrm)
                return true;
 
index 20cbb727df4d005db840e9940b85177ecb61eec3..8e2d7cfa4e166a32dac08b6abb968870588294a8 100644 (file)
@@ -78,7 +78,6 @@ void br_netfilter_rtable_init(struct net_bridge *br)
 
        atomic_set(&rt->dst.__refcnt, 1);
        rt->dst.dev = br->dev;
-       rt->dst.path = &rt->dst;
        dst_init_metrics(&rt->dst, br_dst_default_metrics, true);
        rt->dst.flags   = DST_NOXFRM | DST_FAKE_RTABLE;
        rt->dst.ops = &fake_dst_ops;
index cf2076c0eb220de98090534ee551333a792a08e8..9bc3bb6e94efadcfec279ab5e78651767a4c6853 100644 (file)
@@ -69,7 +69,6 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops,
        dst->ops = ops;
        dst_init_metrics(dst, dst_default_metrics.metrics, true);
        dst->expires = 0UL;
-       dst->path = dst;
 #ifdef CONFIG_XFRM
        dst->xfrm = NULL;
 #endif
index 43b69af242e18d640db1bff451d2ee229fc5e08f..f0ed031f3594b4954fe8cbbdbd5ceed200f933d2 100644 (file)
@@ -1106,7 +1106,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
                new = true;
        }
 
-       __ip_rt_update_pmtu((struct rtable *) rt->dst.path, &fl4, mtu);
+       __ip_rt_update_pmtu((struct rtable *) xfrm_dst_path(&rt->dst), &fl4, mtu);
 
        if (!dst_check(&rt->dst, 0)) {
                if (new)
index 5110a418cc4d0c1040506394460cb482698d8c15..176d74fb3b4d82223cd0cbd7b589ceca8c968c9e 100644 (file)
@@ -1201,13 +1201,13 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork,
                      rt->dst.dev->mtu : dst_mtu(&rt->dst);
        else
                mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ?
-                     rt->dst.dev->mtu : dst_mtu(rt->dst.path);
+                     rt->dst.dev->mtu : dst_mtu(xfrm_dst_path(&rt->dst));
        if (np->frag_size < mtu) {
                if (np->frag_size)
                        mtu = np->frag_size;
        }
        cork->base.fragsize = mtu;
-       if (dst_allfrag(rt->dst.path))
+       if (dst_allfrag(xfrm_dst_path(&rt->dst)))
                cork->base.flags |= IPCORK_ALLFRAG;
        cork->base.length = 0;
 
index 1f1ef1e071c2f5a1e3b0e7104280da9c2838ff80..46fd53b268dadfd1595b33468890903e2f357a46 100644 (file)
@@ -4596,8 +4596,6 @@ static int __net_init ip6_route_net_init(struct net *net)
                                           GFP_KERNEL);
        if (!net->ipv6.ip6_null_entry)
                goto out_ip6_dst_entries;
-       net->ipv6.ip6_null_entry->dst.path =
-               (struct dst_entry *)net->ipv6.ip6_null_entry;
        net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops;
        dst_init_metrics(&net->ipv6.ip6_null_entry->dst,
                         ip6_template_metrics, true);
@@ -4609,8 +4607,6 @@ static int __net_init ip6_route_net_init(struct net *net)
                                               GFP_KERNEL);
        if (!net->ipv6.ip6_prohibit_entry)
                goto out_ip6_null_entry;
-       net->ipv6.ip6_prohibit_entry->dst.path =
-               (struct dst_entry *)net->ipv6.ip6_prohibit_entry;
        net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops;
        dst_init_metrics(&net->ipv6.ip6_prohibit_entry->dst,
                         ip6_template_metrics, true);
@@ -4620,8 +4616,6 @@ static int __net_init ip6_route_net_init(struct net *net)
                                               GFP_KERNEL);
        if (!net->ipv6.ip6_blk_hole_entry)
                goto out_ip6_prohibit_entry;
-       net->ipv6.ip6_blk_hole_entry->dst.path =
-               (struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
        net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
        dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,
                         ip6_template_metrics, true);
index c5851ddddd2a48297a04bc0170a062e311f11cff..c61a7d46b412481348297cacc1e5d355446d7577 100644 (file)
@@ -120,7 +120,7 @@ bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
        if (!x->type_offload || x->encap)
                return false;
 
-       if ((x->xso.offload_handle && (dev == dst->path->dev)) &&
+       if ((x->xso.offload_handle && (dev == xfrm_dst_path(dst)->dev)) &&
             !xdst->child->xfrm && x->type->get_mtu) {
                mtu = x->type->get_mtu(x, xdst->child_mtu_cached);
 
index 58b3ecba2e41e4d77345c3f3e85e8b60048bf3b0..da1b41ee4686fb2408417e0134c66b5337dde859 100644 (file)
@@ -1626,7 +1626,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
        }
 
        xfrm_dst_set_child(xdst_prev, dst);
-       xdst0->u.dst.path = dst;
+       xdst0->path = dst;
 
        err = -ENODEV;
        dev = dst->dev;
@@ -1879,8 +1879,8 @@ static void xfrm_policy_queue_process(struct timer_list *t)
        xfrm_decode_session(skb, &fl, dst->ops->family);
        spin_unlock(&pq->hold_queue.lock);
 
-       dst_hold(dst->path);
-       dst = xfrm_lookup(net, dst->path, &fl, sk, 0);
+       dst_hold(xfrm_dst_path(dst));
+       dst = xfrm_lookup(net, xfrm_dst_path(dst), &fl, sk, 0);
        if (IS_ERR(dst))
                goto purge_queue;
 
@@ -1909,8 +1909,8 @@ static void xfrm_policy_queue_process(struct timer_list *t)
                skb = __skb_dequeue(&list);
 
                xfrm_decode_session(skb, &fl, skb_dst(skb)->ops->family);
-               dst_hold(skb_dst(skb)->path);
-               dst = xfrm_lookup(net, skb_dst(skb)->path, &fl, skb->sk, 0);
+               dst_hold(xfrm_dst_path(skb_dst(skb)));
+               dst = xfrm_lookup(net, xfrm_dst_path(skb_dst(skb)), &fl, skb->sk, 0);
                if (IS_ERR(dst)) {
                        kfree_skb(skb);
                        continue;
@@ -2012,7 +2012,7 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net,
 
        dst_hold(dst);
        xfrm_dst_set_child(xdst, dst);
-       dst1->path = dst;
+       xdst->path = dst;
 
        xfrm_init_path((struct xfrm_dst *)dst1, dst, 0);
 
@@ -2630,7 +2630,7 @@ static int xfrm_bundle_ok(struct xfrm_dst *first)
        struct xfrm_dst *last;
        u32 mtu;
 
-       if (!dst_check(dst->path, ((struct xfrm_dst *)dst)->path_cookie) ||
+       if (!dst_check(xfrm_dst_path(dst), ((struct xfrm_dst *)dst)->path_cookie) ||
            (dst->dev && !netif_running(dst->dev)))
                return 0;
 
@@ -2691,22 +2691,20 @@ static int xfrm_bundle_ok(struct xfrm_dst *first)
 
 static unsigned int xfrm_default_advmss(const struct dst_entry *dst)
 {
-       return dst_metric_advmss(dst->path);
+       return dst_metric_advmss(xfrm_dst_path(dst));
 }
 
 static unsigned int xfrm_mtu(const struct dst_entry *dst)
 {
        unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
 
-       return mtu ? : dst_mtu(dst->path);
+       return mtu ? : dst_mtu(xfrm_dst_path(dst));
 }
 
 static const void *xfrm_get_dst_nexthop(const struct dst_entry *dst,
                                        const void *daddr)
 {
-       const struct dst_entry *path = dst->path;
-
-       for (; dst != path; dst = xfrm_dst_child(dst)) {
+       while (dst->xfrm) {
                const struct xfrm_state *xfrm = dst->xfrm;
 
                if (xfrm->props.mode == XFRM_MODE_TRANSPORT)
@@ -2715,6 +2713,8 @@ static const void *xfrm_get_dst_nexthop(const struct dst_entry *dst,
                        daddr = xfrm->coaddr;
                else if (!(xfrm->type->flags & XFRM_TYPE_LOCAL_COADDR))
                        daddr = &xfrm->id.daddr;
+
+               dst = xfrm_dst_child(dst);
        }
        return daddr;
 }
@@ -2723,7 +2723,7 @@ static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst,
                                           struct sk_buff *skb,
                                           const void *daddr)
 {
-       const struct dst_entry *path = dst->path;
+       const struct dst_entry *path = xfrm_dst_path(dst);
 
        if (!skb)
                daddr = xfrm_get_dst_nexthop(dst, daddr);
@@ -2732,7 +2732,7 @@ static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst,
 
 static void xfrm_confirm_neigh(const struct dst_entry *dst, const void *daddr)
 {
-       const struct dst_entry *path = dst->path;
+       const struct dst_entry *path = xfrm_dst_path(dst);
 
        daddr = xfrm_get_dst_nexthop(dst, daddr);
        path->ops->confirm_neigh(path, daddr);