-
Notifications
You must be signed in to change notification settings - Fork 45
/
homa_peer.h
254 lines (219 loc) · 7.5 KB
/
homa_peer.h
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
/* SPDX-License-Identifier: BSD-2-Clause */
/* This file contains definitions related to managing peers (homa_peer
* and homa_peertab).
*/
#ifndef _HOMA_PEER_H
#define _HOMA_PEER_H
#include "homa_wire.h"
#include "homa_sock.h"
struct homa_rpc;
/**
* struct homa_dead_dst - Used to retain dst_entries that are no longer
* needed, until it is safe to delete them (I'm not confident that the RCU
* mechanism will be safe for these: the reference count could get incremented
* after it's on the RCU list?).
*/
struct homa_dead_dst {
/** @dst: Entry that is no longer used by a struct homa_peer. */
struct dst_entry *dst;
/**
* @gc_time: Time (in units of get_cycles) when it is safe
* to free @dst.
*/
__u64 gc_time;
/** @dst_links: Used to link together entries in peertab->dead_dsts. */
struct list_head dst_links;
};
/**
* define HOMA_PEERTAB_BUCKETS - Number of bits in the bucket index for a
* homa_peertab. Should be large enough to hold an entry for every server
* in a datacenter without long hash chains.
*/
#define HOMA_PEERTAB_BUCKET_BITS 16
/** define HOME_PEERTAB_BUCKETS - Number of buckets in a homa_peertab. */
#define HOMA_PEERTAB_BUCKETS (1 << HOMA_PEERTAB_BUCKET_BITS)
/**
* struct homa_peertab - A hash table that maps from IPv6 addresses
* to homa_peer objects. IPv4 entries are encapsulated as IPv6 addresses.
* Entries are gradually added to this table, but they are never removed
* except when the entire table is deleted. We can't safely delete because
* results returned by homa_peer_find may be retained indefinitely.
*
* This table is managed exclusively by homa_peertab.c, using RCU to
* permit efficient lookups.
*/
struct homa_peertab {
/**
* @write_lock: Synchronizes addition of new entries; not needed
* for lookups (RCU is used instead).
*/
spinlock_t write_lock;
/**
* @dead_dsts: List of dst_entries that are waiting to be deleted.
* Hold @write_lock when manipulating.
*/
struct list_head dead_dsts;
/**
* @buckets: Pointer to heads of chains of homa_peers for each bucket.
* Malloc-ed, and must eventually be freed. NULL means this structure
* has not been initialized.
*/
struct hlist_head *buckets;
};
/**
* struct homa_peer - One of these objects exists for each machine that we
* have communicated with (either as client or server).
*/
struct homa_peer {
/**
* @addr: IPv6 address for the machine (IPv4 addresses are stored
* as IPv4-mapped IPv6 addresses).
*/
struct in6_addr addr;
/** @flow: Addressing info needed to send packets. */
struct flowi flow;
/**
* @dst: Used to route packets to this peer; we own a reference
* to this, which we must eventually release.
*/
struct dst_entry *dst;
/**
* @unsched_cutoffs: priorities to use for unscheduled packets
* sent to this host, as specified in the most recent CUTOFFS
* packet from that host. See documentation for @homa.unsched_cutoffs
* for the meanings of these values.
*/
int unsched_cutoffs[HOMA_MAX_PRIORITIES];
/**
* @cutoff_version: value of cutoff_version in the most recent
* CUTOFFS packet received from this peer. 0 means we haven't
* yet received a CUTOFFS packet from the host. Note that this is
* stored in network byte order.
*/
__be16 cutoff_version;
/**
* last_update_jiffies: time in jiffies when we sent the most
* recent CUTOFFS packet to this peer.
*/
unsigned long last_update_jiffies;
/**
* grantable_rpcs: Contains all homa_rpcs (both requests and
* responses) involving this peer whose msgins require (or required
* them in the past) and have not been fully received. The list is
* sorted in priority order (head has fewest bytes_remaining).
* Locked with homa->grantable_lock.
*/
struct list_head grantable_rpcs;
/**
* @grantable_links: Used to link this peer into homa->grantable_peers.
* If this RPC is not linked into homa->grantable_peers, this is an
* empty list pointing to itself.
*/
struct list_head grantable_links;
/**
* @peertab_links: Links this object into a bucket of its
* homa_peertab.
*/
struct hlist_node peertab_links;
/**
* @outstanding_resends: the number of resend requests we have
* sent to this server (spaced @homa.resend_interval apart) since
* we received a packet from this peer.
*/
int outstanding_resends;
/**
* @most_recent_resend: @homa->timer_ticks when the most recent
* resend was sent to this peer.
*/
int most_recent_resend;
/**
* @least_recent_rpc: of all the RPCs for this peer scanned at
* @current_ticks, this is the RPC whose @resend_timer_ticks
* is farthest in the past.
*/
struct homa_rpc *least_recent_rpc;
/**
* @least_recent_ticks: the @resend_timer_ticks value for
* @least_recent_rpc.
*/
__u32 least_recent_ticks;
/**
* @current_ticks: the value of @homa->timer_ticks the last time
* that @least_recent_rpc and @least_recent_ticks were computed.
* Used to detect the start of a new homa_timer pass.
*/
__u32 current_ticks;
/**
* @resend_rpc: the value of @least_recent_rpc computed in the
* previous homa_timer pass. This RPC will be issued a RESEND
* in the current pass, if it still needs one.
*/
struct homa_rpc *resend_rpc;
/**
* @num_acks: the number of (initial) entries in @acks that
* currently hold valid information.
*/
int num_acks;
/**
* @acks: info about client RPCs whose results have been completely
* received.
*/
struct homa_ack acks[HOMA_MAX_ACKS_PER_PKT];
/**
* @ack_lock: used to synchronize access to @num_acks and @acks.
*/
spinlock_t ack_lock;
};
extern void homa_dst_refresh(struct homa_peertab *peertab,
struct homa_peer *peer, struct homa_sock *hsk);
extern void homa_peertab_destroy(struct homa_peertab *peertab);
extern struct homa_peer **
homa_peertab_get_peers(struct homa_peertab *peertab,
int *num_peers);
extern int homa_peertab_init(struct homa_peertab *peertab);
extern void homa_peer_add_ack(struct homa_rpc *rpc);
extern struct homa_peer
*homa_peer_find(struct homa_peertab *peertab,
const struct in6_addr *addr, struct inet_sock *inet);
extern int homa_peer_get_acks(struct homa_peer *peer, int count,
struct homa_ack *dst);
extern struct dst_entry
*homa_peer_get_dst(struct homa_peer *peer,
struct inet_sock *inet);
extern void homa_peer_lock_slow(struct homa_peer *peer);
extern void homa_peer_set_cutoffs(struct homa_peer *peer, int c0, int c1,
int c2, int c3, int c4, int c5, int c6, int c7);
extern void homa_peertab_gc_dsts(struct homa_peertab *peertab, __u64 now);
/**
* homa_peer_lock() - Acquire the lock for a peer's @unacked_lock. If the lock
* isn't immediately available, record stats on the waiting time.
* @peer: Peer to lock.
*/
static inline void homa_peer_lock(struct homa_peer *peer)
{
if (!spin_trylock_bh(&peer->ack_lock))
homa_peer_lock_slow(peer);
}
/**
* homa_peer_unlock() - Release the lock for a peer's @unacked_lock.
* @peer: Peer to lock.
*/
static inline void homa_peer_unlock(struct homa_peer *peer)
{
spin_unlock_bh(&peer->ack_lock);
}
/**
* homa_get_dst() - Returns destination information associated with a peer,
* updating it if the cached information is stale.
* @peer: Peer whose destination information is desired.
* @hsk: Homa socket; needed by lower-level code to recreate the dst.
* Return Up-to-date destination for peer.
*/
static inline struct dst_entry *homa_get_dst(struct homa_peer *peer,
struct homa_sock *hsk)
{
if (unlikely(peer->dst->obsolete > 0))
homa_dst_refresh(hsk->homa->peers, peer, hsk);
return peer->dst;
}
#endif /* _HOMA_PEER_H */