]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ipv6: adopt dst_dev() helper
authorEric Dumazet <edumazet@google.com>
Fri, 2 Jan 2026 20:37:25 +0000 (12:37 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 8 Jan 2026 09:15:01 +0000 (10:15 +0100)
[ Upstream commit 1caf27297215a5241f9bfc9c07336349d9034ee3 ]

Use the new helper as a step to deal with potential dst->dev races.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20250630121934.3399505-9-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[Harshit: Backport to 6.12.y, pulled this is a prerequisite]
Stable-dep-of: 99a2ace61b21 ("net: use dst_dev_rcu() in sk_setup_caps()")
Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
17 files changed:
include/net/ip6_route.h
net/ipv6/exthdrs.c
net/ipv6/icmp.c
net/ipv6/ila/ila_lwt.c
net/ipv6/ioam6_iptunnel.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_udp_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/ndisc.c
net/ipv6/netfilter/nf_dup_ipv6.c
net/ipv6/output_core.c
net/ipv6/route.c
net/ipv6/rpl_iptunnel.c
net/ipv6/seg6_iptunnel.c
net/ipv6/seg6_local.c

index 6dbdf60b342f6d57ddd6288ce5e4476b413bff60..9255f21818ee7b03d2608fd399b082c0098c7028 100644 (file)
@@ -274,7 +274,7 @@ static inline unsigned int ip6_skb_dst_mtu(const struct sk_buff *skb)
        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);
@@ -337,7 +337,7 @@ static inline unsigned int ip6_dst_mtu_maybe_forward(const struct dst_entry *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();
index 6789623b2b0d1db4d8c13dc505cb362c456c5160..20f77fdfb73da914055ed9e9aa213055e63519ae 100644 (file)
@@ -306,7 +306,7 @@ static int ipv6_destopt_rcv(struct sk_buff *skb)
        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);
index 4d14ab7f7e99f152cd5f5adaa023f0280957f275..8117c1784596752d369f118ba102f7b24c584da9 100644 (file)
@@ -196,6 +196,7 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
                               struct flowi6 *fl6, bool apply_ratelimit)
 {
        struct net *net = sock_net(sk);
+       struct net_device *dev;
        struct dst_entry *dst;
        bool res = false;
 
@@ -208,10 +209,11 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
         * 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);
index 7d574f5132e2fb893863b0eef7ef1704010a04dd..7bb9edc5c28c5d87b6853ebf28764e032759efd4 100644 (file)
@@ -70,7 +70,7 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
                 */
 
                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);
index 163b9e47eb9ff72764cfffcae43ade9bf3897fa5..9e4774771023b3cb3456868971562c12b1c845d6 100644 (file)
@@ -328,7 +328,7 @@ static int ioam6_do_encap(struct net *net, struct sk_buff *skb,
        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);
@@ -417,7 +417,7 @@ do_encap:
                        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;
        }
index 1c186d132fe001512e635a2e694af129bb1f14ae..0b736627ebaf484eee9210e104db6317321f1e8c 100644 (file)
@@ -1084,9 +1084,11 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
                         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) {
index f0e5431c2d46f58fd454bd40847fb60518c72e00..24b68e99636e39400f415423917894c0547054c6 100644 (file)
@@ -60,7 +60,7 @@
 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;
@@ -271,7 +271,7 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
        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);
@@ -503,7 +503,8 @@ int ip6_forward(struct sk_buff *skb)
        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;
@@ -591,12 +592,12 @@ int ip6_forward(struct sk_buff *skb)
                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;
@@ -644,7 +645,7 @@ int ip6_forward(struct sk_buff *skb)
 
        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),
@@ -653,7 +654,7 @@ int ip6_forward(struct sk_buff *skb)
                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;
@@ -666,7 +667,7 @@ int ip6_forward(struct sk_buff *skb)
        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:
@@ -1093,7 +1094,7 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk,
 #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;
        }
index b72ca103490686117bdc88180324d93de6ac6c4c..6450ecf0d0a749dca4c51a71c2319b5df744a950 100644 (file)
@@ -1179,7 +1179,7 @@ route_lookup:
                ndst = dst;
        }
 
