Skip to content

Commit d4bff72

Browse files
tkarlskuba-moo
authored andcommitted
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent cec8599 commit d4bff72

4 files changed

Lines changed: 43 additions & 2 deletions

File tree

drivers/net/macvlan.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
#define MACVLAN_HASH_BITS 8
3737
#define MACVLAN_HASH_SIZE (1<<MACVLAN_HASH_BITS)
38-
#define MACVLAN_BC_QUEUE_LEN 1000
38+
#define MACVLAN_DEFAULT_BC_QUEUE_LEN 1000
3939

4040
#define MACVLAN_F_PASSTHRU 1
4141
#define MACVLAN_F_ADDRCHANGE 2
@@ -46,6 +46,7 @@ struct macvlan_port {
4646
struct list_head vlans;
4747
struct sk_buff_head bc_queue;
4848
struct work_struct bc_work;
49+
u32 bc_queue_len_used;
4950
u32 flags;
5051
int count;
5152
struct hlist_head vlan_source_hash[MACVLAN_HASH_SIZE];
@@ -67,6 +68,7 @@ struct macvlan_skb_cb {
6768
#define MACVLAN_SKB_CB(__skb) ((struct macvlan_skb_cb *)&((__skb)->cb[0]))
6869

6970
static void macvlan_port_destroy(struct net_device *dev);
71+
static void update_port_bc_queue_len(struct macvlan_port *port);
7072

7173
static inline bool macvlan_passthru(const struct macvlan_port *port)
7274
{
@@ -354,7 +356,7 @@ static void macvlan_broadcast_enqueue(struct macvlan_port *port,
354356
MACVLAN_SKB_CB(nskb)->src = src;
355357

356358
spin_lock(&port->bc_queue.lock);
357-
if (skb_queue_len(&port->bc_queue) < MACVLAN_BC_QUEUE_LEN) {
359+
if (skb_queue_len(&port->bc_queue) < port->bc_queue_len_used) {
358360
if (src)
359361
dev_hold(src->dev);
360362
__skb_queue_tail(&port->bc_queue, nskb);
@@ -1218,6 +1220,7 @@ static int macvlan_port_create(struct net_device *dev)
12181220
for (i = 0; i < MACVLAN_HASH_SIZE; i++)
12191221
INIT_HLIST_HEAD(&port->vlan_source_hash[i]);
12201222

1223+
port->bc_queue_len_used = 0;
12211224
skb_queue_head_init(&port->bc_queue);
12221225
INIT_WORK(&port->bc_work, macvlan_process_broadcast);
12231226

@@ -1486,6 +1489,10 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
14861489
goto destroy_macvlan_port;
14871490
}
14881491

1492+
vlan->bc_queue_len_req = MACVLAN_DEFAULT_BC_QUEUE_LEN;
1493+
if (data && data[IFLA_MACVLAN_BC_QUEUE_LEN])
1494+
vlan->bc_queue_len_req = nla_get_u32(data[IFLA_MACVLAN_BC_QUEUE_LEN]);
1495+
14891496
err = register_netdevice(dev);
14901497
if (err < 0)
14911498
goto destroy_macvlan_port;
@@ -1496,6 +1503,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
14961503
goto unregister_netdev;
14971504

14981505
list_add_tail_rcu(&vlan->list, &port->vlans);
1506+
update_port_bc_queue_len(vlan->port);
14991507
netif_stacked_transfer_operstate(lowerdev, dev);
15001508
linkwatch_fire_event(dev);
15011509

@@ -1529,6 +1537,7 @@ void macvlan_dellink(struct net_device *dev, struct list_head *head)
15291537
if (vlan->mode == MACVLAN_MODE_SOURCE)
15301538
macvlan_flush_sources(vlan->port, vlan);
15311539
list_del_rcu(&vlan->list);
1540+
update_port_bc_queue_len(vlan->port);
15321541
unregister_netdevice_queue(dev, head);
15331542
netdev_upper_dev_unlink(vlan->lowerdev, dev);
15341543
}
@@ -1572,6 +1581,12 @@ static int macvlan_changelink(struct net_device *dev,
15721581
}
15731582
vlan->flags = flags;
15741583
}
1584+
1585+
if (data && data[IFLA_MACVLAN_BC_QUEUE_LEN]) {
1586+
vlan->bc_queue_len_req = nla_get_u32(data[IFLA_MACVLAN_BC_QUEUE_LEN]);
1587+
update_port_bc_queue_len(vlan->port);
1588+
}
1589+
15751590
if (set_mode)
15761591
vlan->mode = mode;
15771592
if (data && data[IFLA_MACVLAN_MACADDR_MODE]) {
@@ -1602,6 +1617,8 @@ static size_t macvlan_get_size(const struct net_device *dev)
16021617
+ nla_total_size(2) /* IFLA_MACVLAN_FLAGS */
16031618
+ nla_total_size(4) /* IFLA_MACVLAN_MACADDR_COUNT */
16041619
+ macvlan_get_size_mac(vlan) /* IFLA_MACVLAN_MACADDR */
1620+
+ nla_total_size(4) /* IFLA_MACVLAN_BC_QUEUE_LEN */
1621+
+ nla_total_size(4) /* IFLA_MACVLAN_BC_QUEUE_LEN_USED */
16051622
);
16061623
}
16071624

@@ -1625,6 +1642,7 @@ static int macvlan_fill_info(struct sk_buff *skb,
16251642
const struct net_device *dev)
16261643
{
16271644
struct macvlan_dev *vlan = netdev_priv(dev);
1645+
struct macvlan_port *port = vlan->port;
16281646
int i;
16291647
struct nlattr *nest;
16301648

@@ -1645,6 +1663,10 @@ static int macvlan_fill_info(struct sk_buff *skb,
16451663
}
16461664
nla_nest_end(skb, nest);
16471665
}
1666+
if (nla_put_u32(skb, IFLA_MACVLAN_BC_QUEUE_LEN, vlan->bc_queue_len_req))
1667+
goto nla_put_failure;
1668+
if (nla_put_u32(skb, IFLA_MACVLAN_BC_QUEUE_LEN_USED, port->bc_queue_len_used))
1669+
goto nla_put_failure;
16481670
return 0;
16491671

16501672
nla_put_failure:
@@ -1658,6 +1680,8 @@ static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
16581680
[IFLA_MACVLAN_MACADDR] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
16591681
[IFLA_MACVLAN_MACADDR_DATA] = { .type = NLA_NESTED },
16601682
[IFLA_MACVLAN_MACADDR_COUNT] = { .type = NLA_U32 },
1683+
[IFLA_MACVLAN_BC_QUEUE_LEN] = { .type = NLA_U32 },
1684+
[IFLA_MACVLAN_BC_QUEUE_LEN_USED] = { .type = NLA_REJECT },
16611685
};
16621686

16631687
int macvlan_link_register(struct rtnl_link_ops *ops)
@@ -1688,6 +1712,18 @@ static struct rtnl_link_ops macvlan_link_ops = {
16881712
.priv_size = sizeof(struct macvlan_dev),
16891713
};
16901714

1715+
static void update_port_bc_queue_len(struct macvlan_port *port)
1716+
{
1717+
u32 max_bc_queue_len_req = 0;
1718+
struct macvlan_dev *vlan;
1719+
1720+
list_for_each_entry(vlan, &port->vlans, list) {
1721+
if (vlan->bc_queue_len_req > max_bc_queue_len_req)
1722+
max_bc_queue_len_req = vlan->bc_queue_len_req;
1723+
}
1724+
port->bc_queue_len_used = max_bc_queue_len_req;
1725+
}
1726+
16911727
static int macvlan_device_event(struct notifier_block *unused,
16921728
unsigned long event, void *ptr)
16931729
{

include/linux/if_macvlan.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ struct macvlan_dev {
3030
enum macvlan_mode mode;
3131
u16 flags;
3232
unsigned int macaddr_count;
33+
u32 bc_queue_len_req;
3334
#ifdef CONFIG_NET_POLL_CONTROLLER
3435
struct netpoll *netpoll;
3536
#endif

include/uapi/linux/if_link.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,8 @@ enum {
588588
IFLA_MACVLAN_MACADDR,
589589
IFLA_MACVLAN_MACADDR_DATA,
590590
IFLA_MACVLAN_MACADDR_COUNT,
591+
IFLA_MACVLAN_BC_QUEUE_LEN,
592+
IFLA_MACVLAN_BC_QUEUE_LEN_USED,
591593
__IFLA_MACVLAN_MAX,
592594
};
593595

tools/include/uapi/linux/if_link.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,8 @@ enum {
409409
IFLA_MACVLAN_MACADDR,
410410
IFLA_MACVLAN_MACADDR_DATA,
411411
IFLA_MACVLAN_MACADDR_COUNT,
412+
IFLA_MACVLAN_BC_QUEUE_LEN,
413+
IFLA_MACVLAN_BC_QUEUE_LEN_USED,
412414
__IFLA_MACVLAN_MAX,
413415
};
414416

0 commit comments

Comments
 (0)