unsigned int mtu;
 
        if (np && READ_ONCE(np->pmtudisc) >= IPV6_PMTUDISC_PROBE) {
-               mtu = READ_ONCE(dst->dev->mtu);
+               mtu = READ_ONCE(dst_dev(dst)->mtu);
                mtu -= lwtunnel_headroom(dst->lwtstate, mtu);
        } else {
                mtu = dst_mtu(dst);
 
        mtu = IPV6_MIN_MTU;
        rcu_read_lock();
-       idev = __in6_dev_get(dst->dev);
+       idev = __in6_dev_get(dst_dev(dst));
        if (idev)
                mtu = READ_ONCE(idev->cnf.mtu6);
        rcu_read_unlock();
 
        if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
            !pskb_may_pull(skb, (skb_transport_offset(skb) +
                                 ((skb_transport_header(skb)[1] + 1) << 3)))) {
-               __IP6_INC_STATS(dev_net(dst->dev), idev,
+               __IP6_INC_STATS(dev_net(dst_dev(dst)), idev,
                                IPSTATS_MIB_INHDRERRORS);
 fail_and_free:
                kfree_skb(skb);
 
                               struct flowi6 *fl6, bool apply_ratelimit)
 {
        struct net *net = sock_net(sk);
+       struct net_device *dev;
        struct dst_entry *dst;
        bool res = false;
 
         * this lookup should be more aggressive (not longer than timeout).
         */
        dst = ip6_route_output(net, sk, fl6);
+       dev = dst_dev(dst);
        if (dst->error) {
                IP6_INC_STATS(net, ip6_dst_idev(dst),
                              IPSTATS_MIB_OUTNOROUTES);
-       } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) {
+       } else if (dev && (dev->flags & IFF_LOOPBACK)) {
                res = true;
        } else {
                struct rt6_info *rt = dst_rt6_info(dst);
 
                 */
 
                memset(&fl6, 0, sizeof(fl6));
-               fl6.flowi6_oif = orig_dst->dev->ifindex;
+               fl6.flowi6_oif = dst_dev(orig_dst)->ifindex;
                fl6.flowi6_iif = LOOPBACK_IFINDEX;
                fl6.daddr = *rt6_nexthop(dst_rt6_info(orig_dst),
                                         &ip6h->daddr);
 
        if (has_tunsrc)
                memcpy(&hdr->saddr, tunsrc, sizeof(*tunsrc));
        else
-               ipv6_dev_get_saddr(net, dst->dev, &hdr->daddr,
+               ipv6_dev_get_saddr(net, dst_dev(dst), &hdr->daddr,
                                   IPV6_PREFER_SRC_PUBLIC, &hdr->saddr);
 
        skb_postpush_rcsum(skb, hdr, len);
                        dst_cache_set_ip6(&ilwt->cache, dst, &fl6.saddr);
                local_bh_enable();
 
-               err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
+               err = skb_cow_head(skb, LL_RESERVED_SPACE(dst_dev(dst)));
                if (unlikely(err))
                        goto drop;
        }
 
                         htonl(atomic_fetch_inc(&t->o_seqno)));
 
        /* TooBig packet may have updated dst->dev's mtu */
-       if (!t->parms.collect_md && dst && dst_mtu(dst) > dst->dev->mtu)
-               dst->ops->update_pmtu(dst, NULL, skb, dst->dev->mtu, false);
-
+       if (!t->parms.collect_md && dst) {
+               mtu = READ_ONCE(dst_dev(dst)->mtu);
+               if (dst_mtu(dst) > mtu)
+                       dst->ops->update_pmtu(dst, NULL, skb, mtu, false);
+       }
        err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
                           NEXTHDR_GRE);
        if (err != 0) {
 
 static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
        struct dst_entry *dst = skb_dst(skb);
-       struct net_device *dev = dst->dev;
+       struct net_device *dev = dst_dev(dst);
        struct inet6_dev *idev = ip6_dst_idev(dst);
        unsigned int hh_len = LL_RESERVED_SPACE(dev);
        const struct in6_addr *daddr, *nexthop;
        const struct ipv6_pinfo *np = inet6_sk(sk);
        struct in6_addr *first_hop = &fl6->daddr;
        struct dst_entry *dst = skb_dst(skb);
-       struct net_device *dev = dst->dev;
+       struct net_device *dev = dst_dev(dst);
        struct inet6_dev *idev = ip6_dst_idev(dst);
        struct hop_jumbo_hdr *hop_jumbo;
        int hoplen = sizeof(*hop_jumbo);
        struct dst_entry *dst = skb_dst(skb);
        struct ipv6hdr *hdr = ipv6_hdr(skb);
        struct inet6_skb_parm *opt = IP6CB(skb);
-       struct net *net = dev_net(dst->dev);
+       struct net *net = dev_net(dst_dev(dst));
+       struct net_device *dev;
        struct inet6_dev *idev;
        SKB_DR(reason);
        u32 mtu;
                goto drop;
        }
        dst = skb_dst(skb);
