mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 20:54:03 +02:00
ip6gre: avoid tx_error when sending MLD/DAD on external tunnels
similarly to what has been done with commit 9d149045b3 ("geneve: change
from tx_error to tx_dropped on missing metadata"), avoid reporting errors
to userspace in case the kernel doesn't find any tunnel information for a
skb that is going to be transmitted: an increase of tx_dropped is enough.
tested with the following script:
# for t in ip6gre ip6gretap ip6erspan; do
> ip link add dev gre6-test0 type $t external
> ip address add dev gre6-test0 2001:db8::1/64
> ip link set dev gre6-test0 up
> sleep 30
> ip -s -j link show dev gre6-test0 | jq \
> '.[0].stats64.tx | {"errors": .errors, "dropped": .dropped}'
> ip link del dev gre6-test0
> done
Reported-by: Jianlin Shi <jishi@redhat.com>
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
be589d0428
commit
e5f7e211b6
|
|
@ -707,6 +707,17 @@ static int prepare_ip6gre_xmit_ipv6(struct sk_buff *skb,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct ip_tunnel_info *skb_tunnel_info_txcheck(struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
struct ip_tunnel_info *tun_info;
|
||||||
|
|
||||||
|
tun_info = skb_tunnel_info(skb);
|
||||||
|
if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX)))
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
return tun_info;
|
||||||
|
}
|
||||||
|
|
||||||
static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
|
static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
|
||||||
struct net_device *dev, __u8 dsfield,
|
struct net_device *dev, __u8 dsfield,
|
||||||
struct flowi6 *fl6, int encap_limit,
|
struct flowi6 *fl6, int encap_limit,
|
||||||
|
|
@ -734,10 +745,9 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
|
||||||
const struct ip_tunnel_key *key;
|
const struct ip_tunnel_key *key;
|
||||||
__be16 flags;
|
__be16 flags;
|
||||||
|
|
||||||
tun_info = skb_tunnel_info(skb);
|
tun_info = skb_tunnel_info_txcheck(skb);
|
||||||
if (unlikely(!tun_info ||
|
if (IS_ERR(tun_info) ||
|
||||||
!(tun_info->mode & IP_TUNNEL_INFO_TX) ||
|
unlikely(ip_tunnel_info_af(tun_info) != AF_INET6))
|
||||||
ip_tunnel_info_af(tun_info) != AF_INET6))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
key = &tun_info->key;
|
key = &tun_info->key;
|
||||||
|
|
@ -908,7 +918,8 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
|
|
||||||
tx_err:
|
tx_err:
|
||||||
stats->tx_errors++;
|
if (!t->parms.collect_md || !IS_ERR(skb_tunnel_info_txcheck(skb)))
|
||||||
|
stats->tx_errors++;
|
||||||
stats->tx_dropped++;
|
stats->tx_dropped++;
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
|
|
@ -917,6 +928,7 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,
|
||||||
static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
|
static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
|
||||||
struct net_device *dev)
|
struct net_device *dev)
|
||||||
{
|
{
|
||||||
|
struct ip_tunnel_info *tun_info = NULL;
|
||||||
struct ip6_tnl *t = netdev_priv(dev);
|
struct ip6_tnl *t = netdev_priv(dev);
|
||||||
struct dst_entry *dst = skb_dst(skb);
|
struct dst_entry *dst = skb_dst(skb);
|
||||||
struct net_device_stats *stats;
|
struct net_device_stats *stats;
|
||||||
|
|
@ -964,15 +976,13 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
|
||||||
* for native mode, call prepare_ip6gre_xmit_{ipv4,ipv6}.
|
* for native mode, call prepare_ip6gre_xmit_{ipv4,ipv6}.
|
||||||
*/
|
*/
|
||||||
if (t->parms.collect_md) {
|
if (t->parms.collect_md) {
|
||||||
struct ip_tunnel_info *tun_info;
|
|
||||||
const struct ip_tunnel_key *key;
|
const struct ip_tunnel_key *key;
|
||||||
struct erspan_metadata *md;
|
struct erspan_metadata *md;
|
||||||
__be32 tun_id;
|
__be32 tun_id;
|
||||||
|
|
||||||
tun_info = skb_tunnel_info(skb);
|
tun_info = skb_tunnel_info_txcheck(skb);
|
||||||
if (unlikely(!tun_info ||
|
if (IS_ERR(tun_info) ||
|
||||||
!(tun_info->mode & IP_TUNNEL_INFO_TX) ||
|
unlikely(ip_tunnel_info_af(tun_info) != AF_INET6))
|
||||||
ip_tunnel_info_af(tun_info) != AF_INET6))
|
|
||||||
goto tx_err;
|
goto tx_err;
|
||||||
|
|
||||||
key = &tun_info->key;
|
key = &tun_info->key;
|
||||||
|
|
@ -1065,7 +1075,8 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
|
||||||
|
|
||||||
tx_err:
|
tx_err:
|
||||||
stats = &t->dev->stats;
|
stats = &t->dev->stats;
|
||||||
stats->tx_errors++;
|
if (!IS_ERR(tun_info))
|
||||||
|
stats->tx_errors++;
|
||||||
stats->tx_dropped++;
|
stats->tx_dropped++;
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user