aboutsummaryrefslogtreecommitdiffstats
path: root/cicn-plugin/cicn/cicn_infra.h
blob: 39bf9b59fc26c5b99934f800161fb18969382701 (plain)
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
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
/*
 * Copyright (c) 2017 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * plugin infrastructure: global data structure, common definitions,
 * statistics, etc
 */
#ifndef _CICN_INFRA_H_
#define _CICN_INFRA_H_ 1

#if !CICN_VPP_PLUGIN
#error "cicn-internal file included externally"
#endif

typedef int (*test_cicn_api_handler_fn) (test_cicn_api_op_t *
					 test_cicn_api_op);

// cicn plugin global state: see also
// - icnfwd_runtime_s for per-worker state
// - fib and pits
typedef struct cicn_main_s
{
  /* Binary API message ID base */
  u16 msg_id_base;

  /* Have we been enabled */
  u16 is_enabled;

  /* Convenience */
  vlib_main_t *vlib_main;
  vnet_main_t *vnet_main;

  /* Global FIB instance */
  cicn_fib_t fib;

  /* Info about vpp worker threads, used in our packet distribution node */
  u32 shard_count;		// 1 in single-threaded or 1 worker mode: see worker_count
  u32 worker_count;		// 0 in single-threaded case: see shard_count
  u32 worker_first_index;

  /* Node index for forwarder node in dpdk worker handoff context */
  u32 fwd_next_node;

  /* Global PIT lifetime info */
  uint64_t pit_lifetime_dflt_ms;
  uint64_t pit_lifetime_min_ms;
  uint64_t pit_lifetime_max_ms;

  /* Global ICN Hello Protocol Polling Interval */
  f64 cicn_hello_interval;

  /* The name of the ICN Hello Protocol Interests */
  cicn_hello_name_t hello_name;

  /* Is Hello Protocol polling interval set from cli/api? */
  u32 cicn_hello_interval_cfgd;

  /* Next node id for Hello Interests */
  u32 cicn_hello_next_node_id;

  /* Array of ICN Adjacencies indexed by faceid */
  cicn_hello_adj_t cicn_hello_adjs[CICN_PARAM_FACES_MAX];

  /* Array of ICN Hello data by faceid */
  cicn_hello_data cicn_hello_data_array[CICN_PARAM_FACES_MAX];

  /* Number of active adjacencies */
  u32 n_active_hello_adjs;

  uword *cicn_rc_strings;	// to print string forms of return codes

  /* Event subscribers' info */
  i32 n_face_event_subscribers;
    vl_api_cicn_api_face_events_subscribe_t
    face_event_subscribers[CICN_PARAM_API_EVENT_SUBSCRIBERS_MAX];

  /* Have we been enabled for packet-generation? */
  u32 pgen_enabled;

  /* pgen client side */
  /*   Source and destination info */
  u32 pgen_clt_src_addr;
  int pgen_clt_src_port;
  u32 pgen_clt_dest_addr;
  int pgen_clt_dest_port;

  /* pgen server side */
  /*     Have we enabled the packet generator server? */
  u32 pgen_svr_enabled;

  /*     Arbitrary content */
  u32 pgen_svr_buffer_idx;

  test_cicn_api_handler_fn test_cicn_api_handler;
} cicn_main_t;

extern cicn_main_t cicn_main;

static inline char *
cicn_sstrncpy (char *dst, const char *src, size_t n)
{
  char *res = strncpy (dst, src, n);
  dst[n - 1] = '\000';
  return (res);
}

/* Forwarder's name data structure */
typedef struct cicn_infra_fwdr_name_s
{
  uint64_t fn_match_pfx_hash;	// hash of fname's relevant pfx for match
  int fn_reply_payload_flen;	// total bytes in reply payload
#define CICN_FWDR_NAME_BUFSIZE 200
  uint8_t fn_reply_payload[CICN_FWDR_NAME_BUFSIZE];	// wire-fmt reply payload
  cicn_prefix_hashinf_t fn_hashinf;	// hash of fname components
  char fn_str[CICN_FWDR_NAME_BUFSIZE];	// fname ascii version for output
} cicn_infra_fwdr_name_t;

/* Global name of the forwarder */
extern cicn_infra_fwdr_name_t cicn_infra_fwdr_name;

extern int cicn_infra_fwdr_initialized;

/*
 * Generation numbers for coordination between config changes and running
 * worker threads. Certain configuration changes (deletes, especially)
 * cause the master config generation to increment. Each worker checks the
 * master value and updates its own dedicated value as it begins each
 * frame of work. We hope this allows us to safely integrate configuration
 * changes without more costly synchronization.
 */

/* Each value is actually a stand-alone cache line in size, so that
 * the worker threads don't have to be entangled trying to make high-rate
 * updates to shared cache lines.
 */
typedef struct cicn_infra_shard_s
{
  volatile uint64_t cfg_generation;
  uint64_t _extra[7];
  cicn_face_stats_t face_stats[CICN_PARAM_FACES_MAX];
} cicn_infra_shard_t;

/* Global generation value, updated for (some? all?) config changes */
extern cicn_infra_shard_t cicn_infra_gshard;

#define CICN_INFRA_CFG_GEN_INCR() (cicn_infra_gshard.cfg_generation++)

/* VPP >= 17.04 supports clone-based replication */
#define CICN_INFRA_CLONE_REPLICATION 1

