mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 10:20:17 -04:00
Merge branch 'net-add-data-race-annotations-around-dst-fields'
Eric Dumazet says: ==================== net: add data-race annotations around dst fields Add annotations around various dst fields, which can change under us. Add four helpers to prepare better dst->dev protection, and start using them. More to come later. v1: https://lore.kernel.org/20250627112526.3615031-1-edumazet@google.com ==================== Link: https://patch.msgid.link/20250630121934.3399505-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -240,9 +240,9 @@ static inline void dst_hold(struct dst_entry *dst)
|
||||
|
||||
static inline void dst_use_noref(struct dst_entry *dst, unsigned long time)
|
||||
{
|
||||
if (unlikely(time != dst->lastuse)) {
|
||||
if (unlikely(time != READ_ONCE(dst->lastuse))) {
|
||||
dst->__use++;
|
||||
dst->lastuse = time;
|
||||
WRITE_ONCE(dst->lastuse, time);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,13 +431,15 @@ static inline void dst_link_failure(struct sk_buff *skb)
|
||||
|
||||
static inline void dst_set_expires(struct dst_entry *dst, int timeout)
|
||||
{
|
||||
unsigned long expires = jiffies + timeout;
|
||||
unsigned long old, expires = jiffies + timeout;
|
||||
|
||||
if (expires == 0)
|
||||
expires = 1;
|
||||
|
||||
if (dst->expires == 0 || time_before(expires, dst->expires))
|
||||
dst->expires = expires;
|
||||
old = READ_ONCE(dst->expires);
|
||||
|
||||
if (!old || time_before(expires, old))
|
||||
WRITE_ONCE(dst->expires, expires);
|
||||
}
|
||||
|
||||
static inline unsigned int dst_dev_overhead(struct dst_entry *dst,
|
||||
@@ -456,7 +458,7 @@ INDIRECT_CALLABLE_DECLARE(int ip_output(struct net *, struct sock *,
|
||||
/* Output packet to network from transport. */
|
||||
static inline int dst_output(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
return INDIRECT_CALL_INET(skb_dst(skb)->output,
|
||||
return INDIRECT_CALL_INET(READ_ONCE(skb_dst(skb)->output),
|
||||
ip6_output, ip_output,
|
||||
net, sk, skb);
|
||||
}
|
||||
@@ -466,7 +468,7 @@ INDIRECT_CALLABLE_DECLARE(int ip_local_deliver(struct sk_buff *));
|
||||
/* Input packet from network to transport. */
|
||||
static inline int dst_input(struct sk_buff *skb)
|
||||
{
|
||||
return INDIRECT_CALL_INET(skb_dst(skb)->input,
|
||||
return INDIRECT_CALL_INET(READ_ONCE(skb_dst(skb)->input),
|
||||
ip6_input, ip_local_deliver, skb);
|
||||
}
|
||||
|
||||
@@ -476,7 +478,7 @@ INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *,
|
||||
u32));
|
||||
static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie)
|
||||
{
|
||||
if (dst->obsolete)
|
||||
if (READ_ONCE(dst->obsolete))
|
||||
dst = INDIRECT_CALL_INET(dst->ops->check, ip6_dst_check,
|
||||
ipv4_dst_check, dst, cookie);
|
||||
return dst;
|
||||
@@ -561,6 +563,26 @@ static inline void skb_dst_update_pmtu_no_confirm(struct sk_buff *skb, u32 mtu)
|
||||
dst->ops->update_pmtu(dst, NULL, skb, mtu, false);
|
||||
}
|
||||
|
||||
static inline struct net_device *dst_dev(const struct dst_entry *dst)
|
||||
{
|
||||
return READ_ONCE(dst->dev);
|
||||
}
|
||||
|
||||
static inline struct net_device *skb_dst_dev(const struct sk_buff *skb)
|
||||
{
|
||||
return dst_dev(skb_dst(skb));
|
||||
}
|
||||
|
||||
static inline struct net *skb_dst_dev_net(const struct sk_buff *skb)
|
||||
{
|
||||
return dev_net(skb_dst_dev(skb));
|
||||
}
|
||||
|
||||
static inline struct net *skb_dst_dev_net_rcu(const struct sk_buff *skb)
|
||||
{
|
||||
return dev_net_rcu(skb_dst_dev(skb));
|
||||
}
|
||||
|
||||
struct dst_entry *dst_blackhole_check(struct dst_entry *dst, u32 cookie);
|
||||
void dst_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk,
|
||||
struct sk_buff *skb, u32 mtu, bool confirm_neigh);
|
||||
|
||||
@@ -150,7 +150,7 @@ static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo,
|
||||
int iif, int sdif,
|
||||
bool *refcounted)
|
||||
{
|
||||
struct net *net = dev_net_rcu(skb_dst(skb)->dev);
|
||||
struct net *net = skb_dst_dev_net_rcu(skb);
|
||||
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
|
||||
struct sock *sk;
|
||||
|
||||
|
||||
@@ -481,7 +481,7 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo,
|
||||
const int sdif,
|
||||
bool *refcounted)
|
||||
{
|
||||
struct net *net = dev_net_rcu(skb_dst(skb)->dev);
|
||||
struct net *net = skb_dst_dev_net_rcu(skb);
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
struct sock *sk;
|
||||
|
||||
|
||||
@@ -472,12 +472,12 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
net = dev_net_rcu(dst->dev);
|
||||
net = dev_net_rcu(dst_dev(dst));
|
||||
if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) ||
|
||||
ip_mtu_locked(dst) ||
|
||||
!forwarding) {
|
||||
mtu = rt->rt_pmtu;
|
||||
if (mtu && time_before(jiffies, rt->dst.expires))
|
||||
if (mtu && time_before(jiffies, READ_ONCE(rt->dst.expires)))
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -486,7 +486,7 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
|
||||
if (mtu)
|
||||
goto out;
|
||||
|
||||
mtu = READ_ONCE(dst->dev->mtu);
|
||||
mtu = READ_ONCE(dst_dev(dst)->mtu);
|
||||
|
||||
if (unlikely(ip_mtu_locked(dst))) {
|
||||
if (rt->rt_uses_gateway && mtu > 576)
|
||||
@@ -506,16 +506,17 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
|
||||
static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
|
||||
const struct sk_buff *skb)
|
||||
{
|
||||
const struct dst_entry *dst = skb_dst(skb);
|
||||
unsigned int mtu;
|
||||
|
||||
if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) {
|
||||
bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED;
|
||||
|
||||
return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding);
|
||||
return ip_dst_mtu_maybe_forward(dst, forwarding);
|
||||
}
|
||||
|
||||
mtu = min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
|
||||
return mtu - lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu);
|
||||
mtu = min(READ_ONCE(dst_dev(dst)->mtu), IP_MAX_MTU);
|
||||
return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
|
||||
}
|
||||
|
||||
struct dst_metrics *ip_fib_metrics_init(struct nlattr *fc_mx, int fc_mx_len,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -159,7 +159,7 @@ static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
|
||||
memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
|
||||
IP6CB(skb)->flags = ip6cb_flags;
|
||||
pkt_len = skb->len - skb_inner_network_offset(skb);
|
||||
err = ip6_local_out(dev_net(skb_dst(skb)->dev), sk, skb);
|
||||
err = ip6_local_out(skb_dst_dev_net(skb), sk, skb);
|
||||
|
||||
if (dev) {
|
||||
if (unlikely(net_xmit_eval(err)))
|
||||
|
||||
@@ -138,12 +138,12 @@ int bpf_lwt_push_ip_encap(struct sk_buff *skb, void *hdr, u32 len,
|
||||
static inline void lwtunnel_set_redirect(struct dst_entry *dst)
|
||||
{
|
||||
if (lwtunnel_output_redirect(dst->lwtstate)) {
|
||||
dst->lwtstate->orig_output = dst->output;
|
||||
dst->output = lwtunnel_output;
|
||||
dst->lwtstate->orig_output = READ_ONCE(dst->output);
|
||||
WRITE_ONCE(dst->output, lwtunnel_output);
|
||||
}
|
||||
if (lwtunnel_input_redirect(dst->lwtstate)) {
|
||||
dst->lwtstate->orig_input = dst->input;
|
||||
dst->input = lwtunnel_input;
|
||||
dst->lwtstate->orig_input = READ_ONCE(dst->input);
|
||||
WRITE_ONCE(dst->input, lwtunnel_input);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -390,7 +390,7 @@ static inline int ip4_dst_hoplimit(const struct dst_entry *dst)
|
||||
const struct net *net;
|
||||
|
||||
rcu_read_lock();
|
||||
net = dev_net_rcu(dst->dev);
|
||||
net = dev_net_rcu(dst_dev(dst));
|
||||
hoplimit = READ_ONCE(net->ipv4.sysctl_ip_default_ttl);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
@@ -145,12 +145,12 @@ void dst_dev_put(struct dst_entry *dst)
|
||||
{
|
||||
struct net_device *dev = dst->dev;
|
||||
|
||||
dst->obsolete = DST_OBSOLETE_DEAD;
|
||||
WRITE_ONCE(dst->obsolete, DST_OBSOLETE_DEAD);
|
||||
if (dst->ops->ifdown)
|
||||
dst->ops->ifdown(dst, dev);
|
||||
dst->input = dst_discard;
|
||||
dst->output = dst_discard_out;
|
||||
dst->dev = blackhole_netdev;
|
||||
WRITE_ONCE(dst->input, dst_discard);
|
||||
WRITE_ONCE(dst->output, dst_discard_out);
|
||||
WRITE_ONCE(dst->dev, blackhole_netdev);
|
||||
netdev_ref_replace(dev, blackhole_netdev, &dst->dev_tracker,
|
||||
GFP_ATOMIC);
|
||||
}
|
||||
@@ -263,7 +263,7 @@ unsigned int dst_blackhole_mtu(const struct dst_entry *dst)
|
||||
{
|
||||
unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
|
||||
|
||||
return mtu ? : dst->dev->mtu;
|
||||
return mtu ? : dst_dev(dst)->mtu;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dst_blackhole_mtu);
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ static struct dst_entry *dst_cache_per_cpu_get(struct dst_cache *dst_cache,
|
||||
|
||||
if (unlikely(!time_after(idst->refresh_ts,
|
||||
READ_ONCE(dst_cache->reset_ts)) ||
|
||||
(dst->obsolete && !dst->ops->check(dst, idst->cookie)))) {
|
||||
(READ_ONCE(dst->obsolete) && !dst->ops->check(dst, idst->cookie)))) {
|
||||
dst_cache_per_cpu_dst_set(idst, NULL, 0);
|
||||
dst_release(dst);
|
||||
goto fail;
|
||||
|
||||
@@ -1428,7 +1428,8 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr,
|
||||
* we can reinject the packet there.
|
||||
*/
|
||||
n2 = NULL;
|
||||
if (dst && dst->obsolete != DST_OBSOLETE_DEAD) {
|
||||
if (dst &&
|
||||
READ_ONCE(dst->obsolete) != DST_OBSOLETE_DEAD) {
|
||||
n2 = dst_neigh_lookup_skb(dst, skb);
|
||||
if (n2)
|
||||
n1 = n2;
|
||||
|
||||
@@ -1026,9 +1026,11 @@ int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id,
|
||||
.rta_error = error,
|
||||
.rta_id = id,
|
||||
};
|
||||
unsigned long delta;
|
||||
|
||||
if (dst) {
|
||||
ci.rta_lastuse = jiffies_delta_to_clock_t(jiffies - dst->lastuse);
|
||||
delta = jiffies - READ_ONCE(dst->lastuse);
|
||||
ci.rta_lastuse = jiffies_delta_to_clock_t(delta);
|
||||
ci.rta_used = dst->__use;
|
||||
ci.rta_clntref = rcuref_read(&dst->__rcuref);
|
||||
}
|
||||
|
||||
@@ -602,7 +602,7 @@ struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie)
|
||||
{
|
||||
struct dst_entry *dst = __sk_dst_get(sk);
|
||||
|
||||
if (dst && dst->obsolete &&
|
||||
if (dst && READ_ONCE(dst->obsolete) &&
|
||||
INDIRECT_CALL_INET(dst->ops->check, ip6_dst_check, ipv4_dst_check,
|
||||
dst, cookie) == NULL) {
|
||||
sk_tx_queue_clear(sk);
|
||||
@@ -620,7 +620,7 @@ struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie)
|
||||
{
|
||||
struct dst_entry *dst = sk_dst_get(sk);
|
||||
|
||||
if (dst && dst->obsolete &&
|
||||
if (dst && READ_ONCE(dst->obsolete) &&
|
||||
INDIRECT_CALL_INET(dst->ops->check, ip6_dst_check, ipv4_dst_check,
|
||||
dst, cookie) == NULL) {
|
||||
sk_dst_reset(sk);
|
||||
@@ -2588,8 +2588,8 @@ static u32 sk_dst_gso_max_size(struct sock *sk, struct dst_entry *dst)
|
||||
!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr));
|
||||
#endif
|
||||
/* pairs with the WRITE_ONCE() in netif_set_gso(_ipv4)_max_size() */
|
||||
max_size = is_ipv6 ? READ_ONCE(dst->dev->gso_max_size) :
|
||||
READ_ONCE(dst->dev->gso_ipv4_max_size);
|
||||
max_size = is_ipv6 ? READ_ONCE(dst_dev(dst)->gso_max_size) :
|
||||
READ_ONCE(dst_dev(dst)->gso_ipv4_max_size);
|
||||
if (max_size > GSO_LEGACY_MAX_SIZE && !sk_is_tcp(sk))
|
||||
max_size = GSO_LEGACY_MAX_SIZE;
|
||||
|
||||
@@ -2600,7 +2600,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
|
||||
{
|
||||
u32 max_segs = 1;
|
||||
|
||||
sk->sk_route_caps = dst->dev->features;
|
||||
sk->sk_route_caps = dst_dev(dst)->features;
|
||||
if (sk_is_tcp(sk)) {
|
||||
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||
|
||||
@@ -2618,7 +2618,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
|
||||
sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
|
||||
sk->sk_gso_max_size = sk_dst_gso_max_size(sk, dst);
|
||||
/* pairs with the WRITE_ONCE() in netif_set_gso_max_segs() */
|
||||
max_segs = max_t(u32, READ_ONCE(dst->dev->gso_max_segs), 1);
|
||||
max_segs = max_t(u32, READ_ONCE(dst_dev(dst)->gso_max_segs), 1);
|
||||
}
|
||||
}
|
||||
sk->sk_gso_max_segs = max_segs;
|
||||
|
||||
@@ -109,7 +109,7 @@ void ip4_datagram_release_cb(struct sock *sk)
|
||||
rcu_read_lock();
|
||||
|
||||
dst = __sk_dst_get(sk);
|
||||
if (!dst || !dst->obsolete || dst->ops->check(dst, 0)) {
|
||||
if (!dst || !READ_ONCE(dst->obsolete) || dst->ops->check(dst, 0)) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -311,18 +311,20 @@ static bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
|
||||
{
|
||||
struct dst_entry *dst = &rt->dst;
|
||||
struct inet_peer *peer;
|
||||
struct net_device *dev;
|
||||
bool rc = true;
|
||||
|
||||
if (!apply_ratelimit)
|
||||
return true;
|
||||
|
||||
/* No rate limit on loopback */
|
||||
if (dst->dev && (dst->dev->flags&IFF_LOOPBACK))
|
||||
dev = dst_dev(dst);
|
||||
if (dev && (dev->flags & IFF_LOOPBACK))
|
||||
goto out;
|
||||
|
||||
rcu_read_lock();
|
||||
peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr,
|
||||
l3mdev_master_ifindex_rcu(dst->dev));
|
||||
l3mdev_master_ifindex_rcu(dev));
|
||||
rc = inet_peer_xrlim_allow(peer,
|
||||
READ_ONCE(net->ipv4.sysctl_icmp_ratelimit));
|
||||
rcu_read_unlock();
|
||||
@@ -466,13 +468,13 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
|
||||
*/
|
||||
static struct net_device *icmp_get_route_lookup_dev(struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *route_lookup_dev = NULL;
|
||||
struct net_device *dev = skb->dev;
|
||||
const struct dst_entry *dst;
|
||||
|
||||
if (skb->dev)
|
||||
route_lookup_dev = skb->dev;
|
||||
else if (skb_dst(skb))
|
||||
route_lookup_dev = skb_dst(skb)->dev;
|
||||
return route_lookup_dev;
|
||||
if (dev)
|
||||
return dev;
|
||||
dst = skb_dst(skb);
|
||||
return dst ? dst_dev(dst) : NULL;
|
||||
}
|
||||
|
||||
static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4,
|
||||
@@ -869,7 +871,7 @@ static enum skb_drop_reason icmp_unreach(struct sk_buff *skb)
|
||||
struct net *net;
|
||||
u32 info = 0;
|
||||
|
||||
net = dev_net_rcu(skb_dst(skb)->dev);
|
||||
net = skb_dst_dev_net_rcu(skb);
|
||||
|
||||
/*
|
||||
* Incomplete header ?
|
||||
@@ -1012,7 +1014,7 @@ static enum skb_drop_reason icmp_echo(struct sk_buff *skb)
|
||||
struct icmp_bxm icmp_param;
|
||||
struct net *net;
|
||||
|
||||
net = dev_net_rcu(skb_dst(skb)->dev);
|
||||
net = skb_dst_dev_net_rcu(skb);
|
||||
/* should there be an ICMP stat for ignored echos? */
|
||||
if (READ_ONCE(net->ipv4.sysctl_icmp_echo_ignore_all))
|
||||
return SKB_NOT_DROPPED_YET;
|
||||
@@ -1182,7 +1184,7 @@ static enum skb_drop_reason icmp_timestamp(struct sk_buff *skb)
|
||||
return SKB_NOT_DROPPED_YET;
|
||||
|
||||
out_err:
|
||||
__ICMP_INC_STATS(dev_net_rcu(skb_dst(skb)->dev), ICMP_MIB_INERRORS);
|
||||
__ICMP_INC_STATS(skb_dst_dev_net_rcu(skb), ICMP_MIB_INERRORS);
|
||||
return SKB_DROP_REASON_PKT_TOO_SMALL;
|
||||
}
|
||||
|
||||
|
||||
@@ -427,7 +427,7 @@ static int igmpv3_sendpack(struct sk_buff *skb)
|
||||
|
||||
pig->csum = ip_compute_csum(igmp_hdr(skb), igmplen);
|
||||
|
||||
return ip_local_out(dev_net(skb_dst(skb)->dev), skb->sk, skb);
|
||||
return ip_local_out(skb_dst_dev_net(skb), skb->sk, skb);
|
||||
}
|
||||
|
||||
static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
|
||||
|
||||
@@ -476,7 +476,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
|
||||
/* Process an incoming IP datagram fragment. */
|
||||
int ip_defrag(struct net *net, struct sk_buff *skb, u32 user)
|
||||
{
|
||||
struct net_device *dev = skb->dev ? : skb_dst(skb)->dev;
|
||||
struct net_device *dev = skb->dev ? : skb_dst_dev(skb);
|
||||
int vif = l3mdev_master_ifindex_rcu(dev);
|
||||
struct ipq *qp;
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
|
||||
return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT,
|
||||
net, sk, skb, NULL, skb_dst(skb)->dev,
|
||||
net, sk, skb, NULL, skb_dst_dev(skb),
|
||||
dst_output);
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ static int ip_finish_output2(struct net *net, struct sock *sk, struct sk_buff *s
|
||||
{
|
||||
struct dst_entry *dst = skb_dst(skb);
|
||||
struct rtable *rt = dst_rtable(dst);
|
||||
struct net_device *dev = dst->dev;
|
||||
struct net_device *dev = dst_dev(dst);
|
||||
unsigned int hh_len = LL_RESERVED_SPACE(dev);
|
||||
struct neighbour *neigh;
|
||||
bool is_v6gw = false;
|
||||
@@ -425,7 +425,7 @@ int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
|
||||
int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb_dst(skb)->dev, *indev = skb->dev;
|
||||
struct net_device *dev = skb_dst_dev(skb), *indev = skb->dev;
|
||||
|
||||
skb->dev = dev;
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
|
||||
@@ -229,7 +229,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||
goto tx_error_icmp;
|
||||
}
|
||||
|
||||
tdev = dst->dev;
|
||||
tdev = dst_dev(dst);
|
||||
|
||||
if (tdev == dev) {
|
||||
dst_release(dst);
|
||||
@@ -259,7 +259,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||
xmit:
|
||||
skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev)));
|
||||
skb_dst_set(skb, dst);
|
||||
skb->dev = skb_dst(skb)->dev;
|
||||
skb->dev = skb_dst_dev(skb);
|
||||
|
||||
err = dst_output(tunnel->net, skb->sk, skb);
|
||||
if (net_xmit_eval(err) == 0)
|
||||
|
||||
@@ -20,12 +20,12 @@
|
||||
/* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
|
||||
int ip_route_me_harder(struct net *net, struct sock *sk, struct sk_buff *skb, unsigned int addr_type)
|
||||
{
|
||||
struct net_device *dev = skb_dst_dev(skb);
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
struct rtable *rt;
|
||||
struct flowi4 fl4 = {};
|
||||
__be32 saddr = iph->saddr;
|
||||
__u8 flags;
|
||||
struct net_device *dev = skb_dst(skb)->dev;
|
||||
struct flow_keys flkeys;
|
||||
unsigned int hh_len;
|
||||
|
||||
@@ -74,7 +74,7 @@ int ip_route_me_harder(struct net *net, struct sock *sk, struct sk_buff *skb, un
|
||||
#endif
|
||||
|
||||
/* Change in oif may mean change in hh_len. */
|
||||
hh_len = skb_dst(skb)->dev->hard_header_len;
|
||||
hh_len = skb_dst_dev(skb)->hard_header_len;
|
||||
if (skb_headroom(skb) < hh_len &&
|
||||
pskb_expand_head(skb, HH_DATA_ALIGN(hh_len - skb_headroom(skb)),
|
||||
0, GFP_ATOMIC))
|
||||
|
||||
@@ -413,7 +413,7 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
|
||||
const void *daddr)
|
||||
{
|
||||
const struct rtable *rt = container_of(dst, struct rtable, dst);
|
||||
struct net_device *dev = dst->dev;
|
||||
struct net_device *dev = dst_dev(dst);
|
||||
struct neighbour *n;
|
||||
|
||||
rcu_read_lock();
|
||||
@@ -440,7 +440,7 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
|
||||
static void ipv4_confirm_neigh(const struct dst_entry *dst, const void *daddr)
|
||||
{
|
||||
const struct rtable *rt = container_of(dst, struct rtable, dst);
|
||||
struct net_device *dev = dst->dev;
|
||||
struct net_device *dev = dst_dev(dst);
|
||||
const __be32 *pkey = daddr;
|
||||
|
||||
if (rt->rt_gw_family == AF_INET) {
|
||||
@@ -717,7 +717,7 @@ static void update_or_create_fnhe(struct fib_nh_common *nhc, __be32 daddr,
|
||||
*/
|
||||
rt = rcu_dereference(nhc->nhc_rth_input);
|
||||
if (rt)
|
||||
rt->dst.obsolete = DST_OBSOLETE_KILL;
|
||||
WRITE_ONCE(rt->dst.obsolete, DST_OBSOLETE_KILL);
|
||||
|
||||
for_each_possible_cpu(i) {
|
||||
struct rtable __rcu **prt;
|
||||
@@ -725,7 +725,7 @@ static void update_or_create_fnhe(struct fib_nh_common *nhc, __be32 daddr,
|
||||
prt = per_cpu_ptr(nhc->nhc_pcpu_rth_output, i);
|
||||
rt = rcu_dereference(*prt);
|
||||
if (rt)
|
||||
rt->dst.obsolete = DST_OBSOLETE_KILL;
|
||||
WRITE_ONCE(rt->dst.obsolete, DST_OBSOLETE_KILL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -797,7 +797,7 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow
|
||||
jiffies + ip_rt_gc_timeout);
|
||||
}
|
||||
if (kill_route)
|
||||
rt->dst.obsolete = DST_OBSOLETE_KILL;
|
||||
WRITE_ONCE(rt->dst.obsolete, DST_OBSOLETE_KILL);
|
||||
call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
|
||||
}
|
||||
neigh_release(n);
|
||||
@@ -842,9 +842,9 @@ static void ipv4_negative_advice(struct sock *sk,
|
||||
{
|
||||
struct rtable *rt = dst_rtable(dst);
|
||||
|
||||
if ((dst->obsolete > 0) ||
|
||||
if ((READ_ONCE(dst->obsolete) > 0) ||
|
||||
(rt->rt_flags & RTCF_REDIRECTED) ||
|
||||
rt->dst.expires)
|
||||
READ_ONCE(rt->dst.expires))
|
||||
sk_dst_reset(sk);
|
||||
}
|
||||
|
||||
@@ -1026,14 +1026,15 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
net = dev_net_rcu(dst->dev);
|
||||
net = dev_net_rcu(dst_dev(dst));
|
||||
if (mtu < net->ipv4.ip_rt_min_pmtu) {
|
||||
lock = true;
|
||||
mtu = min(old_mtu, net->ipv4.ip_rt_min_pmtu);
|
||||
}
|
||||
|
||||
if (rt->rt_pmtu == mtu && !lock &&
|
||||
time_before(jiffies, dst->expires - net->ipv4.ip_rt_mtu_expires / 2))
|
||||
time_before(jiffies, READ_ONCE(dst->expires) -
|
||||
net->ipv4.ip_rt_mtu_expires / 2))
|
||||
goto out;
|
||||
|
||||
if (fib_lookup(net, fl4, &res, 0) == 0) {
|
||||
@@ -1136,7 +1137,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
|
||||
__build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0);
|
||||
|
||||
rt = dst_rtable(odst);
|
||||
if (odst->obsolete && !odst->ops->check(odst, 0)) {
|
||||
if (READ_ONCE(odst->obsolete) && !odst->ops->check(odst, 0)) {
|
||||
rt = ip_route_output_flow(sock_net(sk), &fl4, sk);
|
||||
if (IS_ERR(rt))
|
||||
goto out;
|
||||
@@ -1211,7 +1212,8 @@ INDIRECT_CALLABLE_SCOPE struct dst_entry *ipv4_dst_check(struct dst_entry *dst,
|
||||
* this is indicated by setting obsolete to DST_OBSOLETE_KILL or
|
||||
* DST_OBSOLETE_DEAD.
|
||||
*/
|
||||
if (dst->obsolete != DST_OBSOLETE_FORCE_CHK || rt_is_expired(rt))
|
||||
if (READ_ONCE(dst->obsolete) != DST_OBSOLETE_FORCE_CHK ||
|
||||
rt_is_expired(rt))
|
||||
return NULL;
|
||||
return dst;
|
||||
}
|
||||
@@ -1324,7 +1326,7 @@ static unsigned int ipv4_default_advmss(const struct dst_entry *dst)
|
||||
struct net *net;
|
||||
|
||||
rcu_read_lock();
|
||||
net = dev_net_rcu(dst->dev);
|
||||
net = dev_net_rcu(dst_dev(dst));
|
||||
advmss = max_t(unsigned int, ipv4_mtu(dst) - header_size,
|
||||
net->ipv4.ip_rt_min_advmss);
|
||||
rcu_read_unlock();
|
||||
@@ -1571,7 +1573,7 @@ void rt_flush_dev(struct net_device *dev)
|
||||
static bool rt_cache_valid(const struct rtable *rt)
|
||||
{
|
||||
return rt &&
|
||||
rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK &&
|
||||
READ_ONCE(rt->dst.obsolete) == DST_OBSOLETE_FORCE_CHK &&
|
||||
!rt_is_expired(rt);
|
||||
}
|
||||
|
||||
@@ -1685,8 +1687,8 @@ struct rtable *rt_dst_clone(struct net_device *dev, struct rtable *rt)
|
||||
else if (rt->rt_gw_family == AF_INET6)
|
||||
new_rt->rt_gw6 = rt->rt_gw6;
|
||||
|
||||
new_rt->dst.input = rt->dst.input;
|
||||
new_rt->dst.output = rt->dst.output;
|
||||
new_rt->dst.input = READ_ONCE(rt->dst.input);
|
||||
new_rt->dst.output = READ_ONCE(rt->dst.output);
|
||||
new_rt->dst.error = rt->dst.error;
|
||||
new_rt->dst.lastuse = jiffies;
|
||||
new_rt->dst.lwtstate = lwtstate_get(rt->dst.lwtstate);
|
||||
@@ -3009,7 +3011,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src,
|
||||
}
|
||||
}
|
||||
|
||||
expires = rt->dst.expires;
|
||||
expires = READ_ONCE(rt->dst.expires);
|
||||
if (expires) {
|
||||
unsigned long now = jiffies;
|
||||
|
||||
|
||||
@@ -559,6 +559,7 @@ bool tcp_fastopen_active_should_disable(struct sock *sk)
|
||||
void tcp_fastopen_active_disable_ofo_check(struct sock *sk)
|
||||
{
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
struct net_device *dev;
|
||||
struct dst_entry *dst;
|
||||
struct sk_buff *skb;
|
||||
|
||||
@@ -576,7 +577,8 @@ void tcp_fastopen_active_disable_ofo_check(struct sock *sk)
|
||||
} else if (tp->syn_fastopen_ch &&
|
||||
atomic_read(&sock_net(sk)->ipv4.tfo_active_disable_times)) {
|
||||
dst = sk_dst_get(sk);
|
||||
if (!(dst && dst->dev && (dst->dev->flags & IFF_LOOPBACK)))
|
||||
dev = dst ? dst_dev(dst) : NULL;
|
||||
if (!(dev && (dev->flags & IFF_LOOPBACK)))
|
||||
atomic_set(&sock_net(sk)->ipv4.tfo_active_disable_times, 0);
|
||||
dst_release(dst);
|
||||
}
|
||||
|
||||
@@ -788,7 +788,7 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb,
|
||||
arg.iov[0].iov_base = (unsigned char *)&rep;
|
||||
arg.iov[0].iov_len = sizeof(rep.th);
|
||||
|
||||
net = sk ? sock_net(sk) : dev_net_rcu(skb_dst(skb)->dev);
|
||||
net = sk ? sock_net(sk) : skb_dst_dev_net_rcu(skb);
|
||||
|
||||
/* Invalid TCP option size or twice included auth */
|
||||
if (tcp_parse_auth_options(tcp_hdr(skb), &md5_hash_location, &aoh))
|
||||
|
||||
@@ -166,11 +166,11 @@ static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst,
|
||||
unsigned int hash)
|
||||
{
|
||||
struct tcp_metrics_block *tm;
|
||||
struct net *net;
|
||||
bool reclaim = false;
|
||||
struct net *net;
|
||||
|
||||
spin_lock_bh(&tcp_metrics_lock);
|
||||
net = dev_net_rcu(dst->dev);
|
||||
net = dev_net_rcu(dst_dev(dst));
|
||||
|
||||
/* While waiting for the spin-lock the cache might have been populated
|
||||
* with this entry and so we have to check again.
|
||||
@@ -273,7 +273,7 @@ static struct tcp_metrics_block *__tcp_get_metrics_req(struct request_sock *req,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
net = dev_net_rcu(dst->dev);
|
||||
net = dev_net_rcu(dst_dev(dst));
|
||||
hash ^= net_hash_mix(net);
|
||||
hash = hash_32(hash, tcp_metrics_hash_log);
|
||||
|
||||
@@ -318,7 +318,7 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk,
|
||||
else
|
||||
return NULL;
|
||||
|
||||
net = dev_net_rcu(dst->dev);
|
||||
net = dev_net_rcu(dst_dev(dst));
|
||||
hash ^= net_hash_mix(net);
|
||||
hash = hash_32(hash, tcp_metrics_hash_log);
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING,
|
||||
net, sk, skb, skb->dev, skb_dst(skb)->dev,
|
||||
net, sk, skb, skb->dev, skb_dst_dev(skb),
|
||||
__xfrm4_output,
|
||||
!(IPCB(skb)->flags & IPSKB_REROUTED));
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ void ip6_datagram_release_cb(struct sock *sk)
|
||||
|
||||
rcu_read_lock();
|
||||
dst = __sk_dst_get(sk);
|
||||
if (!dst || !dst->obsolete ||
|
||||
if (!dst || !READ_ONCE(dst->obsolete) ||
|
||||
dst->ops->check(dst, inet6_sk(sk)->dst_cookie)) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
|
||||
@@ -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);
|
||||
@@ -460,7 +460,7 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (skb_dst(skb)->dev->flags & IFF_LOOPBACK) {
|
||||
if (skb_dst_dev(skb)->flags & IFF_LOOPBACK) {
|
||||
if (ipv6_hdr(skb)->hop_limit <= 1) {
|
||||
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
|
||||
icmpv6_send(skb, ICMPV6_TIME_EXCEED,
|
||||
@@ -621,7 +621,7 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (skb_dst(skb)->dev->flags & IFF_LOOPBACK) {
|
||||
if (skb_dst_dev(skb)->flags & IFF_LOOPBACK) {
|
||||
if (ipv6_hdr(skb)->hop_limit <= 1) {
|
||||
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
|
||||
icmpv6_send(skb, ICMPV6_TIME_EXCEED,
|
||||
@@ -783,7 +783,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
|
||||
kfree_skb(skb);
|
||||
return -1;
|
||||
}
|
||||
if (!ipv6_chk_home_addr(dev_net(skb_dst(skb)->dev), addr)) {
|
||||
if (!ipv6_chk_home_addr(skb_dst_dev_net(skb), addr)) {
|
||||
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
|
||||
kfree_skb(skb);
|
||||
return -1;
|
||||
@@ -809,7 +809,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (skb_dst(skb)->dev->flags&IFF_LOOPBACK) {
|
||||
if (skb_dst_dev(skb)->flags & IFF_LOOPBACK) {
|
||||
if (ipv6_hdr(skb)->hop_limit <= 1) {
|
||||
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
|
||||
icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -696,6 +696,7 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
|
||||
struct ioam6_schema *sc,
|
||||
u8 sclen, bool is_input)
|
||||
{
|
||||
struct net_device *dev = skb_dst_dev(skb);
|
||||
struct timespec64 ts;
|
||||
ktime_t tstamp;
|
||||
u64 raw64;
|
||||
@@ -712,7 +713,7 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
|
||||
if (is_input)
|
||||
byte--;
|
||||
|
||||
raw32 = dev_net(skb_dst(skb)->dev)->ipv6.sysctl.ioam6_id;
|
||||
raw32 = dev_net(dev)->ipv6.sysctl.ioam6_id;
|
||||
|
||||
*(__be32 *)data = cpu_to_be32((byte << 24) | raw32);
|
||||
data += sizeof(__be32);
|
||||
@@ -728,10 +729,10 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
|
||||
*(__be16 *)data = cpu_to_be16(raw16);
|
||||
data += sizeof(__be16);
|
||||
|
||||
if (skb_dst(skb)->dev->flags & IFF_LOOPBACK)
|
||||
if (dev->flags & IFF_LOOPBACK)
|
||||
raw16 = IOAM6_U16_UNAVAILABLE;
|
||||
else
|
||||
raw16 = (__force u16)READ_ONCE(__in6_dev_get(skb_dst(skb)->dev)->cnf.ioam6_id);
|
||||
raw16 = (__force u16)READ_ONCE(__in6_dev_get(dev)->cnf.ioam6_id);
|
||||
|
||||
*(__be16 *)data = cpu_to_be16(raw16);
|
||||
data += sizeof(__be16);
|
||||
@@ -783,10 +784,10 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
|
||||
struct Qdisc *qdisc;
|
||||
__u32 qlen, backlog;
|
||||
|
||||
if (skb_dst(skb)->dev->flags & IFF_LOOPBACK) {
|
||||
if (dev->flags & IFF_LOOPBACK) {
|
||||
*(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE);
|
||||
} else {
|
||||
queue = skb_get_tx_queue(skb_dst(skb)->dev, skb);
|
||||
queue = skb_get_tx_queue(dev, skb);
|
||||
qdisc = rcu_dereference(queue->qdisc);
|
||||
qdisc_qstats_qlen_backlog(qdisc, &qlen, &backlog);
|
||||
|
||||
@@ -807,7 +808,7 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
|
||||
if (is_input)
|
||||
byte--;
|
||||
|
||||
raw64 = dev_net(skb_dst(skb)->dev)->ipv6.sysctl.ioam6_id_wide;
|
||||
raw64 = dev_net(dev)->ipv6.sysctl.ioam6_id_wide;
|
||||
|
||||
*(__be64 *)data = cpu_to_be64(((u64)byte << 56) | raw64);
|
||||
data += sizeof(__be64);
|
||||
@@ -823,10 +824,10 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
|
||||
*(__be32 *)data = cpu_to_be32(raw32);
|
||||
data += sizeof(__be32);
|
||||
|
||||
if (skb_dst(skb)->dev->flags & IFF_LOOPBACK)
|
||||
if (dev->flags & IFF_LOOPBACK)
|
||||
raw32 = IOAM6_U32_UNAVAILABLE;
|
||||
else
|
||||
raw32 = READ_ONCE(__in6_dev_get(skb_dst(skb)->dev)->cnf.ioam6_id_wide);
|
||||
raw32 = READ_ONCE(__in6_dev_get(dev)->cnf.ioam6_id_wide);
|
||||
|
||||
*(__be32 *)data = cpu_to_be32(raw32);
|
||||
data += sizeof(__be32);
|
||||
|
||||
@@ -335,7 +335,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);
|
||||
@@ -442,7 +442,7 @@ static int ioam6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1085,9 +1085,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) {
|
||||
|
||||
@@ -187,7 +187,9 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
|
||||
* arrived via the sending interface (ethX), because of the
|
||||
* nature of scoping architecture. --yoshfuji
|
||||
*/
|
||||
IP6CB(skb)->iif = skb_valid_dst(skb) ? ip6_dst_idev(skb_dst(skb))->dev->ifindex : dev->ifindex;
|
||||
IP6CB(skb)->iif = skb_valid_dst(skb) ?
|
||||
ip6_dst_idev(skb_dst(skb))->dev->ifindex :
|
||||
dev->ifindex;
|
||||
|
||||
if (unlikely(!pskb_may_pull(skb, sizeof(*hdr))))
|
||||
goto err;
|
||||
@@ -499,38 +501,32 @@ EXPORT_SYMBOL_GPL(ip6_input);
|
||||
|
||||
int ip6_mc_input(struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
int sdif = inet6_sdif(skb);
|
||||
const struct ipv6hdr *hdr;
|
||||
struct net_device *dev;
|
||||
bool deliver;
|
||||
|
||||
__IP6_UPD_PO_STATS(dev_net(skb_dst(skb)->dev),
|
||||
__in6_dev_get_safely(skb->dev), IPSTATS_MIB_INMCAST,
|
||||
skb->len);
|
||||
__IP6_UPD_PO_STATS(skb_dst_dev_net_rcu(skb),
|
||||
__in6_dev_get_safely(dev), IPSTATS_MIB_INMCAST,
|
||||
skb->len);
|
||||
|
||||
/* skb->dev passed may be master dev for vrfs. */
|
||||
if (sdif) {
|
||||
rcu_read_lock();
|
||||
dev = dev_get_by_index_rcu(dev_net(skb->dev), sdif);
|
||||
dev = dev_get_by_index_rcu(dev_net_rcu(dev), sdif);
|
||||
if (!dev) {
|
||||
rcu_read_unlock();
|
||||
kfree_skb(skb);
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
dev = skb->dev;
|
||||
}
|
||||
|
||||
hdr = ipv6_hdr(skb);
|
||||
deliver = ipv6_chk_mcast_addr(dev, &hdr->daddr, NULL);
|
||||
if (sdif)
|
||||
rcu_read_unlock();
|
||||
|
||||
#ifdef CONFIG_IPV6_MROUTE
|
||||
/*
|
||||
* IPv6 multicast router mode is now supported ;)
|
||||
*/
|
||||
if (atomic_read(&dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding) &&
|
||||
if (atomic_read(&dev_net_rcu(skb->dev)->ipv6.devconf_all->mc_forwarding) &&
|
||||
!(ipv6_addr_type(&hdr->daddr) &
|
||||
(IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)) &&
|
||||
likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) {
|
||||
@@ -571,22 +567,21 @@ int ip6_mc_input(struct sk_buff *skb)
|
||||
/* unknown RA - process it normally */
|
||||
}
|
||||
|
||||
if (deliver)
|
||||
if (deliver) {
|
||||
skb2 = skb_clone(skb, GFP_ATOMIC);
|
||||
else {
|
||||
} else {
|
||||
skb2 = skb;
|
||||
skb = NULL;
|
||||
}
|
||||
|
||||
if (skb2) {
|
||||
if (skb2)
|
||||
ip6_mr_input(skb2);
|
||||
}
|
||||
}
|
||||
out:
|
||||
#endif
|
||||
if (likely(deliver))
|
||||
if (likely(deliver)) {
|
||||
ip6_input(skb);
|
||||
else {
|
||||
} else {
|
||||
/* discard */
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -232,8 +232,9 @@ static int ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff *s
|
||||
|
||||
int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb_dst(skb)->dev, *indev = skb->dev;
|
||||
struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
|
||||
struct dst_entry *dst = skb_dst(skb);
|
||||
struct net_device *dev = dst_dev(dst), *indev = skb->dev;
|
||||
struct inet6_dev *idev = ip6_dst_idev(dst);
|
||||
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
skb->dev = dev;
|
||||
@@ -271,7 +272,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 +504,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 +593,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 +646,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 +655,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 +668,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 +1095,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;
|
||||
}
|
||||
|
||||
@@ -632,7 +632,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
||||
} else {
|
||||
if (ip_route_input(skb2, eiph->daddr, eiph->saddr,
|
||||
ip4h_dscp(eiph), skb2->dev) ||
|
||||
skb_dst(skb2)->dev->type != ARPHRD_TUNNEL6)
|
||||
skb_dst_dev(skb2)->type != ARPHRD_TUNNEL6)
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1179,7 +1179,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
|
||||
ndst = dst;
|
||||
}
|
||||
|
||||
tdev = dst->dev;
|
||||
tdev = dst_dev(dst);
|
||||
|
||||
if (tdev == dev) {
|
||||
DEV_STATS_INC(dev, collisions);
|
||||
@@ -1255,7 +1255,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
|
||||
/* 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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
@@ -529,7 +529,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
|
||||
xmit:
|
||||
skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev)));
|
||||
skb_dst_set(skb, dst);
|
||||
skb->dev = skb_dst(skb)->dev;
|
||||
skb->dev = dst_dev(dst);
|
||||
|
||||
err = dst_output(t->net, skb->sk, skb);
|
||||
if (net_xmit_eval(err) == 0)
|
||||
|
||||
@@ -2301,21 +2301,20 @@ static void ip6_mr_output_finish(struct net *net, struct mr_table *mrt,
|
||||
|
||||
int ip6_mr_input(struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
struct net *net = dev_net_rcu(dev);
|
||||
struct mfc6_cache *cache;
|
||||
struct net *net = dev_net(skb->dev);
|
||||
struct mr_table *mrt;
|
||||
struct flowi6 fl6 = {
|
||||
.flowi6_iif = skb->dev->ifindex,
|
||||
.flowi6_iif = dev->ifindex,
|
||||
.flowi6_mark = skb->mark,
|
||||
};
|
||||
int err;
|
||||
struct net_device *dev;
|
||||
|
||||
/* skb->dev passed in is the master dev for vrfs.
|
||||
* Get the proper interface that does have a vif associated with it.
|
||||
*/
|
||||
dev = skb->dev;
|
||||
if (netif_is_l3_master(skb->dev)) {
|
||||
if (netif_is_l3_master(dev)) {
|
||||
dev = dev_get_by_index_rcu(net, IPCB(skb)->iif);
|
||||
if (!dev) {
|
||||
kfree_skb(skb);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -24,7 +24,7 @@ int ip6_route_me_harder(struct net *net, struct sock *sk_partial, struct sk_buff
|
||||
{
|
||||
const struct ipv6hdr *iph = ipv6_hdr(skb);
|
||||
struct sock *sk = sk_to_full_sk(sk_partial);
|
||||
struct net_device *dev = skb_dst(skb)->dev;
|
||||
struct net_device *dev = skb_dst_dev(skb);
|
||||
struct flow_keys flkeys;
|
||||
unsigned int hh_len;
|
||||
struct dst_entry *dst;
|
||||
@@ -72,7 +72,7 @@ int ip6_route_me_harder(struct net *net, struct sock *sk_partial, struct sk_buff
|
||||
#endif
|
||||
|
||||
/* Change in oif may mean change in hh_len. */
|
||||
hh_len = skb_dst(skb)->dev->hard_header_len;
|
||||
hh_len = skb_dst_dev(skb)->hard_header_len;
|
||||
if (skb_headroom(skb) < hh_len &&
|
||||
pskb_expand_head(skb, HH_DATA_ALIGN(hh_len - skb_headroom(skb)),
|
||||
0, GFP_ATOMIC))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -300,7 +300,7 @@ void nf_send_reset6(struct net *net, struct sock *sk, struct sk_buff *oldskb,
|
||||
skb_dst_set(oldskb, dst);
|
||||
}
|
||||
|
||||
fl6.flowi6_oif = l3mdev_master_ifindex(skb_dst(oldskb)->dev);
|
||||
fl6.flowi6_oif = l3mdev_master_ifindex(skb_dst_dev(oldskb));
|
||||
fl6.flowi6_mark = IP6_REPLY_MARK(net, oldskb->mark);
|
||||
security_skb_classify_flow(oldskb, flowi6_to_flowi_common(&fl6));
|
||||
dst = ip6_route_output(net, NULL, &fl6);
|
||||
|
||||
@@ -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();
|
||||
@@ -141,7 +141,7 @@ int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
|
||||
return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
|
||||
net, sk, skb, NULL, skb_dst(skb)->dev,
|
||||
net, sk, skb, NULL, skb_dst_dev(skb),
|
||||
dst_output);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__ip6_local_out);
|
||||
|
||||
@@ -104,11 +104,11 @@ fq_find(struct net *net, __be32 id, const struct ipv6hdr *hdr, int iif)
|
||||
return container_of(q, struct frag_queue, q);
|
||||
}
|
||||
|
||||
static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
|
||||
static int ip6_frag_queue(struct net *net,
|
||||
struct frag_queue *fq, struct sk_buff *skb,
|
||||
struct frag_hdr *fhdr, int nhoff,
|
||||
u32 *prob_offset, int *refs)
|
||||
{
|
||||
struct net *net = dev_net(skb_dst(skb)->dev);
|
||||
int offset, end, fragsize;
|
||||
struct sk_buff *prev_tail;
|
||||
struct net_device *dev;
|
||||
@@ -324,10 +324,10 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *skb,
|
||||
|
||||
static int ipv6_frag_rcv(struct sk_buff *skb)
|
||||
{
|
||||
const struct ipv6hdr *hdr = ipv6_hdr(skb);
|
||||
struct net *net = skb_dst_dev_net(skb);
|
||||
struct frag_hdr *fhdr;
|
||||
struct frag_queue *fq;
|
||||
const struct ipv6hdr *hdr = ipv6_hdr(skb);
|
||||
struct net *net = dev_net(skb_dst(skb)->dev);
|
||||
u8 nexthdr;
|
||||
int iif;
|
||||
|
||||
@@ -384,7 +384,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
|
||||
spin_lock(&fq->q.lock);
|
||||
|
||||
fq->iif = iif;
|
||||
ret = ip6_frag_queue(fq, skb, fhdr, IP6CB(skb)->nhoff,
|
||||
ret = ip6_frag_queue(net, fq, skb, fhdr, IP6CB(skb)->nhoff,
|
||||
&prob_offset, &refs);
|
||||
|
||||
spin_unlock(&fq->q.lock);
|
||||
|
||||
@@ -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)
|
||||
@@ -391,9 +391,8 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
|
||||
static bool __rt6_check_expired(const struct rt6_info *rt)
|
||||
{
|
||||
if (rt->rt6i_flags & RTF_EXPIRES)
|
||||
return time_after(jiffies, rt->dst.expires);
|
||||
else
|
||||
return false;
|
||||
return time_after(jiffies, READ_ONCE(rt->dst.expires));
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool rt6_check_expired(const struct rt6_info *rt)
|
||||
@@ -403,10 +402,10 @@ static bool rt6_check_expired(const struct rt6_info *rt)
|
||||
from = rcu_dereference(rt->from);
|
||||
|
||||
if (rt->rt6i_flags & RTF_EXPIRES) {
|
||||
if (time_after(jiffies, rt->dst.expires))
|
||||
if (time_after(jiffies, READ_ONCE(rt->dst.expires)))
|
||||
return true;
|
||||
} else if (from) {
|
||||
return rt->dst.obsolete != DST_OBSOLETE_FORCE_CHK ||
|
||||
return READ_ONCE(rt->dst.obsolete) != DST_OBSOLETE_FORCE_CHK ||
|
||||
fib6_check_expired(from);
|
||||
}
|
||||
return false;
|
||||
@@ -2134,12 +2133,13 @@ static void rt6_age_examine_exception(struct rt6_exception_bucket *bucket,
|
||||
* expired, independently from their aging, as per RFC 8201 section 4
|
||||
*/
|
||||
if (!(rt->rt6i_flags & RTF_EXPIRES)) {
|
||||
if (time_after_eq(now, rt->dst.lastuse + gc_args->timeout)) {
|
||||
if (time_after_eq(now, READ_ONCE(rt->dst.lastuse) +
|
||||
gc_args->timeout)) {
|
||||
pr_debug("aging clone %p\n", rt);
|
||||
rt6_remove_exception(bucket, rt6_ex);
|
||||
return;
|
||||
}
|
||||
} else if (time_after(jiffies, rt->dst.expires)) {
|
||||
} else if (time_after(jiffies, READ_ONCE(rt->dst.expires))) {
|
||||
pr_debug("purging expired route %p\n", rt);
|
||||
rt6_remove_exception(bucket, rt6_ex);
|
||||
return;
|
||||
@@ -2777,11 +2777,10 @@ static struct dst_entry *rt6_dst_from_check(struct rt6_info *rt,
|
||||
u32 cookie)
|
||||
{
|
||||
if (!__rt6_check_expired(rt) &&
|
||||
rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK &&
|
||||
READ_ONCE(rt->dst.obsolete) == DST_OBSOLETE_FORCE_CHK &&
|
||||
fib6_check(from, cookie))
|
||||
return &rt->dst;
|
||||
else
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INDIRECT_CALLABLE_SCOPE struct dst_entry *ip6_dst_check(struct dst_entry *dst,
|
||||
@@ -2871,7 +2870,7 @@ static void rt6_update_expires(struct rt6_info *rt0, int timeout)
|
||||
rcu_read_lock();
|
||||
from = rcu_dereference(rt0->from);
|
||||
if (from)
|
||||
rt0->dst.expires = from->expires;
|
||||
WRITE_ONCE(rt0->dst.expires, from->expires);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
@@ -2944,7 +2943,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,
|
||||
};
|
||||
|
||||
@@ -3014,7 +3013,7 @@ void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
|
||||
sk_uid(sk));
|
||||
|
||||
dst = __sk_dst_get(sk);
|
||||
if (!dst || !dst->obsolete ||
|
||||
if (!dst || !READ_ONCE(dst->obsolete) ||
|
||||
dst->ops->check(dst, inet6_sk(sk)->dst_cookie))
|
||||
return;
|
||||
|
||||
@@ -3239,7 +3238,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;
|
||||
|
||||
@@ -4302,7 +4301,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,
|
||||
};
|
||||
|
||||
@@ -4588,13 +4587,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);
|
||||
@@ -4631,7 +4631,7 @@ static int ip6_pkt_discard(struct sk_buff *skb)
|
||||
|
||||
static int ip6_pkt_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
skb->dev = skb_dst(skb)->dev;
|
||||
skb->dev = skb_dst_dev(skb);
|
||||
return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES);
|
||||
}
|
||||
|
||||
@@ -4642,7 +4642,7 @@ static int ip6_pkt_prohibit(struct sk_buff *skb)
|
||||
|
||||
static int ip6_pkt_prohibit_out(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
skb->dev = skb_dst(skb)->dev;
|
||||
skb->dev = skb_dst_dev(skb);
|
||||
return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES);
|
||||
}
|
||||
|
||||
@@ -5845,11 +5845,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 (lwtunnel_fill_encap(skb, dst->lwtstate, RTA_ENCAP, RTA_ENCAP_TYPE) < 0)
|
||||
@@ -5904,7 +5907,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
if (rt6_flags & RTF_EXPIRES) {
|
||||
expires = dst ? dst->expires : rt->expires;
|
||||
expires = dst ? READ_ONCE(dst->expires) : rt->expires;
|
||||
expires -= jiffies;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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))) {
|
||||
@@ -362,7 +364,7 @@ static int __seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh,
|
||||
|
||||
#ifdef CONFIG_IPV6_SEG6_HMAC
|
||||
if (sr_has_hmac(isrh)) {
|
||||
struct net *net = dev_net(skb_dst(skb)->dev);
|
||||
struct net *net = skb_dst_dev_net(skb);
|
||||
|
||||
err = seg6_push_hmac(net, &hdr->saddr, isrh);
|
||||
if (unlikely(err))
|
||||
@@ -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:
|
||||
@@ -528,7 +530,7 @@ static int seg6_input_core(struct net *net, struct sock *sk,
|
||||
|
||||
static int seg6_input_nf(struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb_dst(skb)->dev;
|
||||
struct net_device *dev = skb_dst_dev(skb);
|
||||
struct net *net = dev_net(skb->dev);
|
||||
|
||||
switch (skb->protocol) {
|
||||
@@ -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:
|
||||
@@ -614,7 +616,7 @@ static int seg6_output_core(struct net *net, struct sock *sk,
|
||||
|
||||
static int seg6_output_nf(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb_dst(skb)->dev;
|
||||
struct net_device *dev = skb_dst_dev(skb);
|
||||
|
||||
switch (skb->protocol) {
|
||||
case htons(ETH_P_IP):
|
||||
|
||||
@@ -313,7 +313,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;
|
||||
}
|
||||
|
||||
@@ -868,7 +868,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
|
||||
int oif, int rst, u8 tclass, __be32 label,
|
||||
u32 priority, u32 txhash, struct tcp_key *key)
|
||||
{
|
||||
struct net *net = sk ? sock_net(sk) : dev_net_rcu(skb_dst(skb)->dev);
|
||||
struct net *net = sk ? sock_net(sk) : skb_dst_dev_net_rcu(skb);
|
||||
unsigned int tot_len = sizeof(struct tcphdr);
|
||||
struct sock *ctl_sk = net->ipv6.tcp_sk;
|
||||
const struct tcphdr *th = tcp_hdr(skb);
|
||||
@@ -1043,7 +1043,7 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb,
|
||||
if (!sk && !ipv6_unicast_destination(skb))
|
||||
return;
|
||||
|
||||
net = sk ? sock_net(sk) : dev_net_rcu(skb_dst(skb)->dev);
|
||||
net = sk ? sock_net(sk) : skb_dst_dev_net_rcu(skb);
|
||||
/* Invalid TCP option size or twice included auth */
|
||||
if (tcp_parse_auth_options(th, &md5_hash_location, &aoh))
|
||||
return;
|
||||
|
||||
@@ -106,7 +106,7 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
int xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING,
|
||||
net, sk, skb, skb->dev, skb_dst(skb)->dev,
|
||||
net, sk, skb, skb->dev, skb_dst_dev(skb),
|
||||
__xfrm6_output,
|
||||
!(IP6CB(skb)->flags & IP6SKB_REROUTED));
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ __ip_vs_dst_check(struct ip_vs_dest *dest)
|
||||
if (!dest_dst)
|
||||
return NULL;
|
||||
dst = dest_dst->dst_cache;
|
||||
if (dst->obsolete &&
|
||||
if (READ_ONCE(dst->obsolete) &&
|
||||
dst->ops->check(dst, dest_dst->dst_cookie) == NULL)
|
||||
return NULL;
|
||||
return dest_dst;
|
||||
|
||||
@@ -240,7 +240,7 @@ void sctp_transport_set_owner(struct sctp_transport *transport,
|
||||
void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk)
|
||||
{
|
||||
/* If we don't have a fresh route, look one up */
|
||||
if (!transport->dst || transport->dst->obsolete) {
|
||||
if (!transport->dst || READ_ONCE(transport->dst->obsolete)) {
|
||||
sctp_transport_dst_release(transport);
|
||||
transport->af_specific->get_dst(transport, &transport->saddr,
|
||||
&transport->fl, sk);
|
||||
|
||||
@@ -3925,7 +3925,7 @@ static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie)
|
||||
* This will force stale_bundle() to fail on any xdst bundle with
|
||||
* this dst linked in it.
|
||||
*/
|
||||
if (dst->obsolete < 0 && !stale_bundle(dst))
|
||||
if (READ_ONCE(dst->obsolete) < 0 && !stale_bundle(dst))
|
||||
return dst;
|
||||
|
||||
return NULL;
|
||||
@@ -3953,7 +3953,7 @@ static void xfrm_link_failure(struct sk_buff *skb)
|
||||
|
||||
static void xfrm_negative_advice(struct sock *sk, struct dst_entry *dst)
|
||||
{
|
||||
if (dst->obsolete)
|
||||
if (READ_ONCE(dst->obsolete))
|
||||
sk_dst_reset(sk);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user