-
+       dev = dst_dev(dst);
        /* IPv6 specs say nothing about it, but it is clear that we cannot
           send redirects to source routed frames.
           We don't send redirects to frames decapsulated from IPsec.
         */
-       if (IP6CB(skb)->iif == dst->dev->ifindex &&
+       if (IP6CB(skb)->iif == dev->ifindex &&
            opt->srcrt == 0 && !skb_sec_path(skb)) {
                struct in6_addr *target = NULL;
                struct inet_peer *peer;
 
        if (ip6_pkt_too_big(skb, mtu)) {
                /* Again, force OUTPUT device used as source address */
-               skb->dev = dst->dev;
+               skb->dev = dev;
                icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                __IP6_INC_STATS(net, idev, IPSTATS_MIB_INTOOBIGERRORS);
                __IP6_INC_STATS(net, ip6_dst_idev(dst),
                return -EMSGSIZE;
        }
 
-       if (skb_cow(skb, dst->dev->hard_header_len)) {
+       if (skb_cow(skb, dev->hard_header_len)) {
                __IP6_INC_STATS(net, ip6_dst_idev(dst),
                                IPSTATS_MIB_OUTDISCARDS);
                goto drop;
        hdr->hop_limit--;
 
        return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD,
-                      net, NULL, skb, skb->dev, dst->dev,
+                      net, NULL, skb, skb->dev, dev,
                       ip6_forward_finish);
 
 error:
 #ifdef CONFIG_IPV6_SUBTREES
            ip6_rt_check(&rt->rt6i_src, &fl6->saddr, np->saddr_cache) ||
 #endif
-          (fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex)) {
+          (fl6->flowi6_oif && fl6->flowi6_oif != dst_dev(dst)->ifindex)) {
                dst_release(dst);
                dst = NULL;
        }
 
                ndst = dst;
        }
 
-       tdev = dst->dev;
+       tdev = dst_dev(dst);
 
        if (tdev == dev) {
                DEV_STATS_INC(dev, collisions);
        /* Calculate max headroom for all the headers and adjust
         * needed_headroom if necessary.
         */
-       max_headroom = LL_RESERVED_SPACE(dst->dev) + sizeof(struct ipv6hdr)
+       max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct ipv6hdr)
                        + dst->header_len + t->hlen;
        if (max_headroom > READ_ONCE(dev->needed_headroom))
                WRITE_ONCE(dev->needed_headroom, max_headroom);
 
                netdev_dbg(dev, "no route to %pI6\n", &fl6.daddr);
                return ERR_PTR(-ENETUNREACH);
        }
-       if (dst->dev == dev) { /* is this necessary? */
+       if (dst_dev(dst) == dev) { /* is this necessary? */
                netdev_dbg(dev, "circular route to %pI6\n", &fl6.daddr);
                dst_release(dst);
                return ERR_PTR(-ELOOP);
 
                              (const struct in6_addr *)&x->id.daddr))
                goto tx_err_link_failure;
 
-       tdev = dst->dev;
+       tdev = dst_dev(dst);
 
        if (tdev == dev) {
                DEV_STATS_INC(dev, collisions);
 
 {
        struct icmp6hdr *icmp6h = icmp6_hdr(skb);
        struct dst_entry *dst = skb_dst(skb);
+       struct net_device *dev;
        struct inet6_dev *idev;
        struct net *net;
        struct sock *sk;
 
        ip6_nd_hdr(skb, saddr, daddr, READ_ONCE(inet6_sk(sk)->hop_limit), skb->len);
 
-       idev = __in6_dev_get(dst->dev);
+       dev = dst_dev(dst);
+       idev = __in6_dev_get(dev);
        IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
 
        err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
-                     net, sk, skb, NULL, dst->dev,
+                     net, sk, skb, NULL, dev,
                      dst_output);
        if (!err) {
                ICMP6MSGOUT_INC_STATS(net, idev, type);
 
        }
        skb_dst_drop(skb);
        skb_dst_set(skb, dst);
-       skb->dev      = dst->dev;
+       skb->dev      = dst_dev(dst);
        skb->protocol = htons(ETH_P_IPV6);
 
        return true;
 
 {
        int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT);
        if (hoplimit == 0) {
-               struct net_device *dev = dst->dev;
+               struct net_device *dev = dst_dev(dst);
                struct inet6_dev *idev;
 
                rcu_read_lock();
 
        const struct rt6_info *rt = dst_rt6_info(dst);
 
        return ip6_neigh_lookup(rt6_nexthop(rt, &in6addr_any),
-                               dst->dev, skb, daddr);
+                               dst_dev(dst), skb, daddr);
 }
 
 static void ip6_confirm_neigh(const struct dst_entry *dst, const void *daddr)
 {
        const struct rt6_info *rt = dst_rt6_info(dst);
-       struct net_device *dev = dst->dev;
+       struct net_device *dev = dst_dev(dst);
 
        daddr = choose_neigh_daddr(rt6_nexthop(rt, &in6addr_any), NULL, daddr);
        if (!daddr)
 
                if (res.f6i->nh) {
                        struct fib6_nh_match_arg arg = {
-                               .dev = dst->dev,
+                               .dev = dst_dev(dst),
                                .gw = &rt6->rt6i_gateway,
                        };
 
 
 static unsigned int ip6_default_advmss(const struct dst_entry *dst)
 {
-       struct net_device *dev = dst->dev;
+       struct net_device *dev = dst_dev(dst);
        unsigned int mtu = dst_mtu(dst);
        struct net *net;
 
 
        if (res.f6i->nh) {
                struct fib6_nh_match_arg arg = {
-                       .dev = dst->dev,
+                       .dev = dst_dev(dst),
                        .gw = &rt->rt6i_gateway,
                };
 
 static int ip6_pkt_drop(struct sk_buff *skb, u8 code, int ipstats_mib_noroutes)
 {
        struct dst_entry *dst = skb_dst(skb);
-       struct net *net = dev_net(dst->dev);
+       struct net_device *dev = dst_dev(dst);
+       struct net *net = dev_net(dev);
        struct inet6_dev *idev;
        SKB_DR(reason);
        int type;
 
        if (netif_is_l3_master(skb->dev) ||
-           dst->dev == net->loopback_dev)
+           dev == net->loopback_dev)
                idev = __in6_dev_get_safely(dev_get_by_index_rcu(net, IP6CB(skb)->iif));
        else
                idev = ip6_dst_idev(dst);
         * each as a nexthop within RTA_MULTIPATH.
         */
        if (rt6) {
+               struct net_device *dev;
+
                if (rt6_flags & RTF_GATEWAY &&
                    nla_put_in6_addr(skb, RTA_GATEWAY, &rt6->rt6i_gateway))
                        goto nla_put_failure;
 
-               if (dst->dev && nla_put_u32(skb, RTA_OIF, dst->dev->ifindex))
+               dev = dst_dev(dst);
+               if (dev && nla_put_u32(skb, RTA_OIF, dev->ifindex))
                        goto nla_put_failure;
 
                if (lwtunnel_fill_encap(skb, dst->lwtstate, RTA_ENCAP, RTA_ENCAP_TYPE) < 0)
 
                        local_bh_enable();
                }
 
-               err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
+               err = skb_cow_head(skb, LL_RESERVED_SPACE(dst_dev(dst)));
                if (unlikely(err))
                        goto drop;
        }
                        local_bh_enable();
                }
 
-               err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
+               err = skb_cow_head(skb, LL_RESERVED_SPACE(dst_dev(dst)));
                if (unlikely(err))
                        goto drop;
        } else {
 
                               int proto, struct dst_entry *cache_dst)
 {
        struct dst_entry *dst = skb_dst(skb);
-       struct net *net = dev_net(dst->dev);
+       struct net_device *dev = dst_dev(dst);
+       struct net *net = dev_net(dev);
        struct ipv6hdr *hdr, *inner_hdr;
        struct ipv6_sr_hdr *isrh;
        int hdrlen, tot_len, err;
        isrh->nexthdr = proto;
 
        hdr->daddr = isrh->segments[isrh->first_segment];
-       set_tun_src(net, dst->dev, &hdr->daddr, &hdr->saddr);
+       set_tun_src(net, dev, &hdr->daddr, &hdr->saddr);
 
 #ifdef CONFIG_IPV6_SEG6_HMAC
        if (sr_has_hmac(isrh)) {
 {
        __u8 first_seg = osrh->first_segment;
        struct dst_entry *dst = skb_dst(skb);
-       struct net *net = dev_net(dst->dev);
+       struct net_device *dev = dst_dev(dst);
+       struct net *net = dev_net(dev);
        struct ipv6hdr *hdr, *inner_hdr;
        int hdrlen = ipv6_optlen(osrh);
        int red_tlv_offset, tlv_offset;
        if (skip_srh) {
                hdr->nexthdr = proto;
 
-               set_tun_src(net, dst->dev, &hdr->daddr, &hdr->saddr);
+               set_tun_src(net, dev, &hdr->daddr, &hdr->saddr);
                goto out;
        }
 
 
 srcaddr:
        isrh->nexthdr = proto;
-       set_tun_src(net, dst->dev, &hdr->daddr, &hdr->saddr);
+       set_tun_src(net, dev, &hdr->daddr, &hdr->saddr);
 
 #ifdef CONFIG_IPV6_SEG6_HMAC
        if (unlikely(!skip_srh && sr_has_hmac(isrh))) {
                        local_bh_enable();
                }
 
-               err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
+               err = skb_cow_head(skb, LL_RESERVED_SPACE(dst_dev(dst)));
                if (unlikely(err))
                        goto drop;
        } else {
        if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled))
                return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
                               dev_net(skb->dev), NULL, skb, NULL,
-                              skb_dst(skb)->dev, seg6_input_finish);
+                              skb_dst_dev(skb), seg6_input_finish);
 
        return seg6_input_finish(dev_net(skb->dev), NULL, skb);
 drop:
                        local_bh_enable();
                }
 
-               err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
+               err = skb_cow_head(skb, LL_RESERVED_SPACE(dst_dev(dst)));
                if (unlikely(err))
                        goto drop;
        }
 
        if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled))
                return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb,
-                              NULL, skb_dst(skb)->dev, dst_output);
+                              NULL, dst_dev(dst), dst_output);
 
        return dst_output(net, sk, skb);
 drop:
 
        if (!local_delivery)
                dev_flags |= IFF_LOOPBACK;
 
-       if (dst && (dst->dev->flags & dev_flags) && !dst->error) {
+       if (dst && (dst_dev(dst)->flags & dev_flags) && !dst->error) {
                dst_release(dst);
                dst = NULL;
        }