-       tdev = dst->dev;
+       tdev = dst_dev(dst);
 
        if (tdev == dev) {
                DEV_STATS_INC(dev, collisions);
@@ -1255,7 +1255,7 @@ route_lookup:
        /* 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;
        ip_tunnel_adj_headroom(dev, max_headroom);
 
index c99053189ea8a13be63927290576655e8da0c0fb..2acf1bb93fc0fee4b95fd3e3866d5ccbd7dfd1ba 100644 (file)
@@ -168,7 +168,7 @@ struct dst_entry *udp_tunnel6_dst_lookup(struct sk_buff *skb,
                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);
index 01235046914432c415995ea3647cebf511c3935d..fd6f76e36e805b1774cce127bece8c958da1cfcb 100644 (file)
@@ -497,7 +497,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
                              (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);
index 8699d1a188dc4a15ac0b65229c4dd19240c9c054..d961e6c2d09d79cb1fa0148dfd1dc336721bef80 100644 (file)
@@ -473,6 +473,7 @@ void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr,
 {
        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;
@@ -507,11 +508,12 @@ void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr,
 
        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);
index 0c39c77fe8a8a4c7589cdd9e6b7fb78e6f0ef88b..a8bb04bd94cf2c56ca8b58d3c77420b77970587a 100644 (file)
@@ -38,7 +38,7 @@ static bool nf_dup_ipv6_route(struct net *net, struct sk_buff *skb,
        }
        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;
index 806d4b5dd1e60b27726facbb59bbef97d6fee7f5..90a178dd24aaeb44b69ad4abc9da6fa1c10f46d1 100644 (file)
@@ -105,7 +105,7 @@ int ip6_dst_hoplimit(struct dst_entry *dst)
 {
        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();
index 276fa74af2066792d5547c43e04e4b4d73692373..aeac45af3a22af40d001ca93b0d1c776de32ee68 100644 (file)
@@ -228,13 +228,13 @@ static struct neighbour *ip6_dst_neigh_lookup(const struct dst_entry *dst,
        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)
@@ -2945,7 +2945,7 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
 
                if (res.f6i->nh) {
                        struct fib6_nh_match_arg arg = {
-                               .dev = dst->dev,
+                               .dev = dst_dev(dst),
                                .gw = &rt6->rt6i_gateway,
                        };
 
@@ -3240,7 +3240,7 @@ EXPORT_SYMBOL_GPL(ip6_sk_redirect);
 
 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;
 
@@ -4264,7 +4264,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
 
        if (res.f6i->nh) {
                struct fib6_nh_match_arg arg = {
-                       .dev = dst->dev,
+                       .dev = dst_dev(dst),
                        .gw = &rt->rt6i_gateway,
                };
 
@@ -4551,13 +4551,14 @@ int ipv6_route_ioctl(struct net *net, unsigned int cmd, struct in6_rtmsg *rtmsg)
 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);
@@ -5775,11 +5776,14 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
         * 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 (dst->lwtstate &&
index eccfa4203e96b4a6a8af96fbabea29c9b646f274..c7942cf655671c846a0307c589beac984dbcac29 100644 (file)
@@ -242,7 +242,7 @@ static int rpl_output(struct net *net, struct sock *sk, struct sk_buff *skb)
                        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;
        }
@@ -297,7 +297,7 @@ static int rpl_input(struct sk_buff *skb)
                        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 {
index 51583461ae29ba37869133f9380f25cb7dd6be34..27918fc0c9721d777965a819863169f3bde5114c 100644 (file)
@@ -128,7 +128,8 @@ static int __seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh,
                               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;
@@ -181,7 +182,7 @@ static int __seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh,
        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)) {
@@ -212,7 +213,8 @@ static int seg6_do_srh_encap_red(struct sk_buff *skb,
 {
        __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;
@@ -270,7 +272,7 @@ static int seg6_do_srh_encap_red(struct sk_buff *skb,
        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;
        }
 
@@ -306,7 +308,7 @@ static int seg6_do_srh_encap_red(struct sk_buff *skb,
 
 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))) {
@@ -507,7 +509,7 @@ static int seg6_input_core(struct net *net, struct sock *sk,
                        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 {
@@ -518,7 +520,7 @@ static int seg6_input_core(struct net *net, struct sock *sk,
        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:
@@ -593,7 +595,7 @@ static int seg6_output_core(struct net *net, struct sock *sk,
                        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;
        }
@@ -603,7 +605,7 @@ static int seg6_output_core(struct net *net, struct sock *sk,
 
        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:
index e445a0a45568d1bad2d9320055e7ae9392691859..bb196d451a55a1cf6ce68fa70bfbf7ca038efa28 100644 (file)
@@ -310,7 +310,7 @@ seg6_lookup_any_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr,
        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;
        }