diff options
author | Nicolas Dichtel <nicolas.dichtel@6wind.com> | 2019-07-15 06:00:23 -0400 |
---|---|---|
committer | Steffen Klassert <steffen.klassert@secunet.com> | 2019-07-17 04:03:54 -0400 |
commit | 22d6552f827ef76ade3edf6bbb3f05048a0a7d8b (patch) | |
tree | eef63032d09302072b65a0b8654460d24c5cc753 | |
parent | c5d1030f23002430c2a336b2b629b9d6f72b3564 (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.h | 1 | ||||
-rw-r--r-- | net/xfrm/xfrm_interface.c | 32 |
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 { | |||
990 | struct xfrm_if { | 990 | struct 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 | ||
579 | static int xfrmi_dev_init(struct net_device *dev) | 580 | static 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 | ||