X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fip%2Flookup.c;h=a376e51d789fa0c6e5b8cd56bc527162bcdd3c6e;hb=810086d8fd08445919ae03bf36161037e53a712a;hp=95f36d41a86937d81c323965909c872cadae2456;hpb=fa5d19829759cef45cc34efe844d9471f5a1fc61;p=vpp.git diff --git a/src/vnet/ip/lookup.c b/src/vnet/ip/lookup.c index 95f36d41a86..a376e51d789 100644 --- a/src/vnet/ip/lookup.c +++ b/src/vnet/ip/lookup.c @@ -49,6 +49,7 @@ #include #include #include +#include #include /** @@ -73,7 +74,10 @@ ip_interface_address_add_del (ip_lookup_main_t * lm, a = p ? pool_elt_at_index (lm->if_address_pool, p[0]) : 0; /* Verify given length. */ - if ((a && (address_length != a->address_length)) || (address_length == 0)) + if ((a && (address_length != a->address_length)) || + (address_length == 0) || + (lm->is_ip6 && address_length > 128) || + (!lm->is_ip6 && address_length > 32)) { vnm->api_errno = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH; return clib_error_create @@ -162,11 +166,21 @@ ip_interface_address_add_del (ip_lookup_main_t * lm, } else { + if (sw_if_index != a->sw_if_index) + { + if (result_if_address_index) + *result_if_address_index = ~0; + vnm->api_errno = VNET_API_ERROR_DUPLICATE_IF_ADDRESS; + return clib_error_create + ("Prefix %U already found on interface %U", + lm->format_address_and_length, addr_fib, address_length, + format_vnet_sw_if_index_name, vnm, a->sw_if_index); + } + if (result_if_address_index) *result_if_address_index = a - lm->if_address_pool; } - return /* no error */ 0; } @@ -188,9 +202,6 @@ VNET_SW_INTERFACE_ADD_DEL_FUNCTION (ip_sw_interface_add_del); void ip_lookup_init (ip_lookup_main_t * lm, u32 is_ip6) { - /* Preallocate three "special" adjacencies */ - lm->adjacency_heap = adj_pool; - if (!lm->fib_result_n_bytes) lm->fib_result_n_bytes = sizeof (uword); @@ -350,32 +361,6 @@ const ip46_address_t zero_addr = { 0, 0}, }; -u32 -fib_table_id_find_fib_index (fib_protocol_t proto, u32 table_id) -{ - ip4_main_t *im4 = &ip4_main; - ip6_main_t *im6 = &ip6_main; - uword *p; - - switch (proto) - { - case FIB_PROTOCOL_IP4: - p = hash_get (im4->fib_index_by_table_id, table_id); - break; - case FIB_PROTOCOL_IP6: - p = hash_get (im6->fib_index_by_table_id, table_id); - break; - default: - p = NULL; - break; - } - if (NULL != p) - { - return (p[0]); - } - return (~0); -} - clib_error_t * vnet_ip_route_cmd (vlib_main_t * vm, unformat_input_t * main_input, vlib_cli_command_t * cmd) @@ -383,10 +368,11 @@ vnet_ip_route_cmd (vlib_main_t * vm, unformat_input_t _line_input, *line_input = &_line_input; fib_route_path_t *rpaths = NULL, rpath; dpo_id_t dpo = DPO_INVALID, *dpos = NULL; + u32 table_id, is_del, udp_encap_id; fib_prefix_t *prefixs = NULL, pfx; mpls_label_t out_label, via_label; clib_error_t *error = NULL; - u32 table_id, is_del; + u32 weight, preference; vnet_main_t *vnm; u32 fib_index; f64 count; @@ -409,10 +395,6 @@ vnet_ip_route_cmd (vlib_main_t * vm, if (unformat (line_input, "table %d", &table_id)) ; - else if (unformat (line_input, "del")) - is_del = 1; - else if (unformat (line_input, "add")) - is_del = 0; else if (unformat (line_input, "resolve-via-host")) { if (vec_len (rpaths) == 0) @@ -433,21 +415,29 @@ vnet_ip_route_cmd (vlib_main_t * vm, rpaths[vec_len (rpaths) - 1].frp_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED; } - else if (unformat (line_input, "out-label %U", - unformat_mpls_unicast_label, &out_label)) + else if (unformat (line_input, "out-labels")) { if (vec_len (rpaths) == 0) { error = clib_error_return (0, "Paths then labels"); goto done; } - vec_add1 (rpaths[vec_len (rpaths) - 1].frp_label_stack, out_label); + else + { + while (unformat (line_input, "%U", + unformat_mpls_unicast_label, &out_label)) + { + vec_add1 (rpaths[vec_len (rpaths) - 1].frp_label_stack, + out_label); + } + } } else if (unformat (line_input, "via-label %U", unformat_mpls_unicast_label, &rpath.frp_local_label)) { rpath.frp_weight = 1; - rpath.frp_proto = FIB_PROTOCOL_MPLS; + rpath.frp_eos = MPLS_NON_EOS; + rpath.frp_proto = DPO_PROTO_MPLS; rpath.frp_sw_if_index = ~0; vec_add1 (rpaths, rpath); } @@ -466,26 +456,6 @@ vnet_ip_route_cmd (vlib_main_t * vm, pfx.fp_proto = FIB_PROTOCOL_IP6; vec_add1 (prefixs, pfx); } - else if (unformat (line_input, "via %U %U weight %u", - unformat_ip4_address, - &rpath.frp_addr.ip4, - unformat_vnet_sw_interface, vnm, - &rpath.frp_sw_if_index, &rpath.frp_weight)) - { - rpath.frp_proto = FIB_PROTOCOL_IP4; - vec_add1 (rpaths, rpath); - } - - else if (unformat (line_input, "via %U %U weight %u", - unformat_ip6_address, - &rpath.frp_addr.ip6, - unformat_vnet_sw_interface, vnm, - &rpath.frp_sw_if_index, &rpath.frp_weight)) - { - rpath.frp_proto = FIB_PROTOCOL_IP6; - vec_add1 (rpaths, rpath); - } - else if (unformat (line_input, "via %U %U", unformat_ip4_address, &rpath.frp_addr.ip4, @@ -493,7 +463,7 @@ vnet_ip_route_cmd (vlib_main_t * vm, &rpath.frp_sw_if_index)) { rpath.frp_weight = 1; - rpath.frp_proto = FIB_PROTOCOL_IP4; + rpath.frp_proto = DPO_PROTO_IP4; vec_add1 (rpaths, rpath); } @@ -504,16 +474,26 @@ vnet_ip_route_cmd (vlib_main_t * vm, &rpath.frp_sw_if_index)) { rpath.frp_weight = 1; - rpath.frp_proto = FIB_PROTOCOL_IP6; + rpath.frp_proto = DPO_PROTO_IP6; vec_add1 (rpaths, rpath); } + else if (unformat (line_input, "weight %u", &weight)) + { + ASSERT (vec_len (rpaths)); + rpaths[vec_len (rpaths) - 1].frp_weight = weight; + } + else if (unformat (line_input, "preference %u", &preference)) + { + ASSERT (vec_len (rpaths)); + rpaths[vec_len (rpaths) - 1].frp_preference = preference; + } else if (unformat (line_input, "via %U next-hop-table %d", unformat_ip4_address, &rpath.frp_addr.ip4, &rpath.frp_fib_index)) { rpath.frp_weight = 1; rpath.frp_sw_if_index = ~0; - rpath.frp_proto = FIB_PROTOCOL_IP4; + rpath.frp_proto = DPO_PROTO_IP4; vec_add1 (rpaths, rpath); } else if (unformat (line_input, "via %U next-hop-table %d", @@ -522,7 +502,7 @@ vnet_ip_route_cmd (vlib_main_t * vm, { rpath.frp_weight = 1; rpath.frp_sw_if_index = ~0; - rpath.frp_proto = FIB_PROTOCOL_IP6; + rpath.frp_proto = DPO_PROTO_IP6; vec_add1 (rpaths, rpath); } else if (unformat (line_input, "via %U", @@ -535,7 +515,7 @@ vnet_ip_route_cmd (vlib_main_t * vm, rpath.frp_fib_index = table_id; rpath.frp_weight = 1; rpath.frp_sw_if_index = ~0; - rpath.frp_proto = FIB_PROTOCOL_IP4; + rpath.frp_proto = DPO_PROTO_IP4; vec_add1 (rpaths, rpath); } else if (unformat (line_input, "via %U", @@ -544,13 +524,20 @@ vnet_ip_route_cmd (vlib_main_t * vm, rpath.frp_fib_index = table_id; rpath.frp_weight = 1; rpath.frp_sw_if_index = ~0; - rpath.frp_proto = FIB_PROTOCOL_IP6; + rpath.frp_proto = DPO_PROTO_IP6; + vec_add1 (rpaths, rpath); + } + else if (unformat (line_input, "via udp-encap %d", &udp_encap_id)) + { + rpath.frp_udp_encap_id = udp_encap_id; + rpath.frp_flags |= FIB_ROUTE_PATH_UDP_ENCAP; + rpath.frp_proto = fib_proto_to_dpo (pfx.fp_proto); vec_add1 (rpaths, rpath); } else if (unformat (line_input, "lookup in table %d", &rpath.frp_fib_index)) { - rpath.frp_proto = pfx.fp_proto; + rpath.frp_proto = fib_proto_to_dpo (pfx.fp_proto); rpath.frp_sw_if_index = ~0; vec_add1 (rpaths, rpath); } @@ -560,7 +547,7 @@ vnet_ip_route_cmd (vlib_main_t * vm, &rpath.frp_sw_if_index)) { rpath.frp_weight = 1; - rpath.frp_proto = prefixs[0].fp_proto; + rpath.frp_proto = fib_proto_to_dpo (prefixs[0].fp_proto); vec_add1 (rpaths, rpath); } else if (vec_len (prefixs) > 0 && @@ -569,6 +556,10 @@ vnet_ip_route_cmd (vlib_main_t * vm, { vec_add1 (dpos, dpo); } + else if (unformat (line_input, "del")) + is_del = 1; + else if (unformat (line_input, "add")) + is_del = 0; else { error = unformat_parse_error (line_input); @@ -598,7 +589,7 @@ vnet_ip_route_cmd (vlib_main_t * vm, } else { - fib_index = fib_table_id_find_fib_index (prefixs[0].fp_proto, table_id); + fib_index = fib_table_find (prefixs[0].fp_proto, table_id); if (~0 == fib_index) { @@ -647,8 +638,8 @@ vnet_ip_route_cmd (vlib_main_t * vm, /* * the CLI parsing stored table Ids, swap to FIB indicies */ - fi = fib_table_id_find_fib_index (prefixs[i].fp_proto, - rpaths[i].frp_fib_index); + fi = fib_table_find (prefixs[i].fp_proto, + rpaths[i].frp_fib_index); if (~0 == fi) { @@ -714,6 +705,81 @@ done: return error; } +clib_error_t * +vnet_ip_table_cmd (vlib_main_t * vm, + unformat_input_t * main_input, + vlib_cli_command_t * cmd, fib_protocol_t fproto) +{ + unformat_input_t _line_input, *line_input = &_line_input; + clib_error_t *error = NULL; + u32 table_id, is_add; + u8 *name = NULL; + + is_add = 1; + table_id = ~0; + + /* Get a line of input. */ + if (!unformat_user (main_input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%d", &table_id)) + ; + else if (unformat (line_input, "del")) + is_add = 0; + else if (unformat (line_input, "add")) + is_add = 1; + else if (unformat (line_input, "name %s", &name)) + ; + else + { + error = unformat_parse_error (line_input); + goto done; + } + } + + if (~0 == table_id) + { + error = clib_error_return (0, "No table id"); + goto done; + } + else if (0 == table_id) + { + error = clib_error_return (0, "Can't change the default table"); + goto done; + } + else + { + if (is_add) + { + ip_table_create (fproto, table_id, 0, name); + } + else + { + ip_table_delete (fproto, table_id, 0); + } + } + +done: + unformat_free (line_input); + return error; +} + +clib_error_t * +vnet_ip4_table_cmd (vlib_main_t * vm, + unformat_input_t * main_input, vlib_cli_command_t * cmd) +{ + return (vnet_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP4)); +} + +clib_error_t * +vnet_ip6_table_cmd (vlib_main_t * vm, + unformat_input_t * main_input, vlib_cli_command_t * cmd) +{ + return (vnet_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP6)); +} + /* *INDENT-OFF* */ VLIB_CLI_COMMAND (vlib_cli_ip_command, static) = { .path = "ip", @@ -776,6 +842,159 @@ VLIB_CLI_COMMAND (ip_route_command, static) = { .function = vnet_ip_route_cmd, .is_mp_safe = 1, }; + +/* *INDENT-ON* */ +/*? + * This command is used to add or delete IPv4 Tables. All + * Tables must be explicitly added before that can be used. Creating a + * table will add both unicast and multicast FIBs + * + ?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (ip4_table_command, static) = { + .path = "ip table", + .short_help = "ip table [add|del] ", + .function = vnet_ip4_table_cmd, + .is_mp_safe = 1, +}; +/* *INDENT-ON* */ + +/* *INDENT-ON* */ +/*? + * This command is used to add or delete IPv4 Tables. All + * Tables must be explicitly added before that can be used. Creating a + * table will add both unicast and multicast FIBs + * + ?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (ip6_table_command, static) = { + .path = "ip6 table", + .short_help = "ip6 table [add|del] ", + .function = vnet_ip6_table_cmd, + .is_mp_safe = 1, +}; + +static clib_error_t * +ip_table_bind_cmd (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd, + fib_protocol_t fproto) +{ + vnet_main_t *vnm = vnet_get_main (); + clib_error_t *error = 0; + u32 sw_if_index, table_id; + int rv; + + sw_if_index = ~0; + + if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index)) + { + error = clib_error_return (0, "unknown interface `%U'", + format_unformat_error, input); + goto done; + } + + if (unformat (input, "%d", &table_id)) + ; + else + { + error = clib_error_return (0, "expected table id `%U'", + format_unformat_error, input); + goto done; + } + + rv = ip_table_bind (fproto, sw_if_index, table_id, 0); + + if (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE == rv) + { + error = clib_error_return (0, "IP addresses are still present on %U", + format_vnet_sw_if_index_name, + vnet_get_main(), + sw_if_index); + } + else if (VNET_API_ERROR_NO_SUCH_FIB == rv) + { + error = clib_error_return (0, "no such table %d", table_id); + } + else if (0 != rv) + { + error = clib_error_return (0, "unknown error"); + } + + done: + return error; +} + +static clib_error_t * +ip4_table_bind_cmd (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + return (ip_table_bind_cmd (vm , input, cmd, FIB_PROTOCOL_IP4)); +} + +static clib_error_t * +ip6_table_bind_cmd (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + return (ip_table_bind_cmd (vm , input, cmd, FIB_PROTOCOL_IP6)); +} + +/*? + * Place the indicated interface into the supplied IPv4 FIB table (also known + * as a VRF). If the FIB table does not exist, this command creates it. To + * display the current IPv4 FIB table, use the command 'show ip fib'. + * FIB table will only be displayed if a route has been added to the table, or + * an IP Address is assigned to an interface in the table (which adds a route + * automatically). + * + * @note IP addresses added after setting the interface IP table are added to + * the indicated FIB table. If an IP address is added prior to changing the + * table then this is an error. The control plane must remove these addresses + * first and then change the table. VPP will not automatically move the + * addresses from the old to the new table as it does not know the validity + * of such a change. + * + * @cliexpar + * Example of how to add an interface to an IPv4 FIB table (where 2 is the table-id): + * @cliexcmd{set interface ip table GigabitEthernet2/0/0 2} + ?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (set_interface_ip_table_command, static) = +{ + .path = "set interface ip table", + .function = ip4_table_bind_cmd, + .short_help = "set interface ip table ", +}; +/* *INDENT-ON* */ + +/*? + * Place the indicated interface into the supplied IPv6 FIB table (also known + * as a VRF). If the FIB table does not exist, this command creates it. To + * display the current IPv6 FIB table, use the command 'show ip6 fib'. + * FIB table will only be displayed if a route has been added to the table, or + * an IP Address is assigned to an interface in the table (which adds a route + * automatically). + * + * @note IP addresses added after setting the interface IP table are added to + * the indicated FIB table. If an IP address is added prior to changing the + * table then this is an error. The control plane must remove these addresses + * first and then change the table. VPP will not automatically move the + * addresses from the old to the new table as it does not know the validity + * of such a change. + * + * @cliexpar + * Example of how to add an interface to an IPv6 FIB table (where 2 is the table-id): + * @cliexcmd{set interface ip6 table GigabitEthernet2/0/0 2} + ?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (set_interface_ip6_table_command, static) = +{ + .path = "set interface ip6 table", + .function = ip6_table_bind_cmd, + .short_help = "set interface ip6 table " +}; /* *INDENT-ON* */ clib_error_t * @@ -838,12 +1057,14 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, unformat_ip4_address, &pfx.fp_grp_addr.ip4, &pfx.fp_len)) { + memset (&pfx.fp_src_addr.ip4, 0, sizeof (pfx.fp_src_addr.ip4)); pfx.fp_proto = FIB_PROTOCOL_IP4; } else if (unformat (line_input, "%U/%d", unformat_ip6_address, &pfx.fp_grp_addr.ip6, &pfx.fp_len)) { + memset (&pfx.fp_src_addr.ip6, 0, sizeof (pfx.fp_src_addr.ip6)); pfx.fp_proto = FIB_PROTOCOL_IP6; } else if (unformat (line_input, "%U", @@ -865,7 +1086,12 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, &rpath.frp_sw_if_index)) { rpath.frp_weight = 1; - rpath.frp_proto = FIB_PROTOCOL_IP4; + } + else if (unformat (line_input, "via local")) + { + rpath.frp_sw_if_index = ~0; + rpath.frp_weight = 1; + rpath.frp_flags |= FIB_ROUTE_PATH_LOCAL; } else if (unformat (line_input, "%U", unformat_mfib_itf_flags, &iflags)) ; @@ -920,7 +1146,7 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, else if (eflags) { mfib_table_entry_update (fib_index, &pfx, MFIB_SOURCE_CLI, - eflags); + MFIB_RPF_ID_NONE, eflags); } else { @@ -1215,6 +1441,185 @@ VLIB_CLI_COMMAND (ip_probe_neighbor_command, static) = { }; /* *INDENT-ON* */ +clib_error_t * +vnet_ip_container_proxy_add_del (vnet_ip_container_proxy_args_t * args) +{ + u32 fib_index; + + if (!vnet_sw_interface_is_api_valid (vnet_get_main (), args->sw_if_index)) + return clib_error_return_code (0, VNET_API_ERROR_INVALID_INTERFACE, 0, + "invalid sw_if_index"); + + fib_index = fib_table_get_table_id_for_sw_if_index (args->prefix.fp_proto, + args->sw_if_index); + if (args->is_add) + { + dpo_id_t proxy_dpo = DPO_INVALID; + l3_proxy_dpo_add_or_lock (fib_proto_to_dpo (args->prefix.fp_proto), + args->sw_if_index, &proxy_dpo); + fib_table_entry_special_dpo_add (fib_index, + &args->prefix, + FIB_SOURCE_PROXY, + FIB_ENTRY_FLAG_EXCLUSIVE, &proxy_dpo); + dpo_reset (&proxy_dpo); + } + else + { + fib_table_entry_special_remove (fib_index, &args->prefix, + FIB_SOURCE_PROXY); + } + return 0; +} + +u8 +ip_container_proxy_is_set (fib_prefix_t * pfx, u32 sw_if_index) +{ + u32 fib_index; + fib_node_index_t fei; + const dpo_id_t *dpo; + l3_proxy_dpo_t *l3p; + load_balance_t *lb0; + + fib_index = fib_table_get_table_id_for_sw_if_index (pfx->fp_proto, + sw_if_index); + if (fib_index == ~0) + return 0; + + fei = fib_table_lookup_exact_match (fib_index, pfx); + if (fei == FIB_NODE_INDEX_INVALID) + return 0; + + dpo = fib_entry_contribute_ip_forwarding (fei); + lb0 = load_balance_get (dpo->dpoi_index); + dpo = load_balance_get_bucket_i (lb0, 0); + if (dpo->dpoi_type != DPO_L3_PROXY) + return 0; + + l3p = l3_proxy_dpo_get (dpo->dpoi_index); + return (l3p->l3p_sw_if_index == sw_if_index); +} + +clib_error_t * +ip_container_cmd (vlib_main_t * vm, + unformat_input_t * main_input, vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + fib_prefix_t pfx; + + u32 is_del; + vnet_main_t *vnm; + u32 sw_if_index; + + vnm = vnet_get_main (); + is_del = 0; + sw_if_index = ~0; + + /* Get a line of input. */ + if (!unformat_user (main_input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%U", unformat_ip4_address, &pfx.fp_addr.ip4)) + { + pfx.fp_proto = FIB_PROTOCOL_IP4; + pfx.fp_len = 32; + } + else if (unformat (line_input, "%U", + unformat_ip6_address, &pfx.fp_addr.ip6)) + { + pfx.fp_proto = FIB_PROTOCOL_IP6; + pfx.fp_len = 128; + } + else if (unformat (line_input, "%U", + unformat_vnet_sw_interface, vnm, &sw_if_index)) + ; + else if (unformat (line_input, "del")) + is_del = 1; + else + return (clib_error_return (0, "unknown input '%U'", + format_unformat_error, line_input)); + } + + if (~0 == sw_if_index) + { + return (clib_error_return (0, "no interface")); + } + + vnet_ip_container_proxy_args_t args = { + .prefix = pfx, + .sw_if_index = sw_if_index, + .is_add = !is_del, + }; + vnet_ip_container_proxy_add_del (&args); + unformat_free (line_input); + return (NULL); +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (ip_container_command_node, static) = { + .path = "ip container", + .function = ip_container_cmd, + .short_help = "ip container
", + .is_mp_safe = 1, +}; +/* *INDENT-ON* */ + +clib_error_t * +show_ip_container_cmd_fn (vlib_main_t * vm, unformat_input_t * main_input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + vnet_main_t *vnm = vnet_get_main (); + fib_prefix_t pfx; + u32 sw_if_index = ~0; + u8 has_proxy; + + if (!unformat_user (main_input, unformat_line_input, line_input)) + return 0; + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%U", unformat_ip4_address, &pfx.fp_addr.ip4)) + { + pfx.fp_proto = FIB_PROTOCOL_IP4; + pfx.fp_len = 32; + } + else if (unformat (line_input, "%U", + unformat_ip6_address, &pfx.fp_addr.ip6)) + { + pfx.fp_proto = FIB_PROTOCOL_IP6; + pfx.fp_len = 128; + } + else if (unformat (line_input, "%U", + unformat_vnet_sw_interface, vnm, &sw_if_index)) + ; + else + return (clib_error_return (0, "unknown input '%U'", + format_unformat_error, line_input)); + } + + if (~0 == sw_if_index) + { + vlib_cli_output (vm, "no interface"); + return (clib_error_return (0, "no interface")); + } + + has_proxy = ip_container_proxy_is_set (&pfx, sw_if_index); + vlib_cli_output (vm, "ip container proxy is: %s", has_proxy ? "on" : "off"); + + unformat_free (line_input); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (show_ip_container_command, static) = { + .path = "show ip container", + .function = show_ip_container_cmd_fn, + .short_help = "show ip container
", + .is_mp_safe = 1, +}; +/* *INDENT-ON* */ + /* * fd.io coding-style-patch-verification: ON *