summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Dichtel <nicolas.dichtel@6wind.com>2019-07-15 06:00:23 -0400
committerSteffen Klassert <steffen.klassert@secunet.com>2019-07-17 04:03:54 -0400
commit22d6552f827ef76ade3edf6bbb3f05048a0a7d8b (patch)
treeeef63032d09302072b65a0b8654460d24c5cc753
parentc5d1030f23002430c2a336b2b629b9d6f72b3564 (diff)
xfrm interface: fix management of phydev
With the current implementation, phydev cannot be removed: $ ip link add dummy type dummy $ ip link add xfrm1 type xfrm dev dummy if_id 1 $ ip l d dummy kernel:[77938.465445] unregister_netdevice: waiting for dummy to become free. Usage count = 1 Manage it like in ip tunnels, ie just keep the ifindex. Not that the side effect, is that the phydev is now optional. Fixes: f203b76d7809 ("xfrm: Add virtual xfrm interfaces") Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Tested-by: Julien Floret <julien.floret@6wind.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
-rw-r--r--include/net/xfrm.h1
-rw-r--r--net/xfrm/xfrm_interface.c32
2 files changed, 17 insertions, 16 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index ad761ef84797..aa08a7a5f6ac 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -990,7 +990,6 @@ struct xfrm_if_parms {
990struct xfrm_if { 990struct xfrm_if {
991 struct xfrm_if __rcu *next; /* next interface in list */ 991 struct xfrm_if __rcu *next; /* next interface in list */
992 struct net_device *dev; /* virtual device associated with interface */ 992 struct net_device *dev; /* virtual device associated with interface */
993 struct net_device *phydev; /* physical device */
994 struct net *net; /* netns for packet i/o */ 993 struct net *net; /* netns for packet i/o */
995 struct xfrm_if_parms p; /* interface parms */ 994 struct xfrm_if_parms p; /* interface parms */
996 995
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
index 53e5e47b2c55..2ab4859df55a 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -175,7 +175,6 @@ static void xfrmi_dev_uninit(struct net_device *dev)
175 struct xfrmi_net *xfrmn = net_generic(xi->net, xfrmi_net_id); 175 struct xfrmi_net *xfrmn = net_generic(xi->net, xfrmi_net_id);
176 176
177 xfrmi_unlink(xfrmn, xi); 177 xfrmi_unlink(xfrmn, xi);
178 dev_put(xi->phydev);
179 dev_put(dev); 178 dev_put(dev);
180} 179}
181 180
@@ -362,7 +361,7 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
362 goto tx_err; 361 goto tx_err;
363 } 362 }
364 363
365 fl.flowi_oif = xi->phydev->ifindex; 364 fl.flowi_oif = xi->p.link;
366 365
367 ret = xfrmi_xmit2(skb, dev, &fl); 366 ret = xfrmi_xmit2(skb, dev, &fl);
368 if (ret < 0) 367 if (ret < 0)
@@ -548,7 +547,7 @@ static int xfrmi_get_iflink(const struct net_device *dev)
548{ 547{
549 struct xfrm_if *xi = netdev_priv(dev); 548 struct xfrm_if *xi = netdev_priv(dev);
550 549
551 return xi->phydev->ifindex; 550 return xi->p.link;
552} 551}
553 552
554 553
@@ -574,12 +573,14 @@ static void xfrmi_dev_setup(struct net_device *dev)
574 dev->needs_free_netdev = true; 573 dev->needs_free_netdev = true;
575 dev->priv_destructor = xfrmi_dev_free; 574 dev->priv_destructor = xfrmi_dev_free;
576 netif_keep_dst(dev); 575 netif_keep_dst(dev);
576
577 eth_broadcast_addr(dev->broadcast);
577} 578}
578 579
579static int xfrmi_dev_init(struct net_device *dev) 580static int xfrmi_dev_init(struct net_device *dev)
580{ 581{
581 struct xfrm_if *xi = netdev_priv(dev); 582 struct xfrm_if *xi = netdev_priv(dev);
582 struct net_device *phydev = xi->phydev; 583 struct net_device *phydev = __dev_get_by_index(xi->net, xi->p.link);
583 int err; 584 int err;
584 585
585 dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); 586 dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
@@ -594,13 +595,19 @@ static int xfrmi_dev_init(struct net_device *dev)
594 595
595 dev->features |= NETIF_F_LLTX; 596 dev->features |= NETIF_F_LLTX;
596 597
597 dev->needed_headroom = phydev->needed_headroom; 598 if (phydev) {
598 dev->needed_tailroom = phydev->needed_tailroom; 599 dev->needed_headroom = phydev->needed_headroom;
600 dev->needed_tailroom = phydev->needed_tailroom;
599 601
600 if (is_zero_ether_addr(dev->dev_addr)) 602 if (is_zero_ether_addr(dev->dev_addr))
601 eth_hw_addr_inherit(dev, phydev); 603 eth_hw_addr_inherit(dev, phydev);
602 if (is_zero_ether_addr(dev->broadcast)) 604 if (is_zero_ether_addr(dev->broadcast))
603 memcpy(dev->broadcast, phydev->broadcast, dev->addr_len); 605 memcpy(dev->broadcast, phydev->broadcast,
606 dev->addr_len);
607 } else {
608 eth_hw_addr_random(dev);
609 eth_broadcast_addr(dev->broadcast);
610 }
604 611
605 return 0; 612 return 0;
606} 613}
@@ -644,13 +651,8 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
644 xi->p = p; 651 xi->p = p;
645 xi->net = net; 652 xi->net = net;
646 xi->dev = dev; 653 xi->dev = dev;
647 xi->phydev = dev_get_by_index(net, p.link);
648 if (!xi->phydev)
649 return -ENODEV;
650 654
651 err = xfrmi_create(dev); 655 err = xfrmi_create(dev);
652 if (err < 0)
653 dev_put(xi->phydev);
654 return err; 656 return err;
655} 657}
656 658