-
Notifications
You must be signed in to change notification settings - Fork 53
Expand file tree
/
Copy pathhoma_pacer.h
More file actions
145 lines (126 loc) · 4.6 KB
/
homa_pacer.h
File metadata and controls
145 lines (126 loc) · 4.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/* SPDX-License-Identifier: BSD-2-Clause or GPL-2.0+ */
/* This file defines structs and functions related to the Homa pacer,
* which implements SRPT for packet output. In order to do that, it
* throttles packet transmission to prevent the buildup of
* large queues in the NIC.
*/
#ifndef _HOMA_PACER_H
#define _HOMA_PACER_H
#include "homa_impl.h"
#include "homa_qdisc.h"
/**
* struct homa_pacer - Contains information that the pacer users to
* manage packet output. There is one instance of this object stored
* in each struct homa.
*/
struct homa_pacer {
/** @homa: Transport that this pacer is associated with. */
struct homa *homa;
/**
* @mutex: Ensures that only one instance of homa_pacer_xmit
* runs at a time. Only used in "try" mode: never block on this.
*/
spinlock_t mutex;
/**
* @fifo_count: When this becomes <= zero, it's time for the
* pacer to allow the oldest RPC to transmit.
*/
int fifo_count;
/**
* @throttle_lock: Used to synchronize access to @throttled_rpcs. Must
* hold when inserting or removing an RPC from throttled_rpcs.
*/
spinlock_t throttle_lock;
/**
* @throttled_rpcs: Contains all homa_rpcs that have bytes ready
* for transmission, but which couldn't be sent without exceeding
* the NIC queue limit.
*/
struct list_head throttled_rpcs;
/**
* @throttle_add: The most recent homa_clock() time when an RPC was
* added to @throttled_rpcs.
*/
u64 throttle_add;
/**
* @cycles_per_mbyte: the number of homa_clock() cycles that it takes to
* transmit 10**6 bytes on our uplink. This is actually a slight
* overestimate of the value, to ensure that we don't underestimate
* NIC queue length and queue too many packets.
*/
u32 cycles_per_mbyte;
/**
* @wait_queue: Used to block the pacer thread when there
* are no throttled RPCs.
*/
struct wait_queue_head wait_queue;
/**
* @kthread: Kernel thread that transmits packets from
* throttled_rpcs in a way that limits queue buildup in the
* NIC.
*/
struct task_struct *kthread;
/**
* @link_idle_time: The homa_clock() time at which we estimate
* that all of the packets we have passed to the NIC for transmission
* will have been transmitted. May be in the past. This estimate
* assumes that only Homa is transmitting data, so it could be a
* severe underestimate if there is competing traffic from, say, TCP.
*/
atomic64_t link_idle_time ____cacheline_aligned_in_smp;
};
struct homa_pacer *homa_pacer_alloc(struct homa *homa);
int homa_pacer_check_nic_q(struct homa_pacer *pacer,
struct sk_buff *skb, bool force);
int homa_pacer_dointvec(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos);
void homa_pacer_free(struct homa_pacer *pacer);
void homa_pacer_unmanage_rpc(struct homa_rpc *rpc);
void homa_pacer_log_throttled(struct homa_pacer *pacer);
int homa_pacer_main(void *transport);
void homa_pacer_manage_rpc(struct homa_rpc *rpc);
void homa_pacer_throttle_lock_slow(struct homa_pacer *pacer);
void homa_pacer_update_sysctl_deps(struct homa_pacer *pacer);
void homa_pacer_xmit(struct homa_pacer *pacer);
/**
* homa_pacer_check() - This method is invoked at various places in Homa to
* see if the pacer needs to transmit more packets and, if so, transmit
* them. It's needed because the pacer thread may get descheduled by
* Linux, result in output stalls.
* @pacer: Pacer information for a Homa transport.
*/
static inline void homa_pacer_check(struct homa_pacer *pacer)
{
if (list_empty(&pacer->throttled_rpcs))
return;
/* The ">> 1" in the line below gives homa_pacer_main the first chance
* to queue new packets; if the NIC queue becomes more than half
* empty, then we will help out here.
*/
if ((homa_clock() + (pacer->homa->qshared->max_nic_est_backlog_cycles >>
1)) < atomic64_read(&pacer->link_idle_time))
return;
tt_record("homa_check_pacer calling homa_pacer_xmit");
homa_pacer_xmit(pacer);
}
/**
* homa_pacer_throttle_lock() - Acquire the throttle lock. If the lock
* isn't immediately available, record stats on the waiting time.
* @pacer: Pacer information for a Homa transport.
*/
static inline void homa_pacer_throttle_lock(struct homa_pacer *pacer)
__acquires(pacer->throttle_lock)
{
if (!spin_trylock_bh(&pacer->throttle_lock))
homa_pacer_throttle_lock_slow(pacer);
}
/**
* homa_pacer_throttle_unlock() - Release the throttle lock.
* @pacer: Pacer information for a Homa transport.
*/
static inline void homa_pacer_throttle_unlock(struct homa_pacer *pacer)
__releases(pacer->throttle_lock)
{
spin_unlock_bh(&pacer->throttle_lock);
}
#endif /* _HOMA_PACER_H */