Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2e61bca

Browse files
Implement homa_qdisc_check_pacer
This gets throughput with homa_qdisc almost (1% less than) throughput with the old pacer.
1 parent fe0b430 commit 2e61bca

File tree

4 files changed

+131
-1
lines changed

4 files changed

+131
-1
lines changed

homa_offload.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "homa_impl.h"
88
#include "homa_offload.h"
99
#include "homa_pacer.h"
10+
#include "homa_qdisc.h"
1011

1112
DEFINE_PER_CPU(struct homa_offload_core, homa_offload_core);
1213

@@ -467,6 +468,7 @@ struct sk_buff *homa_gro_receive(struct list_head *held_list,
467468

468469
done:
469470
homa_pacer_check(homa->pacer);
471+
homa_qdisc_pacer_check(homa);
470472
offload_core->last_gro = homa_clock();
471473
return result;
472474

homa_qdisc.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,45 @@ int homa_qdisc_redirect_skb(struct sk_buff *skb,
816816
return result;
817817
}
818818

819+
/**
820+
* homa_qdisc_pacer_check() - Check whether any of the homa_qdisc pacer
821+
* threads associated with @homa have fallen behind (e.g. because they
822+
* got descheduled by Linux). If so, call the pacer directly to transmit
823+
* deferred packets.
824+
* @homa: Overall information about the Homa transport; used to find
825+
* homa_qdisc_devs to check.
826+
*/
827+
void homa_qdisc_pacer_check(struct homa *homa) {
828+
struct homa_qdisc_qdevs *qdevs;
829+
struct homa_qdisc_dev *qdev;
830+
u64 now = homa_clock();
831+
int num_qdevs, i;
832+
int max_cycles;
833+
834+
max_cycles = homa->pacer->max_nic_queue_cycles;
835+
qdevs = homa->qdevs;
836+
rcu_read_lock();
837+
num_qdevs = READ_ONCE(qdevs->num_qdevs);
838+
for (i = 0; i < num_qdevs; i++) {
839+
qdev = qdevs->qdevs[i];
840+
if (!homa_qdisc_any_deferred(qdev))
841+
continue;
842+
843+
/* The ">> 1" means that we only help out if the NIC queue has
844+
* dropped below half of its maximum allowed capacity. This
845+
* gives the pacer thread the first shot at queuting new
846+
* packets.
847+
*/
848+
if (now + (max_cycles >> 1) <
849+
atomic64_read(&qdev->link_idle_time))
850+
continue;
851+
tt_record("homa_qdisc_pacer_check calling homa_qdisc_pacer");
852+
homa_qdisc_pacer(qdev);
853+
INC_METRIC(pacer_needed_help, 1);
854+
}
855+
rcu_read_unlock();
856+
}
857+
819858
/**
820859
* homa_qdisc_update_sysctl() - Recompute information in a homa_qdisc_dev
821860
* that depends on sysctl parameters.

homa_qdisc.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ int homa_qdisc_init(struct Qdisc *sch, struct nlattr *opt,
216216
struct netlink_ext_ack *extack);
217217
void homa_qdisc_insert_rb(struct homa_qdisc_dev *qdev,
218218
struct homa_rpc *rpc);
219+
void homa_qdisc_pacer(struct homa_qdisc_dev *qdev);
220+
void homa_qdisc_pacer_check(struct homa *homa);
219221
int homa_qdisc_pacer_main(void *device);
220222
struct homa_qdisc_dev *
221223
homa_qdisc_qdev_get(struct net_device *dev);
@@ -230,7 +232,6 @@ void homa_qdisc_update_all_sysctl(struct homa_net *hnet);
230232
int homa_qdisc_update_link_idle(struct homa_qdisc_dev *qdev,
231233
int bytes, int max_queue_ns);
232234
void homa_qdisc_update_sysctl(struct homa_qdisc_dev *qdev);
233-
void homa_qdisc_pacer(struct homa_qdisc_dev *qdev);
234235
void homa_rcu_kfree(void *object);
235236
void homa_rcu_kfree_callback(struct rcu_head *head);
236237

test/unit_homa_qdisc.c

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,6 +1478,94 @@ TEST_F(homa_qdisc, homa_qdisc_redirect_skb__no_suitable_qdisc)
14781478
homa_qdisc_destroy(self->qdiscs[i]);
14791479
}
14801480

1481+
TEST_F(homa_qdisc, homa_qdisc_pacer_check__enqueue_packet)
1482+
{
1483+
struct homa_qdisc_dev *qdev, *qdev2;
1484+
struct homa_rpc *srpc;
1485+
1486+
/* Create 2 qdevs to verify that homa_qdisc_pacer_check loops over
1487+
* all qdevs.
1488+
*/
1489+
qdev2 = homa_qdisc_qdev_get(mock_dev(1, &self->homa));
1490+
qdev = homa_qdisc_qdev_get(self->dev);
1491+
srpc = unit_server_rpc(&self->hsk, UNIT_OUTGOING, &self->client_ip,
1492+
&self->server_ip, self->client_port,
1493+
self->server_id, 10000, 10000);
1494+
ASSERT_NE(NULL, srpc);
1495+
EXPECT_EQ(0, homa_qdisc_init(self->qdiscs[3], NULL, NULL));
1496+
qdev->pacer_qix = 3;
1497+
EXPECT_EQ(0, self->qdiscs[3]->q.qlen);
1498+
homa_qdisc_defer_homa(qdev, new_test_skb(srpc, &self->addr, 0, 1000));
1499+
EXPECT_TRUE(homa_qdisc_any_deferred(qdev));
1500+
1501+
atomic64_set(&qdev->link_idle_time, 20000);
1502+
mock_clock = 15000;
1503+
self->homa.pacer->max_nic_queue_cycles = 12000;
1504+
1505+
homa_qdisc_pacer_check(&self->homa);
1506+
EXPECT_EQ(1, self->qdiscs[3]->q.qlen);
1507+
EXPECT_FALSE(homa_qdisc_any_deferred(qdev));
1508+
EXPECT_EQ(1, homa_metrics_per_cpu()->pacer_needed_help);
1509+
1510+
homa_qdisc_destroy(self->qdiscs[3]);
1511+
homa_qdisc_qdev_put(qdev);
1512+
homa_qdisc_qdev_put(qdev2);
1513+
}
1514+
TEST_F(homa_qdisc, homa_qdisc_pacer_check__no_deferred_rpcs)
1515+
{
1516+
struct homa_qdisc_dev *qdev, *qdev2;
1517+
1518+
/* Create 2 qdevs to verify that homa_qdisc_pacer_check loops over
1519+
* all qdevs.
1520+
*/
1521+
qdev2 = homa_qdisc_qdev_get(mock_dev(1, &self->homa));
1522+
qdev = homa_qdisc_qdev_get(self->dev);
1523+
EXPECT_EQ(0, homa_qdisc_init(self->qdiscs[3], NULL, NULL));
1524+
qdev->pacer_qix = 3;
1525+
EXPECT_EQ(0, self->qdiscs[3]->q.qlen);
1526+
1527+
atomic64_set(&qdev->link_idle_time, 20000);
1528+
mock_clock = 15000;
1529+
self->homa.pacer->max_nic_queue_cycles = 12000;
1530+
1531+
homa_qdisc_pacer_check(&self->homa);
1532+
EXPECT_EQ(0, self->qdiscs[3]->q.qlen);
1533+
EXPECT_FALSE(homa_qdisc_any_deferred(qdev));
1534+
EXPECT_EQ(0, homa_metrics_per_cpu()->pacer_needed_help);
1535+
1536+
homa_qdisc_destroy(self->qdiscs[3]);
1537+
homa_qdisc_qdev_put(qdev);
1538+
homa_qdisc_qdev_put(qdev2);
1539+
}
1540+
TEST_F(homa_qdisc, homa_qdisc_pacer_check__lag_not_long_enough)
1541+
{
1542+
struct homa_qdisc_dev *qdev;
1543+
struct homa_rpc *srpc;
1544+
1545+
qdev = homa_qdisc_qdev_get(self->dev);
1546+
srpc = unit_server_rpc(&self->hsk, UNIT_OUTGOING, &self->client_ip,
1547+
&self->server_ip, self->client_port,
1548+
self->server_id, 10000, 10000);
1549+
ASSERT_NE(NULL, srpc);
1550+
EXPECT_EQ(0, homa_qdisc_init(self->qdiscs[3], NULL, NULL));
1551+
qdev->pacer_qix = 3;
1552+
EXPECT_EQ(0, self->qdiscs[3]->q.qlen);
1553+
homa_qdisc_defer_homa(qdev, new_test_skb(srpc, &self->addr, 0, 1000));
1554+
EXPECT_TRUE(homa_qdisc_any_deferred(qdev));
1555+
1556+
atomic64_set(&qdev->link_idle_time, 20000);
1557+
mock_clock = 13000;
1558+
self->homa.pacer->max_nic_queue_cycles = 12000;
1559+
1560+
homa_qdisc_pacer_check(&self->homa);
1561+
EXPECT_EQ(0, self->qdiscs[3]->q.qlen);
1562+
EXPECT_TRUE(homa_qdisc_any_deferred(qdev));
1563+
EXPECT_EQ(0, homa_metrics_per_cpu()->pacer_needed_help);
1564+
1565+
homa_qdisc_destroy(self->qdiscs[3]);
1566+
homa_qdisc_qdev_put(qdev);
1567+
}
1568+
14811569
TEST_F(homa_qdisc, homa_qdisc_update_sysctl__basics)
14821570
{
14831571
struct homa_qdisc_dev *qdev;

0 commit comments

Comments
 (0)