• Paolo Abeni's avatar
    ipvlan: use per device spinlock to protect addrs list updates · 82308194
    Paolo Abeni authored
    This changeset moves ipvlan address under RCU protection, using
    a per ipvlan device spinlock to protect list mutation and RCU
    read access to protect list traversal.
    
    Also explicitly use RCU read lock to traverse the per port
    ipvlans list, so that we can now perform a full address lookup
    without asserting the RTNL lock.
    
    Overall this allows the ipvlan driver to check fully for duplicate
    addresses - before this commit ipv6 addresses assigned by autoconf
    via prefix delegation where accepted without any check - and avoid
    the following rntl assertion failure still in the same code path:
    
     RTNL: assertion failed at drivers/net/ipvlan/ipvlan_core.c (124)
     WARNING: CPU: 15 PID: 0 at drivers/net/ipvlan/ipvlan_core.c:124 ipvlan_addr_busy+0x97/0xa0 [ipvlan]
     Modules linked in: ipvlan(E) ixgbe
     CPU: 15 PID: 0 Comm: swapper/15 Tainted: G            E    4.16.0-rc2.ipvlan+ #1782
     Hardware name: Dell Inc. PowerEdge R730/072T6D, BIOS 2.1.7 06/16/2016
     RIP: 0010:ipvlan_addr_busy+0x97/0xa0 [ipvlan]
     RSP: 0018:ffff881ff9e03768 EFLAGS: 00010286
     RAX: 0000000000000000 RBX: ffff881fdf2a9000 RCX: 0000000000000000
     RDX: 0000000000000001 RSI: 00000000000000f6 RDI: 0000000000000300
     RBP: ffff881fdf2a8000 R08: 0000000000000000 R09: 0000000000000000
     R10: 0000000000000001 R11: ffff881ff9e034c0 R12: ffff881fe07bcc00
     R13: 0000000000000001 R14: ffffffffa02002b0 R15: 0000000000000001
     FS:  0000000000000000(0000) GS:ffff881ff9e00000(0000) knlGS:0000000000000000
     CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
     CR2: 00007fc5c1a4f248 CR3: 000000207e012005 CR4: 00000000001606e0
     Call Trace:
      <IRQ>
      ipvlan_addr6_event+0x6c/0xd0 [ipvlan]
      notifier_call_chain+0x49/0x90
      atomic_notifier_call_chain+0x6a/0x100
      ipv6_add_addr+0x5f9/0x720
      addrconf_prefix_rcv_add_addr+0x244/0x3c0
      addrconf_prefix_rcv+0x2f3/0x790
      ndisc_router_discovery+0x633/0xb70
      ndisc_rcv+0x155/0x180
      icmpv6_rcv+0x4ac/0x5f0
      ip6_input_finish+0x138/0x6a0
      ip6_input+0x41/0x1f0
      ipv6_rcv+0x4db/0x8d0
      __netif_receive_skb_core+0x3d5/0xe40
      netif_receive_skb_internal+0x89/0x370
      napi_gro_receive+0x14f/0x1e0
      ixgbe_clean_rx_irq+0x4ce/0x1020 [ixgbe]
      ixgbe_poll+0x31a/0x7a0 [ixgbe]
      net_rx_action+0x296/0x4f0
      __do_softirq+0xcf/0x4f5
      irq_exit+0xf5/0x110
      do_IRQ+0x62/0x110
      common_interrupt+0x91/0x91
      </IRQ>
    
     v1 -> v2: drop unneeded in_softirq check in ipvlan_addr6_validator_event()
    
    Fixes: e9997c29 ("ipvlan: fix check for IP addresses in control path")
    Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    82308194
ipvlan_core.c 19.2 KB