-
Notifications
You must be signed in to change notification settings - Fork 4
/
ccp_priv.h
286 lines (248 loc) · 7.48 KB
/
ccp_priv.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
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
#ifndef CCP_PRIV_H
#define CCP_PRIV_H
#include "ccp.h"
#include "serialize.h"
#ifdef __KERNEL__
#include <linux/kernel.h>
#else
#include <stdio.h>
#endif
#ifdef __KERNEL__
#define FMT_U64 "%llu"
#define FMT_U32 "%lu"
#else
#if defined(__APPLE__)
#define FMT_U64 "%llu"
#else
#define FMT_U64 "%lu"
#endif
#define FMT_U32 "%u"
#endif
#ifdef __KERNEL__
#define __INLINE__ inline
#define __CALLOC__(num_elements, block_size) kcalloc(num_elements, block_size, GFP_KERNEL)
#define __FREE__(ptr) kfree(ptr)
#define CAS(a,o,n) cmpxchg(a,o,n) == o
#else
#define __INLINE__
#define __CALLOC__(num_elements, block_size) calloc(num_elements, block_size)
#define __FREE__(ptr) free(ptr)
#define CAS(a,o,n) __sync_bool_compare_and_swap(a,o,n)
#endif
#define log_fmt(level, fmt, args...) {\
char msg[80]; \
int __ok = snprintf((char*) &msg, 80, fmt, ## args); \
if (__ok >= 0) { \
datapath->log(datapath, level, (const char*) &msg, __ok); \
} \
}
// __LOG_INFO__ is default
#define libccp_trace(fmt, args...)
#define libccp_debug(fmt, args...)
#define libccp_info(fmt, args...) log_fmt(INFO, fmt, ## args)
#define libccp_warn(fmt, args...) log_fmt(WARN, fmt, ## args)
#define libccp_error(fmt, args...) log_fmt(ERROR, fmt, ## args)
#ifdef __LOG_TRACE__
#undef libccp_trace
#define libccp_trace(fmt, args...) log_fmt(TRACE, fmt, ## args)
#undef libccp_debug
#define libccp_debug(fmt, args...) log_fmt(DEBUG, fmt, ## args)
#endif
#ifdef __LOG_DEBUG__
#undef libccp_debug
#define libccp_debug(fmt, args...) log_fmt(DEBUG, fmt, ## args)
#endif
#ifdef __LOG_WARN__
#undef libccp_info
#define libccp_info(fmt, args...)
#endif
#ifdef __LOG_ERROR__
#undef libccp_info
#define libccp_info(fmt, args...)
#undef libccp_warn
#define libccp_warn(fmt, args...)
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Triggers the state machine that goes through the expressions and evaluates conditions if true.
* Should be called on each tick of the ACK clock; i.e. every packet.
*/
int state_machine(
struct ccp_connection *conn
);
struct Register {
u8 type;
int index;
u64 value;
};
struct Instruction64 {
u8 op;
struct Register rRet;
struct Register rLeft;
struct Register rRight;
};
/* Expression contains reference to:
* instructions for condition
* instructions for body of expression
*/
struct Expression {
u32 cond_start_idx;
u32 num_cond_instrs;
u32 event_start_idx;
u32 num_event_instrs;
};
/* Entire datapath program
* a set of expressions (conditions)
* a set of instructions
*/
struct DatapathProgram {
u8 num_to_return;
u16 index; // index in array
u32 program_uid; // program uid assigned by CCP agent
u32 num_expressions;
u32 num_instructions;
struct Expression expressions[MAX_EXPRESSIONS];
struct Instruction64 fold_instructions[MAX_INSTRUCTIONS];
};
int read_expression(
struct Expression *ret,
struct ExpressionMsg *msg
);
int read_instruction(
struct Instruction64 *ret,
struct InstructionMsg *msg
);
struct register_file {
// report and control registers - users send a DEF for these
u64 report_registers[MAX_REPORT_REG]; // reported variables, reset to DEF value upon report
u64 control_registers[MAX_CONTROL_REG]; // extra user defined variables, not reset on report
// tmp, local and implicit registers
u64 impl_registers[MAX_IMPLICIT_REG]; // stores special flags and variables
u64 tmp_registers[MAX_TMP_REG]; // used for temporary calculation in instructions
u64 local_registers[MAX_LOCAL_REG]; // for local variables within a program - created in a bind in a when clause
};
struct staged_update {
bool control_is_pending[MAX_CONTROL_REG];
u64 control_registers[MAX_CONTROL_REG];
bool impl_is_pending[MAX_IMPLICIT_REG];
u64 impl_registers[MAX_IMPLICIT_REG];
};
/* libccp Private State
* struct ccp_connection has a void* state to store libccp's state
* libccp internally casts this to a struct ccp_priv_state*.
*/
struct ccp_priv_state {
bool sent_create;
u64 implicit_time_zero; // can be reset
u16 program_index; // index into program array
int staged_program_index;
struct register_file registers;
struct staged_update pending_update;
};
/*
* Resets a specific register's value in response to an update field message.
* Needs pointer to ccp_connection in case message is for updating the cwnd or rate.
*/
int update_register(
struct ccp_connection* conn,
struct ccp_priv_state *state,
struct UpdateField *update_field
);
/* Reset the output state registers to their default values
* according to the DEF instruction preamble.
*/
void reset_state(struct ccp_datapath *datapath, struct ccp_priv_state *state);
/* Initializes the control registers to their default values
* according to the DEF instruction preamble.
*/
void init_register_state(struct ccp_datapath *datapath, struct ccp_priv_state *state);
/* Reset the implicit time registers to count from datapath->now()
*/
void reset_time(struct ccp_datapath *datapath, struct ccp_priv_state *state);
/* Initialize send machine and measurement machine state in ccp_connection.
* Called from ccp_connection_start()
*/
int init_ccp_priv_state(struct ccp_datapath *datapath, struct ccp_connection *conn);
/* Free the allocated flow memory.
* Call when the flow has ended.
*/
void free_ccp_priv_state(struct ccp_connection *conn);
// send create message to CCP
int send_conn_create(
struct ccp_datapath *datapath,
struct ccp_connection *conn
);
// send measure message to CCP
int send_measurement(
struct ccp_connection *conn,
u32 program_uid,
u64 *fields,
u8 num_fields
);
/* Retrieve the private state from ccp_connection.
*/
__INLINE__ struct ccp_priv_state *get_ccp_priv_state(struct ccp_connection *conn);
/* Lookup a datapath program, available to all flows
*/
struct DatapathProgram* datapath_program_lookup(struct ccp_datapath *datapath, u16 pid);
/*
* Reserved Implicit Registers
*/
#define EXPR_FLAG_REG 0
#define SHOULD_FALLTHROUGH_REG 1
#define SHOULD_REPORT_REG 2
#define US_ELAPSED_REG 3
#define CWND_REG 4
#define RATE_REG 5
/*
* Primitive registers
*/
#define ACK_BYTES_ACKED 0
#define ACK_BYTES_MISORDERED 1
#define ACK_ECN_BYTES 2
#define ACK_ECN_PACKETS 3
#define ACK_LOST_PKTS_SAMPLE 4
#define ACK_NOW 5
#define ACK_PACKETS_ACKED 6
#define ACK_PACKETS_MISORDERED 7
#define FLOW_BYTES_IN_FLIGHT 8
#define FLOW_BYTES_PENDING 9
#define FLOW_PACKETS_IN_FLIGHT 10
#define FLOW_RATE_INCOMING 11
#define FLOW_RATE_OUTGOING 12
#define FLOW_RTT_SAMPLE_US 13
#define FLOW_WAS_TIMEOUT 14
/*
* Operations
*/
#define ADD 0
#define BIND 1
#define DEF 2
#define DIV 3
#define EQUIV 4
#define EWMA 5
#define GT 6
#define IF 7
#define LT 8
#define MAX 9
#define MAXWRAP 10
#define MIN 11
#define MUL 12
#define NOTIF 13
#define SUB 14
#define MAX_OP 15
// types of registers
#define NONVOLATILE_CONTROL_REG 0
#define IMMEDIATE_REG 1
#define IMPLICIT_REG 2
#define LOCAL_REG 3
#define PRIMITIVE_REG 4
#define VOLATILE_REPORT_REG 5
#define NONVOLATILE_REPORT_REG 6
#define TMP_REG 7
#define VOLATILE_CONTROL_REG 8
#ifdef __cplusplus
} // extern "C"
#endif
#endif