Commit 2e9550ed authored by David S. Miller's avatar David S. Miller

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec

Steffen Klassert says:

====================
pull request (net): ipsec 2019-09-05

1) Several xfrm interface fixes from Nicolas Dichtel:
   - Avoid an interface ID corruption on changelink.
   - Fix wrong intterface names in the logs.
   - Fix a list corruption when changing network namespaces.
   - Fix unregistation of the underying phydev.

2) Fix a potential warning when merging xfrm_plocy nodes.
   From Florian Westphal.

Please pull or let me know if there are problems.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f4b633b9 769a807d
...@@ -983,7 +983,6 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst) ...@@ -983,7 +983,6 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev); void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
struct xfrm_if_parms { struct xfrm_if_parms {
char name[IFNAMSIZ]; /* name of XFRM device */
int link; /* ifindex of underlying L2 interface */ int link; /* ifindex of underlying L2 interface */
u32 if_id; /* interface identifyer */ u32 if_id; /* interface identifyer */
}; };
...@@ -991,7 +990,6 @@ struct xfrm_if_parms { ...@@ -991,7 +990,6 @@ struct xfrm_if_parms {
struct xfrm_if { struct xfrm_if {
struct xfrm_if __rcu *next; /* next interface in list */ struct xfrm_if __rcu *next; /* next interface in list */
struct net_device *dev; /* virtual device associated with interface */ struct net_device *dev; /* virtual device associated with interface */
struct net_device *phydev; /* physical device */
struct net *net; /* netns for packet i/o */ struct net *net; /* netns for packet i/o */
struct xfrm_if_parms p; /* interface parms */ struct xfrm_if_parms p; /* interface parms */
......
...@@ -145,8 +145,6 @@ static int xfrmi_create(struct net_device *dev) ...@@ -145,8 +145,6 @@ static int xfrmi_create(struct net_device *dev)
if (err < 0) if (err < 0)
goto out; goto out;
strcpy(xi->p.name, dev->name);
dev_hold(dev); dev_hold(dev);
xfrmi_link(xfrmn, xi); xfrmi_link(xfrmn, xi);
...@@ -177,7 +175,6 @@ static void xfrmi_dev_uninit(struct net_device *dev) ...@@ -177,7 +175,6 @@ static void xfrmi_dev_uninit(struct net_device *dev)
struct xfrmi_net *xfrmn = net_generic(xi->net, xfrmi_net_id); struct xfrmi_net *xfrmn = net_generic(xi->net, xfrmi_net_id);
xfrmi_unlink(xfrmn, xi); xfrmi_unlink(xfrmn, xi);
dev_put(xi->phydev);
dev_put(dev); dev_put(dev);
} }
...@@ -294,7 +291,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) ...@@ -294,7 +291,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
if (tdev == dev) { if (tdev == dev) {
stats->collisions++; stats->collisions++;
net_warn_ratelimited("%s: Local routing loop detected!\n", net_warn_ratelimited("%s: Local routing loop detected!\n",
xi->p.name); dev->name);
goto tx_err_dst_release; goto tx_err_dst_release;
} }
...@@ -364,7 +361,7 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -364,7 +361,7 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
goto tx_err; goto tx_err;
} }
fl.flowi_oif = xi->phydev->ifindex; fl.flowi_oif = xi->p.link;
ret = xfrmi_xmit2(skb, dev, &fl); ret = xfrmi_xmit2(skb, dev, &fl);
if (ret < 0) if (ret < 0)
...@@ -505,7 +502,7 @@ static int xfrmi_change(struct xfrm_if *xi, const struct xfrm_if_parms *p) ...@@ -505,7 +502,7 @@ static int xfrmi_change(struct xfrm_if *xi, const struct xfrm_if_parms *p)
static int xfrmi_update(struct xfrm_if *xi, struct xfrm_if_parms *p) static int xfrmi_update(struct xfrm_if *xi, struct xfrm_if_parms *p)
{ {
struct net *net = dev_net(xi->dev); struct net *net = xi->net;
struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id); struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);
int err; int err;
...@@ -550,7 +547,7 @@ static int xfrmi_get_iflink(const struct net_device *dev) ...@@ -550,7 +547,7 @@ static int xfrmi_get_iflink(const struct net_device *dev)
{ {
struct xfrm_if *xi = netdev_priv(dev); struct xfrm_if *xi = netdev_priv(dev);
return xi->phydev->ifindex; return xi->p.link;
} }
...@@ -576,12 +573,14 @@ static void xfrmi_dev_setup(struct net_device *dev) ...@@ -576,12 +573,14 @@ static void xfrmi_dev_setup(struct net_device *dev)
dev->needs_free_netdev = true; dev->needs_free_netdev = true;
dev->priv_destructor = xfrmi_dev_free; dev->priv_destructor = xfrmi_dev_free;
netif_keep_dst(dev); netif_keep_dst(dev);
eth_broadcast_addr(dev->broadcast);
} }
static int xfrmi_dev_init(struct net_device *dev) static int xfrmi_dev_init(struct net_device *dev)
{ {
struct xfrm_if *xi = netdev_priv(dev); struct xfrm_if *xi = netdev_priv(dev);
struct net_device *phydev = xi->phydev; struct net_device *phydev = __dev_get_by_index(xi->net, xi->p.link);
int err; int err;
dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
...@@ -596,13 +595,19 @@ static int xfrmi_dev_init(struct net_device *dev) ...@@ -596,13 +595,19 @@ static int xfrmi_dev_init(struct net_device *dev)
dev->features |= NETIF_F_LLTX; dev->features |= NETIF_F_LLTX;
dev->needed_headroom = phydev->needed_headroom; if (phydev) {
dev->needed_tailroom = phydev->needed_tailroom; dev->needed_headroom = phydev->needed_headroom;
dev->needed_tailroom = phydev->needed_tailroom;
if (is_zero_ether_addr(dev->dev_addr)) if (is_zero_ether_addr(dev->dev_addr))
eth_hw_addr_inherit(dev, phydev); eth_hw_addr_inherit(dev, phydev);
if (is_zero_ether_addr(dev->broadcast)) if (is_zero_ether_addr(dev->broadcast))
memcpy(dev->broadcast, phydev->broadcast, dev->addr_len); memcpy(dev->broadcast, phydev->broadcast,
dev->addr_len);
} else {
eth_hw_addr_random(dev);
eth_broadcast_addr(dev->broadcast);
}
return 0; return 0;
} }
...@@ -638,12 +643,6 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev, ...@@ -638,12 +643,6 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
int err; int err;
xfrmi_netlink_parms(data, &p); xfrmi_netlink_parms(data, &p);
if (!tb[IFLA_IFNAME])
return -EINVAL;
nla_strlcpy(p.name, tb[IFLA_IFNAME], IFNAMSIZ);
xi = xfrmi_locate(net, &p); xi = xfrmi_locate(net, &p);
if (xi) if (xi)
return -EEXIST; return -EEXIST;
...@@ -652,13 +651,8 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev, ...@@ -652,13 +651,8 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
xi->p = p; xi->p = p;
xi->net = net; xi->net = net;
xi->dev = dev; xi->dev = dev;
xi->phydev = dev_get_by_index(net, p.link);
if (!xi->phydev)
return -ENODEV;
err = xfrmi_create(dev); err = xfrmi_create(dev);
if (err < 0)
dev_put(xi->phydev);
return err; return err;
} }
...@@ -672,11 +666,11 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[], ...@@ -672,11 +666,11 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct xfrm_if *xi = netdev_priv(dev); struct xfrm_if *xi = netdev_priv(dev);
struct net *net = dev_net(dev); struct net *net = xi->net;
struct xfrm_if_parms p;
xfrmi_netlink_parms(data, &xi->p);
xi = xfrmi_locate(net, &xi->p); xfrmi_netlink_parms(data, &p);
xi = xfrmi_locate(net, &p);
if (!xi) { if (!xi) {
xi = netdev_priv(dev); xi = netdev_priv(dev);
} else { } else {
...@@ -684,7 +678,7 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[], ...@@ -684,7 +678,7 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
return -EEXIST; return -EEXIST;
} }
return xfrmi_update(xi, &xi->p); return xfrmi_update(xi, &p);
} }
static size_t xfrmi_get_size(const struct net_device *dev) static size_t xfrmi_get_size(const struct net_device *dev)
...@@ -715,7 +709,7 @@ static struct net *xfrmi_get_link_net(const struct net_device *dev) ...@@ -715,7 +709,7 @@ static struct net *xfrmi_get_link_net(const struct net_device *dev)
{ {
struct xfrm_if *xi = netdev_priv(dev); struct xfrm_if *xi = netdev_priv(dev);
return dev_net(xi->phydev); return xi->net;
} }
static const struct nla_policy xfrmi_policy[IFLA_XFRM_MAX + 1] = { static const struct nla_policy xfrmi_policy[IFLA_XFRM_MAX + 1] = {
......
...@@ -912,6 +912,7 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net, ...@@ -912,6 +912,7 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net,
} else if (delta > 0) { } else if (delta > 0) {
p = &parent->rb_right; p = &parent->rb_right;
} else { } else {
bool same_prefixlen = node->prefixlen == n->prefixlen;
struct xfrm_policy *tmp; struct xfrm_policy *tmp;
hlist_for_each_entry(tmp, &n->hhead, bydst) { hlist_for_each_entry(tmp, &n->hhead, bydst) {
...@@ -919,9 +920,11 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net, ...@@ -919,9 +920,11 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net,
hlist_del_rcu(&tmp->bydst); hlist_del_rcu(&tmp->bydst);
} }
node->prefixlen = prefixlen;
xfrm_policy_inexact_list_reinsert(net, node, family); xfrm_policy_inexact_list_reinsert(net, node, family);
if (node->prefixlen == n->prefixlen) { if (same_prefixlen) {
kfree_rcu(n, rcu); kfree_rcu(n, rcu);
return; return;
} }
...@@ -929,7 +932,6 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net, ...@@ -929,7 +932,6 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net,
rb_erase(*p, new); rb_erase(*p, new);
kfree_rcu(n, rcu); kfree_rcu(n, rcu);
n = node; n = node;
n->prefixlen = prefixlen;
goto restart; goto restart;
} }
} }
......
...@@ -106,6 +106,13 @@ do_overlap() ...@@ -106,6 +106,13 @@ do_overlap()
# #
# 10.0.0.0/24 and 10.0.1.0/24 nodes have been merged as 10.0.0.0/23. # 10.0.0.0/24 and 10.0.1.0/24 nodes have been merged as 10.0.0.0/23.
ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/23 dir fwd priority 200 action block ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/23 dir fwd priority 200 action block
# similar to above: add policies (with partially random address), with shrinking prefixes.
for p in 29 28 27;do
for k in $(seq 1 32); do
ip -net $ns xfrm policy add src 10.253.1.$((RANDOM%255))/$p dst 10.254.1.$((RANDOM%255))/$p dir fwd priority $((200+k)) action block 2>/dev/null
done
done
} }
do_esp_policy_get_check() { do_esp_policy_get_check() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment