FD.io VPP  v18.01.2-1-g9b554f3
Vector Packet Processing
kp_cli.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Intel and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "POD IS" BPODIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <kubeproxy/kp.h>
17 
18 
19 static clib_error_t *
21  unformat_input_t * input, vlib_cli_command_t * cmd)
22 {
23  unformat_input_t _line_input, *line_input = &_line_input;
24  ip46_address_t prefix;
25  u8 plen;
26  u32 new_len = 1024;
27  u32 port = 0;
28  u32 target_port = 0;
29  u32 node_port = 0;
30  u32 del = 0;
31  int ret;
32  u32 nat4 = 0;
33  kp_vip_type_t type;
34  clib_error_t *error = 0;
35 
36  if (!unformat_user (input, unformat_line_input, line_input))
37  return 0;
38 
39  if (!unformat(line_input, "%U", unformat_ip46_prefix, &prefix, &plen, IP46_TYPE_ANY, &plen)) {
40  error = clib_error_return (0, "invalid vip prefix: '%U'",
41  format_unformat_error, line_input);
42  goto done;
43  }
44 
45  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
46  {
47  if (unformat(line_input, "new_len %d", &new_len))
48  ;
49  else if (unformat(line_input, "port %d", &port))
50  ;
51  else if (unformat(line_input, "target_port %d", &target_port))
52  ;
53  else if (unformat(line_input, "node_port %d", &node_port))
54  ;
55  else if (unformat(line_input, "del"))
56  del = 1;
57  else if (unformat(line_input, "nat4"))
58  nat4 = 1;
59  else if (unformat(line_input, "nat6"))
60  nat4 = 0;
61  else {
62  error = clib_error_return (0, "parse error: '%U'",
63  format_unformat_error, line_input);
64  goto done;
65  }
66  }
67 
68 
69  if (ip46_prefix_is_ip4(&prefix, plen)) {
71  } else {
73  }
74 
76 
77  u32 index;
78  if (!del) {
79  if ((ret = kp_vip_add(&prefix, plen, type, new_len, &index,
80  (u16)port, (u16)target_port, (u16)node_port))) {
81  error = clib_error_return (0, "kp_vip_add error %d", ret);
82  goto done;
83  } else {
84  vlib_cli_output(vm, "kp_vip_add ok %d", index);
85  }
86  } else {
87  if ((ret = kp_vip_find_index(&prefix, plen, &index))) {
88  error = clib_error_return (0, "kp_vip_find_index error %d", ret);
89  goto done;
90  } else if ((ret = kp_vip_del(index))) {
91  error = clib_error_return (0, "kp_vip_del error %d", ret);
92  goto done;
93  }
94  }
95 
96 done:
97  unformat_free (line_input);
98 
99  return error;
100 }
101 
102 VLIB_CLI_COMMAND (kp_vip_command, static) =
103 {
104  .path = "kube-proxy vip",
105  .short_help = "kube-proxy vip <prefix> port <n> target_port <n>"
106  " node_port <n> [nat4|nat6)] [new_len <n>] [del]",
107  .function = kp_vip_command_fn,
108 };
109 
110 static clib_error_t *
112  unformat_input_t * input, vlib_cli_command_t * cmd)
113 {
114  unformat_input_t _line_input, *line_input = &_line_input;
115  ip46_address_t vip_prefix, pod_addr;
116  u8 vip_plen;
117  ip46_address_t *pod_array = 0;
118  u32 vip_index;
119  u8 del = 0;
120  int ret;
121  clib_error_t *error = 0;
122 
123  if (!unformat_user (input, unformat_line_input, line_input))
124  return 0;
125 
126  if (!unformat(line_input, "%U", unformat_ip46_prefix, &vip_prefix, &vip_plen, IP46_TYPE_ANY)) {
127  error = clib_error_return (0, "invalid pod address: '%U'",
128  format_unformat_error, line_input);
129  goto done;
130  }
131 
132  if ((ret = kp_vip_find_index(&vip_prefix, vip_plen, &vip_index))) {
133  error = clib_error_return (0, "kp_vip_find_index error %d", ret);
134  goto done;
135  }
136 
137  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
138  {
139  if (unformat(line_input, "%U", unformat_ip46_address, &pod_addr, IP46_TYPE_ANY)) {
140  vec_add1(pod_array, pod_addr);
141  } else if (unformat(line_input, "del")) {
142  del = 1;
143  } else {
144  error = clib_error_return (0, "parse error: '%U'",
145  format_unformat_error, line_input);
146  goto done;
147  }
148  }
149 
150  if (!vec_len(pod_array)) {
151  error = clib_error_return (0, "No POD address provided");
152  goto done;
153  }
154 
156  clib_warning("vip index is %d", vip_index);
157 
158  if (del) {
159  if ((ret = kp_vip_del_pods(vip_index, pod_array, vec_len(pod_array)))) {
160  error = clib_error_return (0, "kp_vip_del_pods error %d", ret);
161  goto done;
162  }
163  } else {
164  if ((ret = kp_vip_add_pods(vip_index, pod_array, vec_len(pod_array)))) {
165  error = clib_error_return (0, "kp_vip_add_pods error %d", ret);
166  goto done;
167  }
168  }
169 
170 done:
171  unformat_free (line_input);
172  vec_free(pod_array);
173 
174  return error;
175 }
176 
177 VLIB_CLI_COMMAND (kp_pod_command, static) =
178 {
179  .path = "kube-proxy pod",
180  .short_help =
181  "kube-proxy pod <vip-prefix> [<address> [<address> [...]]] [del]",
182  .function = kp_pod_command_fn,
183 };
184 
185 static clib_error_t *
187  unformat_input_t * input, vlib_cli_command_t * cmd)
188 {
189  kp_main_t *kpm = &kp_main;
190  unformat_input_t _line_input, *line_input = &_line_input;
191  u32 per_cpu_sticky_buckets = kpm->per_cpu_sticky_buckets;
192  u32 per_cpu_sticky_buckets_log2 = 0;
193  u32 flow_timeout = kpm->flow_timeout;
194  int ret;
195  clib_error_t *error = 0;
196 
197  if (!unformat_user (input, unformat_line_input, line_input))
198  return 0;
199 
200  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
201  {
202  if (unformat(line_input, "buckets %d", &per_cpu_sticky_buckets))
203  ;
204  else if (unformat(line_input, "buckets-log2 %d", &per_cpu_sticky_buckets_log2)) {
205  if (per_cpu_sticky_buckets_log2 >= 32)
206  return clib_error_return (0, "buckets-log2 value is too high");
207  per_cpu_sticky_buckets = 1 << per_cpu_sticky_buckets_log2;
208  } else if (unformat(line_input, "timeout %d", &flow_timeout))
209  ;
210  else {
211  error = clib_error_return (0, "parse error: '%U'",
212  format_unformat_error, line_input);
213  goto done;
214  }
215  }
216 
218 
219  if ((ret = kp_conf(per_cpu_sticky_buckets, flow_timeout))) {
220  error = clib_error_return (0, "kp_conf error %d", ret);
221  goto done;
222  }
223 
224 done:
225  unformat_free (line_input);
226 
227  return error;
228 }
229 
230 VLIB_CLI_COMMAND (kp_conf_command, static) =
231 {
232  .path = "kube-proxy conf",
233  .short_help = "kube-proxy conf [buckets <n>] [timeout <s>]",
234  .function = kp_conf_command_fn,
235 };
236 
237 static clib_error_t *
239  unformat_input_t * input, vlib_cli_command_t * cmd)
240 {
241  vlib_cli_output(vm, "%U", format_kp_main);
242  return NULL;
243 }
244 
245 
246 VLIB_CLI_COMMAND (kp_show_command, static) =
247 {
248  .path = "show kube-proxy",
249  .short_help = "show kube-proxy",
250  .function = kp_show_command_fn,
251 };
252 
253 static clib_error_t *
255  unformat_input_t * input, vlib_cli_command_t * cmd)
256 {
257  unformat_input_t line_input;
258  kp_main_t *kpm = &kp_main;
259  kp_vip_t *vip;
260  u8 verbose = 0;
261 
262  if (!unformat_user (input, unformat_line_input, &line_input))
263  return 0;
264 
265  if (unformat(&line_input, "verbose"))
266  verbose = 1;
267 
268  pool_foreach(vip, kpm->vips, {
269  vlib_cli_output(vm, "%U\n", verbose?format_kp_vip_detailed:format_kp_vip, vip);
270  });
271 
272  unformat_free (&line_input);
273  return NULL;
274 }
275 
276 VLIB_CLI_COMMAND (kp_show_vips_command, static) =
277 {
278  .path = "show kube-proxy vips",
279  .short_help = "show kube-proxy vips [verbose]",
280  .function = kp_show_vips_command_fn,
281 };
282 
283 static clib_error_t *
285  unformat_input_t * input,
286  vlib_cli_command_t * cmd)
287 {
288  unformat_input_t _line_input, *line_input = &_line_input;
289  vnet_main_t * vnm = vnet_get_main();
290  clib_error_t * error = 0;
291  u32 sw_if_index;
292  u32 * inside_sw_if_indices = 0;
293  int is_del = 0;
294  int i;
295 
296  sw_if_index = ~0;
297 
298  /* Get a line of input. */
299  if (!unformat_user (input, unformat_line_input, line_input))
300  return 0;
301 
302  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
303  {
304  if (unformat (line_input, "in %U", unformat_vnet_sw_interface,
305  vnm, &sw_if_index))
306  vec_add1 (inside_sw_if_indices, sw_if_index);
307  else if (unformat (line_input, "del"))
308  is_del = 1;
309  else
310  {
311  error = clib_error_return (0, "unknown input '%U'",
312  format_unformat_error, line_input);
313  goto done;
314  }
315  }
316 
317  if (vec_len (inside_sw_if_indices))
318  {
319  for (i = 0; i < vec_len(inside_sw_if_indices); i++)
320  {
321  sw_if_index = inside_sw_if_indices[i];
322 
323  if (kp_nat4_interface_add_del (sw_if_index, is_del))
324  {
325  error = clib_error_return (0, "%s %U failed",
326  is_del ? "del" : "add",
329  sw_if_index));
330  goto done;
331  }
332  }
333  }
334 
335 done:
336  unformat_free (line_input);
337  vec_free (inside_sw_if_indices);
338 
339  return error;
340 }
341 
342 VLIB_CLI_COMMAND (kp_set_interface_nat4_command, static) = {
343  .path = "kube-proxy set interface nat4",
345  .short_help = "kube-proxy set interface nat4 in <intfc> [del]",
346 };
347 
348 static clib_error_t *
350  unformat_input_t * input, vlib_cli_command_t * cmd)
351 {
352  u32 thread_index;
354  kp_main_t *kpm = &kp_main;
355 
356  for(thread_index = 0; thread_index < tm->n_vlib_mains; thread_index++ ) {
357  kp_hash_t *h = kpm->per_cpu[thread_index].sticky_ht;
358  if (h != NULL) {
359  kp_hash_bucket_t *b;
360  u32 i;
361  kp_hash_foreach_entry(h, b, i) {
362  vlib_refcount_add(&kpm->pod_refcount, thread_index, b->value[i], -1);
363  vlib_refcount_add(&kpm->pod_refcount, thread_index, 0, 1);
364  }
365 
366  kp_hash_free(h);
367  kpm->per_cpu[thread_index].sticky_ht = NULL;
368  }
369  }
370 
371  return NULL;
372 }
373 
374 /*
375  * flush all kube-proxy flowtables
376  * This is indented for debug and unit-tests purposes only
377  */
378 VLIB_CLI_COMMAND (kp_flowtable_flush_command, static) = {
379  .path = "test kube-proxy flowtable flush",
380  .short_help = "test kube-proxy flowtable flush",
381  .function = kp_flowtable_flush_command_fn,
382 };
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
vlib_refcount_t pod_refcount
Each POD has an associated reference counter.
Definition: kp.h:371
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
format_function_t format_kp_main
Definition: kp.h:471
#define NULL
Definition: clib.h:55
static clib_error_t * kp_show_vips_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: kp_cli.c:254
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:518
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:983
#define kp_hash_foreach_entry(h, bucket, i)
Definition: kphash.h:75
kp_per_cpu_t * per_cpu
Some global data is per-cpu.
Definition: kp.h:380
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
unformat_function_t unformat_vnet_sw_interface
kp_vip_type_t
kube-proxy supports IPv4 and IPv6 traffic and NAT4 and NAT6.
Definition: kp.h:171
int kp_vip_add(ip46_address_t *prefix, u8 plen, kp_vip_type_t type, u32 new_length, u32 *vip_index, u16 port, u16 target_port, u16 node_port)
Definition: kp.c:725
static clib_error_t * kp_set_interface_nat4_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: kp_cli.c:284
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:438
int kp_vip_del(u32 vip_index)
Definition: kp.c:810
#define clib_error_return(e, args...)
Definition: error.h:99
Definition: kp.h:352
unformat_function_t unformat_line_input
Definition: format.h:281
format_function_t format_vnet_sw_interface_name
int kp_vip_del_pods(u32 vip_index, ip46_address_t *addresses, u32 n)
Definition: kp.c:670
static_always_inline void kp_hash_free(kp_hash_t *h)
Definition: kphash.h:102
static clib_error_t * kp_pod_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: kp_cli.c:111
struct _unformat_input_t unformat_input_t
void kp_garbage_collection()
Definition: kp.c:292
static_always_inline void vlib_refcount_add(vlib_refcount_t *r, u32 thread_index, u32 counter_index, i32 v)
Definition: refcount.h:68
u32 per_cpu_sticky_buckets
Number of buckets in the per-cpu sticky hash table.
Definition: kp.h:390
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
vlib_main_t * vm
Definition: buffer.c:283
vec_header_t h
Definition: buffer.c:282
static clib_error_t * kp_vip_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: kp_cli.c:20
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
#define clib_warning(format, args...)
Definition: error.h:59
static clib_error_t * kp_flowtable_flush_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: kp_cli.c:349
uword unformat_ip46_prefix(unformat_input_t *input, va_list *args)
Definition: kp.c:49
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
u32 flow_timeout
Flow timeout in seconds.
Definition: kp.h:395
unsigned int u32
Definition: types.h:88
unformat_function_t unformat_ip46_address
Definition: format.h:71
u32 value[KPHASH_ENTRY_PER_BUCKET]
Definition: kphash.h:58
int kp_nat4_interface_add_del(u32 sw_if_index, int is_del)
Definition: kp.c:906
kp_main_t kp_main
Definition: kp.c:28
unsigned short u16
Definition: types.h:57
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
static clib_error_t * kp_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: kp_cli.c:238
int kp_vip_add_pods(u32 vip_index, ip46_address_t *addresses, u32 n)
Definition: kp.c:481
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
kp_vip_t * vips
Pool of all Virtual IPs.
Definition: kp.h:356
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
int kp_vip_find_index(ip46_address_t *prefix, u8 plen, u32 *vip_index)
Definition: kp.c:454
#define ip46_prefix_is_ip4(ip46, len)
Definition: kp.h:432
static clib_error_t * kp_conf_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: kp_cli.c:186
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
Load balancing service is provided per VIP.
Definition: kp.h:190
int kp_conf(u32 per_cpu_sticky_buckets, u32 flow_timeout)
Fix global kube-proxy parameters.
Definition: kp.c:421
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
kp_hash_t * sticky_ht
Each CPU has its own sticky flow hash table.
Definition: kp.h:348