Skip to content

Commit

Permalink
net: Enable Tx queue selection based on Rx queues
Browse files Browse the repository at this point in the history
This patch adds support to pick Tx queue based on the Rx queue(s) map
configuration set by the admin through the sysfs attribute
for each Tx queue. If the user configuration for receive queue(s) map
does not apply, then the Tx queue selection falls back to CPU(s) map
based selection and finally to hashing.

Signed-off-by: Amritha Nambiar <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
anambiarin authored and davem330 committed Jul 2, 2018
1 parent c6345ce commit fc9bab2
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 17 deletions.
10 changes: 10 additions & 0 deletions include/net/sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -1730,6 +1730,16 @@ static inline void sk_rx_queue_clear(struct sock *sk)
#endif
}

#ifdef CONFIG_XPS
static inline int sk_rx_queue_get(const struct sock *sk)
{
if (sk && sk->sk_rx_queue_mapping != NO_QUEUE_MAPPING)
return sk->sk_rx_queue_mapping;

return -1;
}
#endif

static inline void sk_set_socket(struct sock *sk, struct socket *sock)
{
sk_tx_queue_clear(sk);
Expand Down
62 changes: 45 additions & 17 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -3459,35 +3459,63 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
}
#endif /* CONFIG_NET_EGRESS */

static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
#ifdef CONFIG_XPS
static int __get_xps_queue_idx(struct net_device *dev, struct sk_buff *skb,
struct xps_dev_maps *dev_maps, unsigned int tci)
{
struct xps_map *map;
int queue_index = -1;

if (dev->num_tc) {
tci *= dev->num_tc;
tci += netdev_get_prio_tc_map(dev, skb->priority);
}

map = rcu_dereference(dev_maps->attr_map[tci]);
if (map) {
if (map->len == 1)
queue_index = map->queues[0];
else
queue_index = map->queues[reciprocal_scale(
skb_get_hash(skb), map->len)];
if (unlikely(queue_index >= dev->real_num_tx_queues))
queue_index = -1;
}
return queue_index;
}
#endif

static int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
{
#ifdef CONFIG_XPS
struct xps_dev_maps *dev_maps;
struct xps_map *map;
struct sock *sk = skb->sk;
int queue_index = -1;

if (!static_key_false(&xps_needed))
return -1;

rcu_read_lock();
dev_maps = rcu_dereference(dev->xps_cpus_map);
if (!static_key_false(&xps_rxqs_needed))
goto get_cpus_map;

dev_maps = rcu_dereference(dev->xps_rxqs_map);
if (dev_maps) {
unsigned int tci = skb->sender_cpu - 1;
int tci = sk_rx_queue_get(sk);

if (dev->num_tc) {
tci *= dev->num_tc;
tci += netdev_get_prio_tc_map(dev, skb->priority);
}
if (tci >= 0 && tci < dev->num_rx_queues)
queue_index = __get_xps_queue_idx(dev, skb, dev_maps,
tci);
}

map = rcu_dereference(dev_maps->attr_map[tci]);
if (map) {
if (map->len == 1)
queue_index = map->queues[0];
else
queue_index = map->queues[reciprocal_scale(skb_get_hash(skb),
map->len)];
if (unlikely(queue_index >= dev->real_num_tx_queues))
queue_index = -1;
get_cpus_map:
if (queue_index < 0) {
dev_maps = rcu_dereference(dev->xps_cpus_map);
if (dev_maps) {
unsigned int tci = skb->sender_cpu - 1;

queue_index = __get_xps_queue_idx(dev, skb, dev_maps,
tci);
}
}
rcu_read_unlock();
Expand Down

0 comments on commit fc9bab2

Please sign in to comment.