Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

macvlan: Support for high multicast packet rate

Background:
Broadcast and multicast packages are enqueued for later processing.
This queue was previously hardcoded to 1000.

This proved insufficient for handling very high packet rates.
This resulted in packet drops for multicast.
While at the same time unicast worked fine.

The change:
This patch make the queue length adjustable to accommodate
for environments with very high multicast packet rate.
But still keeps the default value of 1000 unless specified.

The queue length is specified as a request per macvlan
using the IFLA_MACVLAN_BC_QUEUE_LEN parameter.

The actual used queue length will then be the maximum of
any macvlan connected to the same port. The actual used
queue length for the port can be retrieved (read only)
by the IFLA_MACVLAN_BC_QUEUE_LEN_USED parameter for verification.

This will be followed up by a patch to iproute2
in order to adjust the parameter from userspace.

Signed-off-by: Thomas Karlsson <thomas.karlsson@paneda.se>
Link: https://lore.kernel.org/r/dd4673b2-7eab-edda-6815-85c67ce87f63@paneda.se
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Thomas Karlsson and committed by
Jakub Kicinski
d4bff72c cec85994

+43 -2
+38 -2
drivers/net/macvlan.c
··· 35 35 36 36 #define MACVLAN_HASH_BITS 8 37 37 #define MACVLAN_HASH_SIZE (1<<MACVLAN_HASH_BITS) 38 - #define MACVLAN_BC_QUEUE_LEN 1000 38 + #define MACVLAN_DEFAULT_BC_QUEUE_LEN 1000 39 39 40 40 #define MACVLAN_F_PASSTHRU 1 41 41 #define MACVLAN_F_ADDRCHANGE 2 ··· 46 46 struct list_head vlans; 47 47 struct sk_buff_head bc_queue; 48 48 struct work_struct bc_work; 49 + u32 bc_queue_len_used; 49 50 u32 flags; 50 51 int count; 51 52 struct hlist_head vlan_source_hash[MACVLAN_HASH_SIZE]; ··· 68 67 #define MACVLAN_SKB_CB(__skb) ((struct macvlan_skb_cb *)&((__skb)->cb[0])) 69 68 70 69 static void macvlan_port_destroy(struct net_device *dev); 70 + static void update_port_bc_queue_len(struct macvlan_port *port); 71 71 72 72 static inline bool macvlan_passthru(const struct macvlan_port *port) 73 73 { ··· 356 354 MACVLAN_SKB_CB(nskb)->src = src; 357 355 358 356 spin_lock(&port->bc_queue.lock); 359 - if (skb_queue_len(&port->bc_queue) < MACVLAN_BC_QUEUE_LEN) { 357 + if (skb_queue_len(&port->bc_queue) < port->bc_queue_len_used) { 360 358 if (src) 361 359 dev_hold(src->dev); 362 360 __skb_queue_tail(&port->bc_queue, nskb); ··· 1220 1218 for (i = 0; i < MACVLAN_HASH_SIZE; i++) 1221 1219 INIT_HLIST_HEAD(&port->vlan_source_hash[i]); 1222 1220 1221 + port->bc_queue_len_used = 0; 1223 1222 skb_queue_head_init(&port->bc_queue); 1224 1223 INIT_WORK(&port->bc_work, macvlan_process_broadcast); 1225 1224 ··· 1489 1486 goto destroy_macvlan_port; 1490 1487 } 1491 1488 1489 + vlan->bc_queue_len_req = MACVLAN_DEFAULT_BC_QUEUE_LEN; 1490 + if (data && data[IFLA_MACVLAN_BC_QUEUE_LEN]) 1491 + vlan->bc_queue_len_req = nla_get_u32(data[IFLA_MACVLAN_BC_QUEUE_LEN]); 1492 + 1492 1493 err = register_netdevice(dev); 1493 1494 if (err < 0) 1494 1495 goto destroy_macvlan_port; ··· 1503 1496 goto unregister_netdev; 1504 1497 1505 1498 list_add_tail_rcu(&vlan->list, &port->vlans); 1499 + update_port_bc_queue_len(vlan->port); 1506 1500 netif_stacked_transfer_operstate(lowerdev, dev); 1507 1501 linkwatch_fire_event(dev); 1508 1502 ··· 1537 1529 if (vlan->mode == MACVLAN_MODE_SOURCE) 1538 1530 macvlan_flush_sources(vlan->port, vlan); 1539 1531 list_del_rcu(&vlan->list); 1532 + update_port_bc_queue_len(vlan->port); 1540 1533 unregister_netdevice_queue(dev, head); 1541 1534 netdev_upper_dev_unlink(vlan->lowerdev, dev); 1542 1535 } ··· 1581 1572 } 1582 1573 vlan->flags = flags; 1583 1574 } 1575 + 1576 + if (data && data[IFLA_MACVLAN_BC_QUEUE_LEN]) { 1577 + vlan->bc_queue_len_req = nla_get_u32(data[IFLA_MACVLAN_BC_QUEUE_LEN]); 1578 + update_port_bc_queue_len(vlan->port); 1579 + } 1580 + 1584 1581 if (set_mode) 1585 1582 vlan->mode = mode; 1586 1583 if (data && data[IFLA_MACVLAN_MACADDR_MODE]) { ··· 1617 1602 + nla_total_size(2) /* IFLA_MACVLAN_FLAGS */ 1618 1603 + nla_total_size(4) /* IFLA_MACVLAN_MACADDR_COUNT */ 1619 1604 + macvlan_get_size_mac(vlan) /* IFLA_MACVLAN_MACADDR */ 1605 + + nla_total_size(4) /* IFLA_MACVLAN_BC_QUEUE_LEN */ 1606 + + nla_total_size(4) /* IFLA_MACVLAN_BC_QUEUE_LEN_USED */ 1620 1607 ); 1621 1608 } 1622 1609 ··· 1642 1625 const struct net_device *dev) 1643 1626 { 1644 1627 struct macvlan_dev *vlan = netdev_priv(dev); 1628 + struct macvlan_port *port = vlan->port; 1645 1629 int i; 1646 1630 struct nlattr *nest; 1647 1631 ··· 1663 1645 } 1664 1646 nla_nest_end(skb, nest); 1665 1647 } 1648 + if (nla_put_u32(skb, IFLA_MACVLAN_BC_QUEUE_LEN, vlan->bc_queue_len_req)) 1649 + goto nla_put_failure; 1650 + if (nla_put_u32(skb, IFLA_MACVLAN_BC_QUEUE_LEN_USED, port->bc_queue_len_used)) 1651 + goto nla_put_failure; 1666 1652 return 0; 1667 1653 1668 1654 nla_put_failure: ··· 1680 1658 [IFLA_MACVLAN_MACADDR] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, 1681 1659 [IFLA_MACVLAN_MACADDR_DATA] = { .type = NLA_NESTED }, 1682 1660 [IFLA_MACVLAN_MACADDR_COUNT] = { .type = NLA_U32 }, 1661 + [IFLA_MACVLAN_BC_QUEUE_LEN] = { .type = NLA_U32 }, 1662 + [IFLA_MACVLAN_BC_QUEUE_LEN_USED] = { .type = NLA_REJECT }, 1683 1663 }; 1684 1664 1685 1665 int macvlan_link_register(struct rtnl_link_ops *ops) ··· 1711 1687 .get_link_net = macvlan_get_link_net, 1712 1688 .priv_size = sizeof(struct macvlan_dev), 1713 1689 }; 1690 + 1691 + static void update_port_bc_queue_len(struct macvlan_port *port) 1692 + { 1693 + u32 max_bc_queue_len_req = 0; 1694 + struct macvlan_dev *vlan; 1695 + 1696 + list_for_each_entry(vlan, &port->vlans, list) { 1697 + if (vlan->bc_queue_len_req > max_bc_queue_len_req) 1698 + max_bc_queue_len_req = vlan->bc_queue_len_req; 1699 + } 1700 + port->bc_queue_len_used = max_bc_queue_len_req; 1701 + } 1714 1702 1715 1703 static int macvlan_device_event(struct notifier_block *unused, 1716 1704 unsigned long event, void *ptr)
+1
include/linux/if_macvlan.h
··· 30 30 enum macvlan_mode mode; 31 31 u16 flags; 32 32 unsigned int macaddr_count; 33 + u32 bc_queue_len_req; 33 34 #ifdef CONFIG_NET_POLL_CONTROLLER 34 35 struct netpoll *netpoll; 35 36 #endif
+2
include/uapi/linux/if_link.h
··· 588 588 IFLA_MACVLAN_MACADDR, 589 589 IFLA_MACVLAN_MACADDR_DATA, 590 590 IFLA_MACVLAN_MACADDR_COUNT, 591 + IFLA_MACVLAN_BC_QUEUE_LEN, 592 + IFLA_MACVLAN_BC_QUEUE_LEN_USED, 591 593 __IFLA_MACVLAN_MAX, 592 594 }; 593 595
+2
tools/include/uapi/linux/if_link.h
··· 409 409 IFLA_MACVLAN_MACADDR, 410 410 IFLA_MACVLAN_MACADDR_DATA, 411 411 IFLA_MACVLAN_MACADDR_COUNT, 412 + IFLA_MACVLAN_BC_QUEUE_LEN, 413 + IFLA_MACVLAN_BC_QUEUE_LEN_USED, 412 414 __IFLA_MACVLAN_MAX, 413 415 }; 414 416