dpdk: rework cryptodev ipsec build and setup
[vpp.git] / src / vnet / ipsec / ipsec_cli.c
1 /*
2  * decap.c : IPSec tunnel support
3  *
4  * Copyright (c) 2015 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <vnet/vnet.h>
19 #include <vnet/api_errno.h>
20 #include <vnet/ip/ip.h>
21 #include <vnet/interface.h>
22
23 #include <vnet/ipsec/ipsec.h>
24
25 static clib_error_t *
26 set_interface_spd_command_fn (vlib_main_t * vm,
27                               unformat_input_t * input,
28                               vlib_cli_command_t * cmd)
29 {
30   unformat_input_t _line_input, *line_input = &_line_input;
31   ipsec_main_t *im = &ipsec_main;
32   u32 sw_if_index = (u32) ~ 0;
33   u32 spd_id;
34   int is_add = 1;
35
36   if (!unformat_user (input, unformat_line_input, line_input))
37     return 0;
38
39   if (unformat
40       (line_input, "%U %u", unformat_vnet_sw_interface, im->vnet_main,
41        &sw_if_index, &spd_id))
42     ;
43   else if (unformat (line_input, "del"))
44     is_add = 0;
45   else
46     return clib_error_return (0, "parse error: '%U'",
47                               format_unformat_error, line_input);
48
49   unformat_free (line_input);
50
51   ipsec_set_interface_spd (vm, sw_if_index, spd_id, is_add);
52
53   return 0;
54 }
55
56 /* *INDENT-OFF* */
57 VLIB_CLI_COMMAND (set_interface_spd_command, static) = {
58     .path = "set interface ipsec spd",
59     .short_help =
60     "set interface ipsec spd <int> <id>",
61     .function = set_interface_spd_command_fn,
62 };
63 /* *INDENT-ON* */
64
65 static clib_error_t *
66 ipsec_sa_add_del_command_fn (vlib_main_t * vm,
67                              unformat_input_t * input,
68                              vlib_cli_command_t * cmd)
69 {
70   ipsec_main_t *im = &ipsec_main;
71   unformat_input_t _line_input, *line_input = &_line_input;
72   ipsec_sa_t sa;
73   int is_add = ~0;
74   u8 *ck = 0, *ik = 0;
75   clib_error_t *err = 0;
76
77   memset (&sa, 0, sizeof (sa));
78
79   if (!unformat_user (input, unformat_line_input, line_input))
80     return 0;
81
82   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
83     {
84       if (unformat (line_input, "add %u", &sa.id))
85         is_add = 1;
86       else if (unformat (line_input, "del %u", &sa.id))
87         is_add = 0;
88       else if (unformat (line_input, "spi %u", &sa.spi))
89         ;
90       else if (unformat (line_input, "esp"))
91         sa.protocol = IPSEC_PROTOCOL_ESP;
92       else if (unformat (line_input, "ah"))
93         //sa.protocol = IPSEC_PROTOCOL_AH;
94         return clib_error_return (0, "unsupported security protocol 'AH'");
95       else
96         if (unformat (line_input, "crypto-key %U", unformat_hex_string, &ck))
97         sa.crypto_key_len = vec_len (ck);
98       else
99         if (unformat
100             (line_input, "crypto-alg %U", unformat_ipsec_crypto_alg,
101              &sa.crypto_alg))
102         {
103           if (sa.crypto_alg < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
104               sa.crypto_alg >= IPSEC_CRYPTO_N_ALG)
105             return clib_error_return (0, "unsupported crypto-alg: '%U'",
106                                       format_ipsec_crypto_alg, sa.crypto_alg);
107         }
108       else
109         if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik))
110         sa.integ_key_len = vec_len (ik);
111       else if (unformat (line_input, "integ-alg %U", unformat_ipsec_integ_alg,
112                          &sa.integ_alg))
113         {
114           if (sa.integ_alg < IPSEC_INTEG_ALG_SHA1_96 ||
115               sa.integ_alg >= IPSEC_INTEG_N_ALG)
116             return clib_error_return (0, "unsupported integ-alg: '%U'",
117                                       format_ipsec_integ_alg, sa.integ_alg);
118         }
119       else if (unformat (line_input, "tunnel-src %U",
120                          unformat_ip4_address, &sa.tunnel_src_addr.ip4))
121         sa.is_tunnel = 1;
122       else if (unformat (line_input, "tunnel-dst %U",
123                          unformat_ip4_address, &sa.tunnel_dst_addr.ip4))
124         sa.is_tunnel = 1;
125       else if (unformat (line_input, "tunnel-src %U",
126                          unformat_ip6_address, &sa.tunnel_src_addr.ip6))
127         {
128           sa.is_tunnel = 1;
129           sa.is_tunnel_ip6 = 1;
130         }
131       else if (unformat (line_input, "tunnel-dst %U",
132                          unformat_ip6_address, &sa.tunnel_dst_addr.ip6))
133         {
134           sa.is_tunnel = 1;
135           sa.is_tunnel_ip6 = 1;
136         }
137       else
138         return clib_error_return (0, "parse error: '%U'",
139                                   format_unformat_error, line_input);
140     }
141
142   unformat_free (line_input);
143
144   if (sa.crypto_key_len > sizeof (sa.crypto_key))
145     sa.crypto_key_len = sizeof (sa.crypto_key);
146
147   if (sa.integ_key_len > sizeof (sa.integ_key))
148     sa.integ_key_len = sizeof (sa.integ_key);
149
150   if (ck)
151     strncpy ((char *) sa.crypto_key, (char *) ck, sa.crypto_key_len);
152
153   if (ik)
154     strncpy ((char *) sa.integ_key, (char *) ik, sa.integ_key_len);
155
156   if (is_add)
157     {
158       ASSERT (im->cb.check_support_cb);
159       err = im->cb.check_support_cb (&sa);
160       if (err)
161         return err;
162     }
163
164   ipsec_add_del_sa (vm, &sa, is_add);
165
166   return 0;
167 }
168
169 /* *INDENT-OFF* */
170 VLIB_CLI_COMMAND (ipsec_sa_add_del_command, static) = {
171     .path = "ipsec sa",
172     .short_help =
173     "ipsec sa [add|del]",
174     .function = ipsec_sa_add_del_command_fn,
175 };
176 /* *INDENT-ON* */
177
178 static clib_error_t *
179 ipsec_spd_add_del_command_fn (vlib_main_t * vm,
180                               unformat_input_t * input,
181                               vlib_cli_command_t * cmd)
182 {
183   unformat_input_t _line_input, *line_input = &_line_input;
184   u32 spd_id = ~0;
185   int is_add = ~0;
186
187   if (!unformat_user (input, unformat_line_input, line_input))
188     return 0;
189
190   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
191     {
192       if (unformat (line_input, "add"))
193         is_add = 1;
194       else if (unformat (line_input, "del"))
195         is_add = 0;
196       else if (unformat (line_input, "%u", &spd_id))
197         ;
198       else
199         return clib_error_return (0, "parse error: '%U'",
200                                   format_unformat_error, line_input);
201     }
202
203   unformat_free (line_input);
204
205   if (spd_id == ~0)
206     return clib_error_return (0, "please specify SPD ID");
207
208   ipsec_add_del_spd (vm, spd_id, is_add);
209
210   return 0;
211 }
212
213 /* *INDENT-OFF* */
214 VLIB_CLI_COMMAND (ipsec_spd_add_del_command, static) = {
215     .path = "ipsec spd",
216     .short_help =
217     "ipsec spd [add|del] <id>",
218     .function = ipsec_spd_add_del_command_fn,
219 };
220 /* *INDENT-ON* */
221
222
223 static clib_error_t *
224 ipsec_policy_add_del_command_fn (vlib_main_t * vm,
225                                  unformat_input_t * input,
226                                  vlib_cli_command_t * cmd)
227 {
228   unformat_input_t _line_input, *line_input = &_line_input;
229   ipsec_policy_t p;
230   int is_add = 0;
231   int is_ip_any = 1;
232   u32 tmp, tmp2;
233
234   memset (&p, 0, sizeof (p));
235   p.lport.stop = p.rport.stop = ~0;
236   p.laddr.stop.ip4.as_u32 = p.raddr.stop.ip4.as_u32 = (u32) ~ 0;
237   p.laddr.stop.ip6.as_u64[0] = p.laddr.stop.ip6.as_u64[1] = (u64) ~ 0;
238   p.raddr.stop.ip6.as_u64[0] = p.raddr.stop.ip6.as_u64[1] = (u64) ~ 0;
239
240   if (!unformat_user (input, unformat_line_input, line_input))
241     return 0;
242
243   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
244     {
245       if (unformat (line_input, "add"))
246         is_add = 1;
247       else if (unformat (line_input, "del"))
248         is_add = 0;
249       else if (unformat (line_input, "spd %u", &p.id))
250         ;
251       else if (unformat (line_input, "inbound"))
252         p.is_outbound = 0;
253       else if (unformat (line_input, "outbound"))
254         p.is_outbound = 1;
255       else if (unformat (line_input, "priority %d", &p.priority))
256         ;
257       else if (unformat (line_input, "protocol %u", &tmp))
258         p.protocol = (u8) tmp;
259       else
260         if (unformat
261             (line_input, "action %U", unformat_ipsec_policy_action,
262              &p.policy))
263         {
264           if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
265             return clib_error_return (0, "unsupported action: 'resolve'");
266         }
267       else if (unformat (line_input, "sa %u", &p.sa_id))
268         ;
269       else if (unformat (line_input, "local-ip-range %U - %U",
270                          unformat_ip4_address, &p.laddr.start.ip4,
271                          unformat_ip4_address, &p.laddr.stop.ip4))
272         is_ip_any = 0;
273       else if (unformat (line_input, "remote-ip-range %U - %U",
274                          unformat_ip4_address, &p.raddr.start.ip4,
275                          unformat_ip4_address, &p.raddr.stop.ip4))
276         is_ip_any = 0;
277       else if (unformat (line_input, "local-ip-range %U - %U",
278                          unformat_ip6_address, &p.laddr.start.ip6,
279                          unformat_ip6_address, &p.laddr.stop.ip6))
280         {
281           p.is_ipv6 = 1;
282           is_ip_any = 0;
283         }
284       else if (unformat (line_input, "remote-ip-range %U - %U",
285                          unformat_ip6_address, &p.raddr.start.ip6,
286                          unformat_ip6_address, &p.raddr.stop.ip6))
287         {
288           p.is_ipv6 = 1;
289           is_ip_any = 0;
290         }
291       else if (unformat (line_input, "local-port-range %u - %u", &tmp, &tmp2))
292         {
293           p.lport.start = tmp;
294           p.lport.stop = tmp2;
295         }
296       else
297         if (unformat (line_input, "remote-port-range %u - %u", &tmp, &tmp2))
298         {
299           p.rport.start = tmp;
300           p.rport.stop = tmp2;
301         }
302       else
303         return clib_error_return (0, "parse error: '%U'",
304                                   format_unformat_error, line_input);
305     }
306
307   unformat_free (line_input);
308
309   ipsec_add_del_policy (vm, &p, is_add);
310   if (is_ip_any)
311     {
312       p.is_ipv6 = 1;
313       ipsec_add_del_policy (vm, &p, is_add);
314     }
315   return 0;
316 }
317
318 /* *INDENT-OFF* */
319 VLIB_CLI_COMMAND (ipsec_policy_add_del_command, static) = {
320     .path = "ipsec policy",
321     .short_help =
322     "ipsec policy [add|del] spd <id> priority <n> ",
323     .function = ipsec_policy_add_del_command_fn,
324 };
325 /* *INDENT-ON* */
326
327 static clib_error_t *
328 set_ipsec_sa_key_command_fn (vlib_main_t * vm,
329                              unformat_input_t * input,
330                              vlib_cli_command_t * cmd)
331 {
332   unformat_input_t _line_input, *line_input = &_line_input;
333   ipsec_sa_t sa;
334   u8 *ck = 0, *ik = 0;
335
336   memset (&sa, 0, sizeof (sa));
337
338   if (!unformat_user (input, unformat_line_input, line_input))
339     return 0;
340
341   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
342     {
343       if (unformat (line_input, "%u", &sa.id))
344         ;
345       else
346         if (unformat (line_input, "crypto-key %U", unformat_hex_string, &ck))
347         sa.crypto_key_len = vec_len (ck);
348       else
349         if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik))
350         sa.integ_key_len = vec_len (ik);
351       else
352         return clib_error_return (0, "parse error: '%U'",
353                                   format_unformat_error, line_input);
354     }
355
356   unformat_free (line_input);
357
358   if (sa.crypto_key_len > sizeof (sa.crypto_key))
359     sa.crypto_key_len = sizeof (sa.crypto_key);
360
361   if (sa.integ_key_len > sizeof (sa.integ_key))
362     sa.integ_key_len = sizeof (sa.integ_key);
363
364   if (ck)
365     strncpy ((char *) sa.crypto_key, (char *) ck, sa.crypto_key_len);
366
367   if (ik)
368     strncpy ((char *) sa.integ_key, (char *) ik, sa.integ_key_len);
369
370   ipsec_set_sa_key (vm, &sa);
371
372   return 0;
373 }
374
375 /* *INDENT-OFF* */
376 VLIB_CLI_COMMAND (set_ipsec_sa_key_command, static) = {
377     .path = "set ipsec sa",
378     .short_help =
379     "set ipsec sa <id> crypto-key <key> integ-key <key>",
380     .function = set_ipsec_sa_key_command_fn,
381 };
382 /* *INDENT-ON* */
383
384 static clib_error_t *
385 show_ipsec_command_fn (vlib_main_t * vm,
386                        unformat_input_t * input, vlib_cli_command_t * cmd)
387 {
388   ipsec_spd_t *spd;
389   ipsec_sa_t *sa;
390   ipsec_policy_t *p;
391   ipsec_main_t *im = &ipsec_main;
392   u32 *i;
393   ipsec_tunnel_if_t *t;
394   vnet_hw_interface_t *hi;
395
396   /* *INDENT-OFF* */
397   pool_foreach (sa, im->sad, ({
398     if (sa->id) {
399       vlib_cli_output(vm, "sa %u spi %u mode %s protocol %s", sa->id, sa->spi,
400                       sa->is_tunnel ? "tunnel" : "transport",
401                       sa->protocol ? "esp" : "ah");
402       if (sa->protocol == IPSEC_PROTOCOL_ESP) {
403         vlib_cli_output(vm, "  crypto alg %U%s%U integrity alg %U%s%U",
404                         format_ipsec_crypto_alg, sa->crypto_alg,
405                         sa->crypto_alg ? " key " : "",
406                         format_hex_bytes, sa->crypto_key, sa->crypto_key_len,
407                         format_ipsec_integ_alg, sa->integ_alg,
408                         sa->integ_alg ? " key " : "",
409                         format_hex_bytes, sa->integ_key, sa->integ_key_len);
410       }
411       if (sa->is_tunnel && sa->is_tunnel_ip6) {
412         vlib_cli_output(vm, "  tunnel src %U dst %U",
413                         format_ip6_address, &sa->tunnel_src_addr.ip6,
414                         format_ip6_address, &sa->tunnel_dst_addr.ip6);
415       } else if (sa->is_tunnel) {
416         vlib_cli_output(vm, "  tunnel src %U dst %U",
417                         format_ip4_address, &sa->tunnel_src_addr.ip4,
418                         format_ip4_address, &sa->tunnel_dst_addr.ip4);
419       }
420     }
421   }));
422   /* *INDENT-ON* */
423
424   /* *INDENT-OFF* */
425   pool_foreach (spd, im->spds, ({
426     vlib_cli_output(vm, "spd %u", spd->id);
427
428     vlib_cli_output(vm, " outbound policies");
429     vec_foreach(i, spd->ipv4_outbound_policies)
430       {
431         p = pool_elt_at_index(spd->policies, *i);
432         vlib_cli_output(vm, "  priority %d action %U protocol %s%s",
433                         p->priority,
434                         format_ipsec_policy_action, p->policy,
435                         p->protocol ?
436                           format(0, "%U", format_ip_protocol, p->protocol) :
437                           (u8 *) "any",
438                         p->policy == IPSEC_POLICY_ACTION_PROTECT ?
439                           format(0, " sa %u", p->sa_id) :
440                           (u8 *) "");
441         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
442                         format_ip4_address, &p->laddr.start.ip4,
443                         format_ip4_address, &p->laddr.stop.ip4,
444                         p->lport.start, p->lport.stop);
445         vlib_cli_output(vm, "   remte addr range %U - %U port range %u - %u",
446                         format_ip4_address, &p->raddr.start.ip4,
447                         format_ip4_address, &p->raddr.stop.ip4,
448                         p->rport.start, p->rport.stop);
449         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
450                         p->counter.bytes);
451       };
452     vec_foreach(i, spd->ipv6_outbound_policies)
453       {
454         p = pool_elt_at_index(spd->policies, *i);
455         vlib_cli_output(vm, "  priority %d action %U protocol %s%s",
456                         p->priority,
457                         format_ipsec_policy_action, p->policy,
458                         p->protocol ?
459                           format(0, "%U", format_ip_protocol, p->protocol) :
460                           (u8 *) "any",
461                         p->policy == IPSEC_POLICY_ACTION_PROTECT ?
462                           format(0, " sa %u", p->sa_id) :
463                           (u8 *) "");
464         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
465                         format_ip6_address, &p->laddr.start.ip6,
466                         format_ip6_address, &p->laddr.stop.ip6,
467                         p->lport.start, p->lport.stop);
468         vlib_cli_output(vm, "   remote addr range %U - %U port range %u - %u",
469                         format_ip6_address, &p->raddr.start.ip6,
470                         format_ip6_address, &p->raddr.stop.ip6,
471                         p->rport.start, p->rport.stop);
472         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
473                         p->counter.bytes);
474       };
475     vlib_cli_output(vm, " inbound policies");
476     vec_foreach(i, spd->ipv4_inbound_protect_policy_indices)
477       {
478         p = pool_elt_at_index(spd->policies, *i);
479         vlib_cli_output(vm, "  priority %d action %U protocol %s%s",
480                         p->priority,
481                         format_ipsec_policy_action, p->policy,
482                         p->protocol ?
483                           format(0, "%U", format_ip_protocol, p->protocol) :
484                           (u8 *) "any",
485                         p->policy == IPSEC_POLICY_ACTION_PROTECT ?
486                           format(0, " sa %u", p->sa_id) :
487                           (u8 *) "");
488         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
489                         format_ip4_address, &p->laddr.start.ip4,
490                         format_ip4_address, &p->laddr.stop.ip4,
491                         p->lport.start, p->lport.stop);
492         vlib_cli_output(vm, "   remte addr range %U - %U port range %u - %u",
493                         format_ip4_address, &p->raddr.start.ip4,
494                         format_ip4_address, &p->raddr.stop.ip4,
495                         p->rport.start, p->rport.stop);
496         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
497                         p->counter.bytes);
498       };
499     vec_foreach(i, spd->ipv4_inbound_policy_discard_and_bypass_indices)
500       {
501         p = pool_elt_at_index(spd->policies, *i);
502         vlib_cli_output(vm, "  priority %d action %U protocol %s%s",
503                         p->priority,
504                         format_ipsec_policy_action, p->policy,
505                         p->protocol ?
506                           format(0, "%U", format_ip_protocol, p->protocol) :
507                           (u8 *) "any",
508                         p->policy == IPSEC_POLICY_ACTION_PROTECT ?
509                           format(0, " sa %u", p->sa_id) :
510                           (u8 *) "");
511         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
512                         format_ip4_address, &p->laddr.start.ip4,
513                         format_ip4_address, &p->laddr.stop.ip4,
514                         p->lport.start, p->lport.stop);
515         vlib_cli_output(vm, "   remte addr range %U - %U port range %u - %u",
516                         format_ip4_address, &p->raddr.start.ip4,
517                         format_ip4_address, &p->raddr.stop.ip4,
518                         p->rport.start, p->rport.stop);
519         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
520                         p->counter.bytes);
521       };
522     vec_foreach(i, spd->ipv6_inbound_protect_policy_indices)
523       {
524         p = pool_elt_at_index(spd->policies, *i);
525         vlib_cli_output(vm, "  priority %d action %U protocol %s%s",
526                         p->priority,
527                         format_ipsec_policy_action, p->policy,
528                         p->protocol ?
529                           format(0, "%U", format_ip_protocol, p->protocol) :
530                           (u8 *) "any",
531                         p->policy == IPSEC_POLICY_ACTION_PROTECT ?
532                           format(0, " sa %u", p->sa_id) :
533                           (u8 *) "");
534         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
535                         format_ip6_address, &p->laddr.start.ip6,
536                         format_ip6_address, &p->laddr.stop.ip6,
537                         p->lport.start, p->lport.stop);
538         vlib_cli_output(vm, "   remote addr range %U - %U port range %u - %u",
539                         format_ip6_address, &p->raddr.start.ip6,
540                         format_ip6_address, &p->raddr.stop.ip6,
541                         p->rport.start, p->rport.stop);
542         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
543                         p->counter.bytes);
544       };
545     vec_foreach(i, spd->ipv6_inbound_policy_discard_and_bypass_indices)
546       {
547         p = pool_elt_at_index(spd->policies, *i);
548         vlib_cli_output(vm, "  priority %d action %U protocol %s%s",
549                         p->priority,
550                         format_ipsec_policy_action, p->policy,
551                         p->protocol ?
552                           format(0, "%U", format_ip_protocol, p->protocol) :
553                           (u8 *) "any",
554                         p->policy == IPSEC_POLICY_ACTION_PROTECT ?
555                           format(0, " sa %u", p->sa_id) :
556                           (u8 *) "");
557         vlib_cli_output(vm, "   local addr range %U - %U port range %u - %u",
558                         format_ip6_address, &p->laddr.start.ip6,
559                         format_ip6_address, &p->laddr.stop.ip6,
560                         p->lport.start, p->lport.stop);
561         vlib_cli_output(vm, "   remote addr range %U - %U port range %u - %u",
562                         format_ip6_address, &p->raddr.start.ip6,
563                         format_ip6_address, &p->raddr.stop.ip6,
564                         p->rport.start, p->rport.stop);
565         vlib_cli_output(vm, "   packets %u bytes %u", p->counter.packets,
566                         p->counter.bytes);
567       };
568   }));
569   /* *INDENT-ON* */
570
571   vlib_cli_output (vm, "tunnel interfaces");
572   /* *INDENT-OFF* */
573   pool_foreach (t, im->tunnel_interfaces, ({
574     if (t->hw_if_index == ~0)
575       continue;
576     hi = vnet_get_hw_interface (im->vnet_main, t->hw_if_index);
577     vlib_cli_output(vm, "  %s seq", hi->name);
578     sa = pool_elt_at_index(im->sad, t->output_sa_index);
579     vlib_cli_output(vm, "   seq %u seq-hi %u esn %u anti-replay %u",
580                     sa->seq, sa->seq_hi, sa->use_esn, sa->use_anti_replay);
581     vlib_cli_output(vm, "   local-spi %u local-ip %U", sa->spi,
582                     format_ip4_address, &sa->tunnel_src_addr.ip4);
583     vlib_cli_output(vm, "   local-crypto %U %U",
584                     format_ipsec_crypto_alg, sa->crypto_alg,
585                     format_hex_bytes, sa->crypto_key, sa->crypto_key_len);
586     vlib_cli_output(vm, "   local-integrity %U %U",
587                     format_ipsec_integ_alg, sa->integ_alg,
588                     format_hex_bytes, sa->integ_key, sa->integ_key_len);
589     sa = pool_elt_at_index(im->sad, t->input_sa_index);
590     vlib_cli_output(vm, "   last-seq %u last-seq-hi %u esn %u anti-replay %u window %U",
591                     sa->last_seq, sa->last_seq_hi, sa->use_esn,
592                     sa->use_anti_replay,
593                     format_ipsec_replay_window, sa->replay_window);
594     vlib_cli_output(vm, "   remote-spi %u remote-ip %U", sa->spi,
595                     format_ip4_address, &sa->tunnel_src_addr.ip4);
596     vlib_cli_output(vm, "   remote-crypto %U %U",
597                     format_ipsec_crypto_alg, sa->crypto_alg,
598                     format_hex_bytes, sa->crypto_key, sa->crypto_key_len);
599     vlib_cli_output(vm, "   remote-integrity %U %U",
600                     format_ipsec_integ_alg, sa->integ_alg,
601                     format_hex_bytes, sa->integ_key, sa->integ_key_len);
602   }));
603   /* *INDENT-ON* */
604   return 0;
605 }
606
607 /* *INDENT-OFF* */
608 VLIB_CLI_COMMAND (show_ipsec_command, static) = {
609     .path = "show ipsec",
610     .short_help = "show ipsec",
611     .function = show_ipsec_command_fn,
612 };
613 /* *INDENT-ON* */
614
615 static clib_error_t *
616 clear_ipsec_counters_command_fn (vlib_main_t * vm,
617                                  unformat_input_t * input,
618                                  vlib_cli_command_t * cmd)
619 {
620   ipsec_main_t *im = &ipsec_main;
621   ipsec_spd_t *spd;
622   ipsec_policy_t *p;
623
624   /* *INDENT-OFF* */
625   pool_foreach (spd, im->spds, ({
626     pool_foreach(p, spd->policies, ({
627       p->counter.packets = p->counter.bytes = 0;
628     }));
629   }));
630   /* *INDENT-ON* */
631
632   return 0;
633 }
634
635 /* *INDENT-OFF* */
636 VLIB_CLI_COMMAND (clear_ipsec_counters_command, static) = {
637     .path = "clear ipsec counters",
638     .short_help = "clear ipsec counters",
639     .function = clear_ipsec_counters_command_fn,
640 };
641 /* *INDENT-ON* */
642
643 static clib_error_t *
644 create_ipsec_tunnel_command_fn (vlib_main_t * vm,
645                                 unformat_input_t * input,
646                                 vlib_cli_command_t * cmd)
647 {
648   unformat_input_t _line_input, *line_input = &_line_input;
649   ipsec_add_del_tunnel_args_t a;
650   int rv;
651   u32 num_m_args = 0;
652
653   memset (&a, 0, sizeof (a));
654   a.is_add = 1;
655
656   /* Get a line of input. */
657   if (!unformat_user (input, unformat_line_input, line_input))
658     return 0;
659
660   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
661     {
662       if (unformat
663           (line_input, "local-ip %U", unformat_ip4_address, &a.local_ip))
664         num_m_args++;
665       else
666         if (unformat
667             (line_input, "remote-ip %U", unformat_ip4_address, &a.remote_ip))
668         num_m_args++;
669       else if (unformat (line_input, "local-spi %u", &a.local_spi))
670         num_m_args++;
671       else if (unformat (line_input, "remote-spi %u", &a.remote_spi))
672         num_m_args++;
673       else if (unformat (line_input, "del"))
674         a.is_add = 0;
675       else
676         return clib_error_return (0, "unknown input `%U'",
677                                   format_unformat_error, input);
678     }
679   unformat_free (line_input);
680
681   if (num_m_args < 4)
682     return clib_error_return (0, "mandatory argument(s) missing");
683
684   rv = ipsec_add_del_tunnel_if (&a);
685
686   switch (rv)
687     {
688     case 0:
689       break;
690     case VNET_API_ERROR_INVALID_VALUE:
691       if (a.is_add)
692         return clib_error_return (0,
693                                   "IPSec tunnel interface already exists...");
694       else
695         return clib_error_return (0, "IPSec tunnel interface not exists...");
696     default:
697       return clib_error_return (0, "ipsec_register_interface returned %d",
698                                 rv);
699     }
700
701   return 0;
702 }
703
704 /* *INDENT-OFF* */
705 VLIB_CLI_COMMAND (create_ipsec_tunnel_command, static) = {
706   .path = "create ipsec tunnel",
707   .short_help = "create ipsec tunnel local-ip <addr> local-spi <spi> remote-ip <addr> remote-spi <spi>",
708   .function = create_ipsec_tunnel_command_fn,
709 };
710 /* *INDENT-ON* */
711
712 static clib_error_t *
713 set_interface_key_command_fn (vlib_main_t * vm,
714                               unformat_input_t * input,
715                               vlib_cli_command_t * cmd)
716 {
717   unformat_input_t _line_input, *line_input = &_line_input;
718   ipsec_main_t *im = &ipsec_main;
719   ipsec_if_set_key_type_t type = IPSEC_IF_SET_KEY_TYPE_NONE;
720   u32 hw_if_index = (u32) ~ 0;
721   u32 alg;
722   u8 *key = 0;
723
724   if (!unformat_user (input, unformat_line_input, line_input))
725     return 0;
726
727   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
728     {
729       if (unformat (line_input, "%U",
730                     unformat_vnet_hw_interface, im->vnet_main, &hw_if_index))
731         ;
732       else
733         if (unformat
734             (line_input, "local crypto %U", unformat_ipsec_crypto_alg, &alg))
735         type = IPSEC_IF_SET_KEY_TYPE_LOCAL_CRYPTO;
736       else
737         if (unformat
738             (line_input, "remote crypto %U", unformat_ipsec_crypto_alg, &alg))
739         type = IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO;
740       else
741         if (unformat
742             (line_input, "local integ %U", unformat_ipsec_integ_alg, &alg))
743         type = IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG;
744       else
745         if (unformat
746             (line_input, "remote integ %U", unformat_ipsec_integ_alg, &alg))
747         type = IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG;
748       else if (unformat (line_input, "%U", unformat_hex_string, &key))
749         ;
750       else
751         return clib_error_return (0, "parse error: '%U'",
752                                   format_unformat_error, line_input);
753     }
754
755   unformat_free (line_input);
756
757   if (type == IPSEC_IF_SET_KEY_TYPE_NONE)
758     return clib_error_return (0, "unknown key type");
759
760   if (alg > 0 && vec_len (key) == 0)
761     return clib_error_return (0, "key is not specified");
762
763   if (hw_if_index == (u32) ~ 0)
764     return clib_error_return (0, "interface not specified");
765
766   ipsec_set_interface_key (im->vnet_main, hw_if_index, type, alg, key);
767   vec_free (key);
768
769   return 0;
770 }
771
772 /* *INDENT-OFF* */
773 VLIB_CLI_COMMAND (set_interface_key_command, static) = {
774     .path = "set interface ipsec key",
775     .short_help =
776     "set interface ipsec key <int> <local|remote> <crypto|integ> <key type> <key>",
777     .function = set_interface_key_command_fn,
778 };
779 /* *INDENT-ON* */
780
781 clib_error_t *
782 ipsec_cli_init (vlib_main_t * vm)
783 {
784   return 0;
785 }
786
787 VLIB_INIT_FUNCTION (ipsec_cli_init);
788
789
790 /*
791  * fd.io coding-style-patch-verification: ON
792  *
793  * Local Variables:
794  * eval: (c-set-style "gnu")
795  * End:
796  */