/* Fixed array for worker threads, to be indexed by worker index */
#define CICN_INFRA_WORKERS_MAX  24
extern cicn_infra_shard_t cicn_infra_shards[CICN_INFRA_WORKERS_MAX];

/* Per shard limits */
uint32_t cicn_infra_shard_pit_size;
uint32_t cicn_infra_shard_cs_size;

/* cicn-owned return code for cases where unix rc are insufficient */
#define foreach_cicn_rc							\
_(OK, 0, "ok")								\
_(FACE_UNKNOWN, 1, "face unknown")					\
_(FIB_PFX_COMP_LIMIT, 2, "fib prefix too man components")		\
_(FIB_PFX_SIZE_LIMIT, 3, "fib prefix too long")				\
_(FIB_NHOP_LIMIT, 4, "fib next hop limit exceeded")

typedef enum
{
#define _(a,b,c) CICN_RC_##a = b,
  foreach_cicn_rc
#undef _
} cicn_rc_e;

struct cicn_rd_s
{
  cicn_rc_e rd_cicn_rc;
  int rd_ux_rc;
};

static inline void
cicn_rd_set (cicn_rd_t * cicn_rd, cicn_rc_e cicn_rc, int ux_rc)
{
  cicn_rd->rd_cicn_rc = cicn_rc;
  cicn_rd->rd_ux_rc = ux_rc;
}

/*
 * Printable error representation
 */
const char *cicn_rc_str (cicn_rc_e crc);

const char *cicn_rd_str (cicn_rd_t * cicn_rd);

/*
 * wrapped timer sequence package (increment, comparison)
 */

/*
 * wrappable counter math (assumed uint16_t): return sum of addends
 */
static inline uint16_t
cicn_infra_seq16_sum (uint16_t addend1, uint16_t addend2)
{
  return (addend1 + addend2);
}

/*
 * for comparing wrapping numbers, return lt,eq,gt 0 for a lt,eq,gt b
 */
static inline int
cicn_infra_seq16_cmp (uint16_t a, uint16_t b)
{
  return ((int16_t) (a - b));
}

/*
 * below are wrappers for lt, le, gt, ge seq16 comparators
 */
static inline int
cicn_infra_seq16_lt (uint16_t a, uint16_t b)
{
  return (cicn_infra_seq16_cmp (a, b) < 0);
}

static inline int
cicn_infra_seq16_le (uint16_t a, uint16_t b)
{
  return (cicn_infra_seq16_cmp (a, b) <= 0);
}

static inline int
cicn_infra_seq16_gt (uint16_t a, uint16_t b)
{
  return (cicn_infra_seq16_cmp (a, b) > 0);
}

static inline int
cicn_infra_seq16_ge (uint16_t a, uint16_t b)
{
  return (cicn_infra_seq16_cmp (a, b) >= 0);
}

/* Definitions and Forward refs for the time counters we're trying out.
 * Counters are maintained by the background process.
 */
#define SEC_MS 1000
#define CICN_INFRA_FAST_TIMER_SECS  1
#define CICN_INFRA_FAST_TIMER_MSECS (CICN_INFRA_FAST_TIMER_SECS * SEC_MS)
#define CICN_INFRA_SLOW_TIMER_SECS  60
#define CICN_INFRA_SLOW_TIMER_MSECS (CICN_INFRA_SLOW_TIMER_SECS * SEC_MS)

extern uint16_t cicn_infra_fast_timer;	/* Counts at 1 second intervals */
extern uint16_t cicn_infra_slow_timer;	/* Counts at 1 minute intervals */

/*
 * Utilities to convert lifetime into expiry time based on
 * compressed clock, suitable for the opportunistic hashtable
 * entry timeout processing.
 */

// convert time in msec to time in clicks
static inline uint16_t
cicn_infra_ms2clicks (uint64_t time_ms, uint64_t ms_per_click)
{
  f64 time_clicks =
    ((f64) (time_ms + ms_per_click - 1)) / ((f64) ms_per_click);
  return ((uint16_t) time_clicks);
}

static inline uint16_t
cicn_infra_get_fast_exp_time (uint64_t lifetime_ms)
{
  uint16_t lifetime_clicks =
    cicn_infra_ms2clicks (lifetime_ms, CICN_INFRA_FAST_TIMER_MSECS);
  return (cicn_infra_seq16_sum (cicn_infra_fast_timer, lifetime_clicks));
}

static inline uint16_t
cicn_infra_get_slow_exp_time (uint64_t lifetime_ms)
{
  uint16_t lifetime_clicks =
    cicn_infra_ms2clicks (lifetime_ms, CICN_INFRA_SLOW_TIMER_MSECS);
  return (cicn_infra_seq16_sum (cicn_infra_slow_timer, lifetime_clicks));
}

int
cicn_infra_plugin_enable_disable (int enable_disable,
				  int fib_max_size,
				  int pit_max_size,
				  f64 pit_dflt_lifetime_sec_req,
				  f64 pit_min_lifetime_sec_req,
				  f64 pit_max_lifetime_sec_req,
				  int cs_max_size);

/* First versions of the ICN nodes: the forwarder node, the work-distributor
 * node and the packet-generator client and server nodes
 */
extern vlib_node_registration_t icnfwd_node;
extern vlib_node_registration_t icndist_node;
extern vlib_node_registration_t icn_pg_node;
extern vlib_node_registration_t icn_pg_server_node;

#endif // _CICN_INFRA_H_