From 7cd468a3d7dee7d6c92f69a0bb7061ae208ec727 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Mon, 19 Dec 2016 23:05:39 +0100 Subject: Reorganize source tree to use single autotools instance Change-Id: I7b51f88292e057c6443b12224486f2d0c9f8ae23 Signed-off-by: Damjan Marion --- src/vnet/lisp-cp/control.h | 314 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 314 insertions(+) create mode 100644 src/vnet/lisp-cp/control.h (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h new file mode 100644 index 00000000..e89c6fd6 --- /dev/null +++ b/src/vnet/lisp-cp/control.h @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2016 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. + */ + +#ifndef VNET_CONTROL_H_ +#define VNET_CONTROL_H_ + +#include +#include +#include + +#define NUMBER_OF_RETRIES 1 +#define PENDING_MREQ_EXPIRATION_TIME 3.0 /* seconds */ +#define PENDING_MREQ_QUEUE_LEN 5 + +#define PENDING_MREG_EXPIRATION_TIME 3.0 /* seconds */ +#define RLOC_PROBING_INTERVAL 60.0 + +/* when map-registration is enabled "quick registration" takes place first. + In this mode ETR sends map-register messages at an increased frequency + until specified message count is reached */ +#define QUICK_MAP_REGISTER_MSG_COUNT 3 +#define QUICK_MAP_REGISTER_INTERVAL 3.0 + +/* normal map-register period */ +#define MAP_REGISTER_INTERVAL 60.0 + +/* 15 minutes */ +#define MAP_REGISTER_DEFAULT_TTL 900 + +typedef struct +{ + gid_address_t src; + gid_address_t dst; + u32 retries_num; + f64 time_to_expire; + u8 is_smr_invoked; + u64 *nonces; + u8 to_be_removed; +} pending_map_request_t; + +typedef struct +{ + gid_address_t leid; + gid_address_t reid; + u8 is_src_dst; + locator_pair_t *locator_pairs; +} fwd_entry_t; + +typedef struct +{ + gid_address_t leid; + gid_address_t reid; +} lisp_adjacency_t; + +typedef enum +{ + IP4_MISS_PACKET, + IP6_MISS_PACKET +} miss_packet_type_t; + +/* map-server/map-resolver structure */ +typedef struct +{ + u8 is_down; + f64 last_update; + ip_address_t address; + char *key; +} lisp_msmr_t; + +typedef struct +{ + /* headers */ + u8 data[100]; + u32 length; + miss_packet_type_t type; +} miss_packet_t; + +typedef enum +{ + MR_MODE_DST_ONLY = 0, + MR_MODE_SRC_DST, + _MR_MODE_MAX +} map_request_mode_t; + +typedef struct +{ + /* LISP feature status */ + u8 is_enabled; + + /* eid table */ + gid_dictionary_t mapping_index_by_gid; + + /* pool of mappings */ + mapping_t *mapping_pool; + + /* hash map of secret keys by mapping index */ + u8 *key_by_mapping_index; + + /* pool of locators */ + locator_t *locator_pool; + + /* pool of locator-sets */ + locator_set_t *locator_set_pool; + + /* vector of locator-set vectors composed of and indexed by locator index */ + u32 **locator_to_locator_sets; + + /* hash map of locators by name */ + uword *locator_set_index_by_name; + + /* vector of eid index vectors supported and indexed by locator-set index */ + u32 **locator_set_to_eids; + + /* vectors of indexes for local locator-sets and mappings */ + u32 *local_mappings_indexes; + u32 *local_locator_set_indexes; + + /* hash map of forwarding entries by mapping index */ + u32 *fwd_entry_by_mapping_index; + + /* forwarding entries pool */ + fwd_entry_t *fwd_entry_pool; + + /* hash map keyed by nonce of pending map-requests */ + uword *pending_map_requests_by_nonce; + + /* pool of pending map requests */ + pending_map_request_t *pending_map_requests_pool; + + /* hash map of sent map register messages */ + uword *map_register_messages_by_nonce; + + /* vector of map-resolvers */ + lisp_msmr_t *map_resolvers; + + /* vector of map-servers */ + lisp_msmr_t *map_servers; + + /* map resolver address currently being used for sending requests. + * This has to be an actual address and not an index to map_resolvers vector + * since the vector may be modified during request resend/retry procedure + * and break things :-) */ + ip_address_t active_map_resolver; + + u8 do_map_resolver_election; + + /* map-request locator set index */ + u32 mreq_itr_rlocs; + + /* vni to vrf hash tables */ + uword *table_id_by_vni; + uword *vni_by_table_id; + + /* vni to bd-index hash tables */ + uword *bd_id_by_vni; + uword *vni_by_bd_id; + + /* track l2 and l3 interfaces that have been created for vni */ + uword *l2_dp_intf_by_vni; + + /* Proxy ETR map index */ + u32 pitr_map_index; + + /* LISP PITR mode */ + u8 lisp_pitr; + + /* map request mode */ + u8 map_request_mode; + + /* enable/disable map registering */ + u8 map_registering; + + /* enable/disable rloc-probing */ + u8 rloc_probing; + + /* timing wheel for mappping timeouts */ + timing_wheel_t wheel; + + /* commodity */ + ip4_main_t *im4; + ip6_main_t *im6; + vlib_main_t *vlib_main; + vnet_main_t *vnet_main; +} lisp_cp_main_t; + +/* lisp-gpe control plane */ +lisp_cp_main_t lisp_control_main; + +extern vlib_node_registration_t lisp_cp_input_node; +extern vlib_node_registration_t lisp_cp_lookup_ip4_node; +extern vlib_node_registration_t lisp_cp_lookup_ip6_node; + +clib_error_t *lisp_cp_init (); + +always_inline lisp_cp_main_t * +vnet_lisp_cp_get_main () +{ + return &lisp_control_main; +} + +typedef struct +{ + u8 is_add; + union + { + u8 *name; + u32 index; + }; + locator_t *locators; + u8 local; +} vnet_lisp_add_del_locator_set_args_t; + +int +vnet_lisp_add_del_locator_set (vnet_lisp_add_del_locator_set_args_t * a, + u32 * ls_index); +int +vnet_lisp_add_del_locator (vnet_lisp_add_del_locator_set_args_t * a, + locator_set_t * ls, u32 * ls_index); + +typedef struct +{ + u8 is_add; + gid_address_t eid; + u32 locator_set_index; + + u32 ttl; + u8 action; + u8 authoritative; + + u8 local; + u8 is_static; + u8 *key; + u8 key_id; +} vnet_lisp_add_del_mapping_args_t; + +int +vnet_lisp_map_cache_add_del (vnet_lisp_add_del_mapping_args_t * a, + u32 * map_index); +int +vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a, + u32 * map_index_result); + +int +vnet_lisp_add_del_mapping (gid_address_t * deid, locator_t * dlocs, u8 action, + u8 authoritative, u32 ttl, u8 is_add, u8 is_static, + u32 * res_map_index); + +typedef struct +{ + gid_address_t reid; + gid_address_t leid; + u8 is_add; +} vnet_lisp_add_del_adjacency_args_t; + +int vnet_lisp_add_del_adjacency (vnet_lisp_add_del_adjacency_args_t * a); + +typedef struct +{ + u8 is_add; + ip_address_t address; +} vnet_lisp_add_del_map_resolver_args_t; + +int +vnet_lisp_add_del_map_resolver (vnet_lisp_add_del_map_resolver_args_t * a); +int vnet_lisp_add_del_map_server (ip_address_t * addr, u8 is_add); + +clib_error_t *vnet_lisp_enable_disable (u8 is_enabled); +u8 vnet_lisp_enable_disable_status (void); + +int vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add); + +typedef struct +{ + u8 is_add; + u8 *locator_set_name; +} vnet_lisp_add_del_mreq_itr_rloc_args_t; + +int +vnet_lisp_add_del_mreq_itr_rlocs (vnet_lisp_add_del_mreq_itr_rloc_args_t * a); + +int vnet_lisp_clear_all_remote_adjacencies (void); + +int vnet_lisp_eid_table_map (u32 vni, u32 vrf, u8 is_l2, u8 is_add); +int vnet_lisp_add_del_map_table_key (gid_address_t * eid, char *key, + u8 is_add); +int vnet_lisp_set_map_request_mode (u8 mode); +u8 vnet_lisp_get_map_request_mode (void); +lisp_adjacency_t *vnet_lisp_adjacencies_get_by_vni (u32 vni); +int vnet_lisp_rloc_probe_enable_disable (u8 is_enable); +int vnet_lisp_map_register_enable_disable (u8 is_enable); +u8 vnet_lisp_map_register_state_get (void); +u8 vnet_lisp_rloc_probe_state_get (void); + +#endif /* VNET_CONTROL_H_ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ -- cgit 1.2.3-korg From f3dc11a9d71a30ac89e7ceb523abdb1ff13f0ac3 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Tue, 24 Jan 2017 03:13:43 -0800 Subject: Move LISP cp cli to separate file Change-Id: I24355c71606c047e474b2541bb274e3d183fee85 Signed-off-by: Florin Coras --- src/vnet.am | 1 + src/vnet/lisp-cp/control.c | 1748 +++++-------------------------------------- src/vnet/lisp-cp/control.h | 2 +- src/vnet/lisp-cp/lisp_cli.c | 1423 +++++++++++++++++++++++++++++++++++ 4 files changed, 1610 insertions(+), 1564 deletions(-) create mode 100644 src/vnet/lisp-cp/lisp_cli.c (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/vnet.am b/src/vnet.am index c751c100..669ea1ff 100644 --- a/src/vnet.am +++ b/src/vnet.am @@ -569,6 +569,7 @@ libvnet_la_SOURCES += \ vnet/lisp-cp/gid_dictionary.c \ vnet/lisp-cp/lisp_msg_serdes.c \ vnet/lisp-cp/packets.c \ + vnet/lisp-cp/lisp_cli.c \ vnet/lisp-cp/lisp_api.c nobase_include_HEADERS += \ diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index 3b85036a..043d60fc 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -26,6 +25,8 @@ #include #include +lisp_cp_main_t lisp_control_main; + u8 *format_lisp_cp_input_trace (u8 * s, va_list * args); typedef enum @@ -49,10 +50,6 @@ typedef struct mapping_t *mappings; } map_records_arg_t; -static int -lisp_add_del_adjacency (lisp_cp_main_t * lcm, gid_address_t * local_eid, - gid_address_t * remote_eid, u8 is_add); - u8 vnet_lisp_get_map_request_mode (void) { @@ -590,58 +587,6 @@ vnet_lisp_adjacencies_get_by_vni (u32 vni) return adjs; } -static clib_error_t * -lisp_show_adjacencies_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - lisp_adjacency_t *adjs, *adj; - vlib_cli_output (vm, "%s %40s\n", "leid", "reid"); - unformat_input_t _line_input, *line_input = &_line_input; - u32 vni = ~0; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "vni %d", &vni)) - ; - else - { - vlib_cli_output (vm, "parse error: '%U'", - format_unformat_error, line_input); - return 0; - } - } - - if (~0 == vni) - { - vlib_cli_output (vm, "error: no vni specified!"); - return 0; - } - - adjs = vnet_lisp_adjacencies_get_by_vni (vni); - - vec_foreach (adj, adjs) - { - vlib_cli_output (vm, "%U %40U\n", format_gid_address, &adj->leid, - format_gid_address, &adj->reid); - } - vec_free (adjs); - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_show_adjacencies_command) = { - .path = "show lisp adjacencies", - .short_help = "show lisp adjacencies", - .function = lisp_show_adjacencies_command_fn, -}; -/* *INDENT-ON* */ - static lisp_msmr_t * get_map_server (ip_address_t * a) { @@ -716,58 +661,6 @@ vnet_lisp_add_del_map_server (ip_address_t * addr, u8 is_add) return 0; } -static clib_error_t * -lisp_add_del_map_server_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - int rv = 0; - u8 is_add = 1, ip_set = 0; - ip_address_t ip; - unformat_input_t _line_input, *line_input = &_line_input; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "add")) - is_add = 1; - else if (unformat (line_input, "del")) - is_add = 0; - else if (unformat (line_input, "%U", unformat_ip_address, &ip)) - ip_set = 1; - else - { - vlib_cli_output (vm, "parse error: '%U'", - format_unformat_error, line_input); - return 0; - } - } - - if (!ip_set) - { - vlib_cli_output (vm, "map-server ip address not set!"); - return 0; - } - - rv = vnet_lisp_add_del_map_server (&ip, is_add); - if (!rv) - vlib_cli_output (vm, "failed to %s map-server!", - is_add ? "add" : "delete"); - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_add_del_map_server_command) = { - .path = "lisp map-server", - .short_help = "lisp map-server add|del ", - .function = lisp_add_del_map_server_command_fn, -}; -/* *INDENT-ON* */ - /** * Add/remove mapping to/from map-cache. Overwriting not allowed. */ @@ -906,110 +799,6 @@ vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a, return vnet_lisp_map_cache_add_del (a, map_index_result); } -static clib_error_t * -lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - unformat_input_t _line_input, *line_input = &_line_input; - u8 is_add = 1; - gid_address_t eid; - gid_address_t *eids = 0; - clib_error_t *error = 0; - u8 *locator_set_name = 0; - u32 locator_set_index = 0, map_index = 0; - uword *p; - vnet_lisp_add_del_mapping_args_t _a, *a = &_a; - int rv = 0; - u32 vni = 0; - u8 *key = 0; - u32 key_id = 0; - - memset (&eid, 0, sizeof (eid)); - memset (a, 0, sizeof (*a)); - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "add")) - is_add = 1; - else if (unformat (line_input, "del")) - is_add = 0; - else if (unformat (line_input, "eid %U", unformat_gid_address, &eid)) - ; - else if (unformat (line_input, "vni %d", &vni)) - gid_address_vni (&eid) = vni; - else if (unformat (line_input, "secret-key %_%v%_", &key)) - ; - else if (unformat (line_input, "key-id %U", unformat_hmac_key_id, - &key_id)) - ; - else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name)) - { - p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name); - if (!p) - { - error = clib_error_return (0, "locator-set %s doesn't exist", - locator_set_name); - goto done; - } - locator_set_index = p[0]; - } - else - { - error = unformat_parse_error (line_input); - goto done; - } - } - /* XXX treat batch configuration */ - - if (GID_ADDR_SRC_DST == gid_address_type (&eid)) - { - error = - clib_error_return (0, "src/dst is not supported for local EIDs!"); - goto done; - } - - if (key && (0 == key_id)) - { - vlib_cli_output (vm, "invalid key_id!"); - return 0; - } - - gid_address_copy (&a->eid, &eid); - a->is_add = is_add; - a->locator_set_index = locator_set_index; - a->local = 1; - a->key = key; - a->key_id = key_id; - - rv = vnet_lisp_add_del_local_mapping (a, &map_index); - if (0 != rv) - { - error = clib_error_return (0, "failed to %s local mapping!", - is_add ? "add" : "delete"); - } -done: - vec_free (eids); - if (locator_set_name) - vec_free (locator_set_name); - gid_address_free (&a->eid); - vec_free (a->key); - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_add_del_local_eid_command) = { - .path = "lisp eid-table", - .short_help = "lisp eid-table add/del [vni ] eid " - "locator-set [key key-id sha1|sha256 ]", - .function = lisp_add_del_local_eid_command_fn, -}; -/* *INDENT-ON* */ - int vnet_lisp_eid_table_map (u32 vni, u32 dp_id, u8 is_l2, u8 is_add) { @@ -1066,46 +855,6 @@ vnet_lisp_eid_table_map (u32 vni, u32 dp_id, u8 is_l2, u8 is_add) } -static clib_error_t * -lisp_eid_table_map_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - u8 is_add = 1, is_l2 = 0; - u32 vni = 0, dp_id = 0; - unformat_input_t _line_input, *line_input = &_line_input; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "del")) - is_add = 0; - else if (unformat (line_input, "vni %d", &vni)) - ; - else if (unformat (line_input, "vrf %d", &dp_id)) - ; - else if (unformat (line_input, "bd %d", &dp_id)) - is_l2 = 1; - else - { - return unformat_parse_error (line_input); - } - } - vnet_lisp_eid_table_map (vni, dp_id, is_l2, is_add); - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_eid_table_map_command) = { - .path = "lisp eid-table map", - .short_help = "lisp eid-table map [del] vni vrf | bd ", - .function = lisp_eid_table_map_command_fn, -}; -/* *INDENT-ON* */ - /* return 0 if the two locator sets are identical 1 otherwise */ static u8 compare_locators (lisp_cp_main_t * lcm, u32 * old_ls_indexes, @@ -1186,6 +935,7 @@ remove_overlapping_sub_prefixes (lisp_cp_main_t * lcm, gid_address_t * eid, { gid_address_t *e; remove_mapping_args_t a; + memset (&a, 0, sizeof (a)); /* do this only in src/dst mode ... */ @@ -1205,7 +955,14 @@ remove_overlapping_sub_prefixes (lisp_cp_main_t * lcm, gid_address_t * eid, vec_foreach (e, a.eids_to_be_deleted) { - lisp_add_del_adjacency (lcm, 0, e, 0 /* is_add */ ); + vnet_lisp_add_del_adjacency_args_t _adj_args, *adj_args = &_adj_args; + + memset (adj_args, 0, sizeof (adj_args[0])); + gid_address_copy (&adj_args->reid, e); + adj_args->is_add = 0; + if (vnet_lisp_add_del_adjacency (adj_args)) + clib_warning ("failed to del adjacency!"); + vnet_lisp_add_del_mapping (e, 0, 0, 0, 0, 0 /* is add */ , 0, 0); } @@ -1402,10 +1159,10 @@ cleanup: * Note that adjacencies are not stored, they only result in forwarding entries * being created. */ -static int -lisp_add_del_adjacency (lisp_cp_main_t * lcm, gid_address_t * local_eid, - gid_address_t * remote_eid, u8 is_add) +int +vnet_lisp_add_del_adjacency (vnet_lisp_add_del_adjacency_args_t * a) { + lisp_cp_main_t *lcm = &lisp_control_main; u32 local_mi, remote_mi = ~0; if (vnet_lisp_enable_disable_status () == 0) @@ -1415,16 +1172,16 @@ lisp_add_del_adjacency (lisp_cp_main_t * lcm, gid_address_t * local_eid, } remote_mi = gid_dictionary_sd_lookup (&lcm->mapping_index_by_gid, - remote_eid, local_eid); + &a->reid, &a->leid); if (GID_LOOKUP_MISS == remote_mi) { clib_warning ("Remote eid %U not found. Cannot add adjacency!", - format_gid_address, remote_eid); + format_gid_address, &a->reid); return -1; } - if (is_add) + if (a->is_add) { /* TODO 1) check if src/dst 2) once we have src/dst working, use it in * delete*/ @@ -1432,13 +1189,13 @@ lisp_add_del_adjacency (lisp_cp_main_t * lcm, gid_address_t * local_eid, /* check if source eid has an associated mapping. If pitr mode is on, * just use the pitr's mapping */ local_mi = lcm->lisp_pitr ? lcm->pitr_map_index : - gid_dictionary_lookup (&lcm->mapping_index_by_gid, local_eid); + gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->leid); if (GID_LOOKUP_MISS == local_mi) { clib_warning ("Local eid %U not found. Cannot add adjacency!", - format_gid_address, local_eid); + format_gid_address, &a->leid); return -1; } @@ -1453,691 +1210,109 @@ lisp_add_del_adjacency (lisp_cp_main_t * lcm, gid_address_t * local_eid, } int -vnet_lisp_add_del_adjacency (vnet_lisp_add_del_adjacency_args_t * a) +vnet_lisp_set_map_request_mode (u8 mode) { lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - return lisp_add_del_adjacency (lcm, &a->leid, &a->reid, a->is_add); -} - -/** - * Handler for add/del remote mapping CLI. - * - * @param vm vlib context - * @param input input from user - * @param cmd cmd - * @return pointer to clib error structure - */ -static clib_error_t * -lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - clib_error_t *error = 0; - unformat_input_t _line_input, *line_input = &_line_input; - u8 is_add = 1, del_all = 0; - locator_t rloc, *rlocs = 0, *curr_rloc = 0; - gid_address_t eid; - u8 eid_set = 0; - u32 vni, action = ~0, p, w; - int rv; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - memset (&eid, 0, sizeof (eid)); - memset (&rloc, 0, sizeof (rloc)); + if (vnet_lisp_enable_disable_status () == 0) + { + clib_warning ("LISP is disabled!"); + return VNET_API_ERROR_LISP_DISABLED; + } - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + if (mode >= _MR_MODE_MAX) { - if (unformat (line_input, "del-all")) - del_all = 1; - else if (unformat (line_input, "del")) - is_add = 0; - else if (unformat (line_input, "add")) - ; - else if (unformat (line_input, "eid %U", unformat_gid_address, &eid)) - eid_set = 1; - else if (unformat (line_input, "vni %u", &vni)) - { - gid_address_vni (&eid) = vni; - } - else if (unformat (line_input, "p %d w %d", &p, &w)) - { - if (!curr_rloc) - { - clib_warning - ("No RLOC configured for setting priority/weight!"); - goto done; - } - curr_rloc->priority = p; - curr_rloc->weight = w; - } - else if (unformat (line_input, "rloc %U", unformat_ip_address, - &gid_address_ip (&rloc.address))) - { - /* since rloc is stored in ip prefix we need to set prefix length */ - ip_prefix_t *pref = &gid_address_ippref (&rloc.address); + clib_warning ("Invalid LISP map request mode %d!", mode); + return VNET_API_ERROR_INVALID_ARGUMENT; + } - u8 version = gid_address_ip_version (&rloc.address); - ip_prefix_len (pref) = ip_address_max_len (version); + lcm->map_request_mode = mode; + return 0; +} - vec_add1 (rlocs, rloc); - curr_rloc = &rlocs[vec_len (rlocs) - 1]; - } - else if (unformat (line_input, "action %U", - unformat_negative_mapping_action, &action)) - ; - else - { - clib_warning ("parse error"); - goto done; - } +int +vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + u32 locator_set_index = ~0; + mapping_t *m; + uword *p; + + if (vnet_lisp_enable_disable_status () == 0) + { + clib_warning ("LISP is disabled!"); + return VNET_API_ERROR_LISP_DISABLED; } - if (!eid_set) + p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name); + if (!p) { - clib_warning ("missing eid!"); - goto done; + clib_warning ("locator-set %v doesn't exist", locator_set_name); + return -1; } + locator_set_index = p[0]; - if (!del_all) + if (is_add) { - if (is_add && (~0 == action) && 0 == vec_len (rlocs)) - { - clib_warning ("no action set for negative map-reply!"); - goto done; - } + pool_get (lcm->mapping_pool, m); + m->locator_set_index = locator_set_index; + m->local = 1; + lcm->pitr_map_index = m - lcm->mapping_pool; + + /* enable pitr mode */ + lcm->lisp_pitr = 1; } else { - vnet_lisp_clear_all_remote_adjacencies (); - goto done; - } - - /* TODO build src/dst with seid */ + /* remove pitr mapping */ + pool_put_index (lcm->mapping_pool, lcm->pitr_map_index); - /* if it's a delete, clean forwarding */ - if (!is_add) - { - lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - rv = lisp_add_del_adjacency (lcm, 0, &eid, /* is_add */ 0); - if (rv) - { - goto done; - } + /* disable pitr mode */ + lcm->lisp_pitr = 0; } - - /* add as static remote mapping, i.e., not authoritative and infinite - * ttl */ - rv = vnet_lisp_add_del_mapping (&eid, rlocs, action, 0, ~0, is_add, - 1 /* is_static */ , 0); - - if (rv) - clib_warning ("failed to %s remote mapping!", is_add ? "add" : "delete"); - -done: - vec_free (rlocs); - unformat_free (line_input); - return error; + return 0; } -VLIB_CLI_COMMAND (lisp_add_del_remote_mapping_command) = -{ -.path = "lisp remote-mapping",.short_help = - "lisp remote-mapping add|del [del-all] vni " - "eid [action ] rloc p w " - "[rloc ... ]",.function = - lisp_add_del_remote_mapping_command_fn,}; - -/** - * Handler for add/del adjacency CLI. - */ -static clib_error_t * -lisp_add_del_adjacency_command_fn (vlib_main_t * vm, unformat_input_t * input, - vlib_cli_command_t * cmd) +/* cleans locator to locator-set data and removes locators not part of + * any locator-set */ +static void +clean_locator_to_locator_set (lisp_cp_main_t * lcm, u32 lsi) { - clib_error_t *error = 0; - unformat_input_t _line_input, *line_input = &_line_input; - vnet_lisp_add_del_adjacency_args_t _a, *a = &_a; - u8 is_add = 1; - ip_prefix_t *reid_ippref, *leid_ippref; - gid_address_t leid, reid; - u8 *dmac = gid_address_mac (&reid); - u8 *smac = gid_address_mac (&leid); - u8 reid_set = 0, leid_set = 0; - u32 vni; - int rv; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - memset (&reid, 0, sizeof (reid)); - memset (&leid, 0, sizeof (leid)); - - leid_ippref = &gid_address_ippref (&leid); - reid_ippref = &gid_address_ippref (&reid); - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + u32 i, j, *loc_indexp, *ls_indexp, **ls_indexes, *to_be_deleted = 0; + locator_set_t *ls = pool_elt_at_index (lcm->locator_set_pool, lsi); + for (i = 0; i < vec_len (ls->locator_indices); i++) { - if (unformat (line_input, "del")) - is_add = 0; - else if (unformat (line_input, "add")) - ; - else if (unformat (line_input, "reid %U", - unformat_ip_prefix, reid_ippref)) - { - gid_address_type (&reid) = GID_ADDR_IP_PREFIX; - reid_set = 1; - } - else if (unformat (line_input, "reid %U", unformat_mac_address, dmac)) - { - gid_address_type (&reid) = GID_ADDR_MAC; - reid_set = 1; - } - else if (unformat (line_input, "vni %u", &vni)) - { - gid_address_vni (&leid) = vni; - gid_address_vni (&reid) = vni; - } - else if (unformat (line_input, "leid %U", - unformat_ip_prefix, leid_ippref)) - { - gid_address_type (&leid) = GID_ADDR_IP_PREFIX; - leid_set = 1; - } - else if (unformat (line_input, "leid %U", unformat_mac_address, smac)) + loc_indexp = vec_elt_at_index (ls->locator_indices, i); + ls_indexes = vec_elt_at_index (lcm->locator_to_locator_sets, + loc_indexp[0]); + for (j = 0; j < vec_len (ls_indexes[0]); j++) { - gid_address_type (&leid) = GID_ADDR_MAC; - leid_set = 1; + ls_indexp = vec_elt_at_index (ls_indexes[0], j); + if (ls_indexp[0] == lsi) + break; } - else + + /* delete index for removed locator-set */ + vec_del1 (ls_indexes[0], j); + + /* delete locator if it's part of no locator-set */ + if (vec_len (ls_indexes[0]) == 0) { - clib_warning ("parse error"); - goto done; + pool_put_index (lcm->locator_pool, loc_indexp[0]); + vec_add1 (to_be_deleted, i); } } - if (!reid_set || !leid_set) + if (to_be_deleted) { - clib_warning ("missing remote or local eid!"); - goto done; + for (i = 0; i < vec_len (to_be_deleted); i++) + { + loc_indexp = vec_elt_at_index (to_be_deleted, i); + vec_del1 (ls->locator_indices, loc_indexp[0]); + } + vec_free (to_be_deleted); } - - if ((gid_address_type (&leid) != gid_address_type (&reid)) - || (gid_address_type (&reid) == GID_ADDR_IP_PREFIX - && ip_prefix_version (reid_ippref) - != ip_prefix_version (leid_ippref))) - { - clib_warning ("remote and local EIDs are of different types!"); - return error; - } - - memset (a, 0, sizeof (a[0])); - gid_address_copy (&a->leid, &leid); - gid_address_copy (&a->reid, &reid); - - a->is_add = is_add; - rv = vnet_lisp_add_del_adjacency (a); - - if (rv) - clib_warning ("failed to %s adjacency!", is_add ? "add" : "delete"); - -done: - unformat_free (line_input); - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_add_del_adjacency_command) = { - .path = "lisp adjacency", - .short_help = "lisp adjacency add|del vni reid " - "leid ", - .function = lisp_add_del_adjacency_command_fn, -}; -/* *INDENT-ON* */ - -int -vnet_lisp_set_map_request_mode (u8 mode) -{ - lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - - if (vnet_lisp_enable_disable_status () == 0) - { - clib_warning ("LISP is disabled!"); - return VNET_API_ERROR_LISP_DISABLED; - } - - if (mode >= _MR_MODE_MAX) - { - clib_warning ("Invalid LISP map request mode %d!", mode); - return VNET_API_ERROR_INVALID_ARGUMENT; - } - - lcm->map_request_mode = mode; - return 0; -} - -static clib_error_t * -lisp_map_request_mode_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - unformat_input_t _i, *i = &_i; - map_request_mode_t mr_mode = _MR_MODE_MAX; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, i)) - return 0; - - while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) - { - if (unformat (i, "dst-only")) - mr_mode = MR_MODE_DST_ONLY; - else if (unformat (i, "src-dst")) - mr_mode = MR_MODE_SRC_DST; - else - { - clib_warning ("parse error '%U'", format_unformat_error, i); - goto done; - } - } - - if (_MR_MODE_MAX == mr_mode) - { - clib_warning ("No LISP map request mode entered!"); - return 0; - } - - vnet_lisp_set_map_request_mode (mr_mode); -done: - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_map_request_mode_command) = { - .path = "lisp map-request mode", - .short_help = "lisp map-request mode dst-only|src-dst", - .function = lisp_map_request_mode_command_fn, -}; -/* *INDENT-ON* */ - -static u8 * -format_lisp_map_request_mode (u8 * s, va_list * args) -{ - u32 mode = va_arg (*args, u32); - - switch (mode) - { - case 0: - return format (0, "dst-only"); - case 1: - return format (0, "src-dst"); - } - return 0; -} - -static clib_error_t * -lisp_show_map_request_mode_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - vlib_cli_output (vm, "map-request mode: %U", format_lisp_map_request_mode, - vnet_lisp_get_map_request_mode ()); - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_show_map_request_mode_command) = { - .path = "show lisp map-request mode", - .short_help = "show lisp map-request mode", - .function = lisp_show_map_request_mode_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -lisp_show_map_resolvers_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - lisp_msmr_t *mr; - lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - - vec_foreach (mr, lcm->map_resolvers) - { - vlib_cli_output (vm, "%U", format_ip_address, &mr->address); - } - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_show_map_resolvers_command) = { - .path = "show lisp map-resolvers", - .short_help = "show lisp map-resolvers", - .function = lisp_show_map_resolvers_command_fn, -}; -/* *INDENT-ON* */ - -int -vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add) -{ - lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - u32 locator_set_index = ~0; - mapping_t *m; - uword *p; - - if (vnet_lisp_enable_disable_status () == 0) - { - clib_warning ("LISP is disabled!"); - return VNET_API_ERROR_LISP_DISABLED; - } - - p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name); - if (!p) - { - clib_warning ("locator-set %v doesn't exist", locator_set_name); - return -1; - } - locator_set_index = p[0]; - - if (is_add) - { - pool_get (lcm->mapping_pool, m); - m->locator_set_index = locator_set_index; - m->local = 1; - lcm->pitr_map_index = m - lcm->mapping_pool; - - /* enable pitr mode */ - lcm->lisp_pitr = 1; - } - else - { - /* remove pitr mapping */ - pool_put_index (lcm->mapping_pool, lcm->pitr_map_index); - - /* disable pitr mode */ - lcm->lisp_pitr = 0; - } - return 0; -} - -static clib_error_t * -lisp_pitr_set_locator_set_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - u8 locator_name_set = 0; - u8 *locator_set_name = 0; - u8 is_add = 1; - unformat_input_t _line_input, *line_input = &_line_input; - clib_error_t *error = 0; - int rv = 0; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "ls %_%v%_", &locator_set_name)) - locator_name_set = 1; - else if (unformat (line_input, "disable")) - is_add = 0; - else - return clib_error_return (0, "parse error"); - } - - if (!locator_name_set) - { - clib_warning ("No locator set specified!"); - goto done; - } - rv = vnet_lisp_pitr_set_locator_set (locator_set_name, is_add); - if (0 != rv) - { - error = clib_error_return (0, "failed to %s pitr!", - is_add ? "add" : "delete"); - } - -done: - if (locator_set_name) - vec_free (locator_set_name); - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_pitr_set_locator_set_command) = { - .path = "lisp pitr", - .short_help = "lisp pitr [disable] ls ", - .function = lisp_pitr_set_locator_set_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -lisp_show_pitr_command_fn (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - mapping_t *m; - locator_set_t *ls; - u8 *tmp_str = 0; - - vlib_cli_output (vm, "%=20s%=16s", - "pitr", lcm->lisp_pitr ? "locator-set" : ""); - - if (!lcm->lisp_pitr) - { - vlib_cli_output (vm, "%=20s", "disable"); - return 0; - } - - if (~0 == lcm->pitr_map_index) - { - tmp_str = format (0, "N/A"); - } - else - { - m = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index); - if (~0 != m->locator_set_index) - { - ls = - pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index); - tmp_str = format (0, "%s", ls->name); - } - else - { - tmp_str = format (0, "N/A"); - } - } - vec_add1 (tmp_str, 0); - - vlib_cli_output (vm, "%=20s%=16s", "enable", tmp_str); - - vec_free (tmp_str); - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_show_pitr_command) = { - .path = "show lisp pitr", - .short_help = "Show pitr", - .function = lisp_show_pitr_command_fn, -}; -/* *INDENT-ON* */ - -static u8 * -format_eid_entry (u8 * s, va_list * args) -{ - vnet_main_t *vnm = va_arg (*args, vnet_main_t *); - lisp_cp_main_t *lcm = va_arg (*args, lisp_cp_main_t *); - mapping_t *mapit = va_arg (*args, mapping_t *); - locator_set_t *ls = va_arg (*args, locator_set_t *); - gid_address_t *gid = &mapit->eid; - u32 ttl = mapit->ttl; - u8 aut = mapit->authoritative; - u32 *loc_index; - u8 first_line = 1; - u8 *loc; - - u8 *type = ls->local ? format (0, "local(%s)", ls->name) - : format (0, "remote"); - - if (vec_len (ls->locator_indices) == 0) - { - s = format (s, "%-35U%-30s%-20u%-u", format_gid_address, gid, - type, ttl, aut); - } - else - { - vec_foreach (loc_index, ls->locator_indices) - { - locator_t *l = pool_elt_at_index (lcm->locator_pool, loc_index[0]); - if (l->local) - loc = format (0, "%U", format_vnet_sw_if_index_name, vnm, - l->sw_if_index); - else - loc = format (0, "%U", format_ip_address, - &gid_address_ip (&l->address)); - - if (first_line) - { - s = format (s, "%-35U%-20s%-30v%-20u%-u\n", format_gid_address, - gid, type, loc, ttl, aut); - first_line = 0; - } - else - s = format (s, "%55s%v\n", "", loc); - } - } - return s; -} - -static clib_error_t * -lisp_show_eid_table_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - mapping_t *mapit; - unformat_input_t _line_input, *line_input = &_line_input; - u32 mi; - gid_address_t eid; - u8 print_all = 1; - u8 filter = 0; - - memset (&eid, 0, sizeof (eid)); - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "eid %U", unformat_gid_address, &eid)) - print_all = 0; - else if (unformat (line_input, "local")) - filter = 1; - else if (unformat (line_input, "remote")) - filter = 2; - else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); - } - - vlib_cli_output (vm, "%-35s%-20s%-30s%-20s%-s", - "EID", "type", "locators", "ttl", "autoritative"); - - if (print_all) - { - /* *INDENT-OFF* */ - pool_foreach (mapit, lcm->mapping_pool, - ({ - locator_set_t * ls = pool_elt_at_index (lcm->locator_set_pool, - mapit->locator_set_index); - if (filter && !((1 == filter && ls->local) || - (2 == filter && !ls->local))) - { - continue; - } - vlib_cli_output (vm, "%U", format_eid_entry, lcm->vnet_main, - lcm, mapit, ls); - })); - /* *INDENT-ON* */ - } - else - { - mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &eid); - if ((u32) ~ 0 == mi) - return 0; - - mapit = pool_elt_at_index (lcm->mapping_pool, mi); - locator_set_t *ls = pool_elt_at_index (lcm->locator_set_pool, - mapit->locator_set_index); - - if (filter && !((1 == filter && ls->local) || - (2 == filter && !ls->local))) - { - return 0; - } - - vlib_cli_output (vm, "%U,", format_eid_entry, lcm->vnet_main, - lcm, mapit, ls); - } - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_cp_show_eid_table_command) = { - .path = "show lisp eid-table", - .short_help = "Shows EID table", - .function = lisp_show_eid_table_command_fn, -}; -/* *INDENT-ON* */ - -/* cleans locator to locator-set data and removes locators not part of - * any locator-set */ -static void -clean_locator_to_locator_set (lisp_cp_main_t * lcm, u32 lsi) -{ - u32 i, j, *loc_indexp, *ls_indexp, **ls_indexes, *to_be_deleted = 0; - locator_set_t *ls = pool_elt_at_index (lcm->locator_set_pool, lsi); - for (i = 0; i < vec_len (ls->locator_indices); i++) - { - loc_indexp = vec_elt_at_index (ls->locator_indices, i); - ls_indexes = vec_elt_at_index (lcm->locator_to_locator_sets, - loc_indexp[0]); - for (j = 0; j < vec_len (ls_indexes[0]); j++) - { - ls_indexp = vec_elt_at_index (ls_indexes[0], j); - if (ls_indexp[0] == lsi) - break; - } - - /* delete index for removed locator-set */ - vec_del1 (ls_indexes[0], j); - - /* delete locator if it's part of no locator-set */ - if (vec_len (ls_indexes[0]) == 0) - { - pool_put_index (lcm->locator_pool, loc_indexp[0]); - vec_add1 (to_be_deleted, i); - } - } - - if (to_be_deleted) - { - for (i = 0; i < vec_len (to_be_deleted); i++) - { - loc_indexp = vec_elt_at_index (to_be_deleted, i); - vec_del1 (ls->locator_indices, loc_indexp[0]); - } - vec_free (to_be_deleted); - } -} +} static inline uword * get_locator_set_index (vnet_lisp_add_del_locator_set_args_t * a, uword * p) @@ -2380,550 +1555,123 @@ vnet_lisp_add_del_locator_set (vnet_lisp_add_del_locator_set_args_t * a, return -1; } - ls = pool_elt_at_index (lcm->locator_set_pool, p[0]); - if (!ls) - { - clib_warning ("locator-set with index %d doesn't exists", p[0]); - return -1; - } - - if (lcm->mreq_itr_rlocs == p[0]) - { - clib_warning ("Can't delete the locator-set used to constrain " - "the itr-rlocs in map-requests!"); - return -1; - } - - if (vec_len (lcm->locator_set_to_eids) != 0) - { - eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids, p[0]); - if (vec_len (eid_indexes[0]) != 0) - { - clib_warning - ("Can't delete a locator that supports a mapping!"); - return -1; - } - } - - /* clean locator to locator-sets data */ - clean_locator_to_locator_set (lcm, p[0]); - - if (ls->local) - { - u32 it, lsi; - - vec_foreach_index (it, lcm->local_locator_set_indexes) - { - lsi = vec_elt (lcm->local_locator_set_indexes, it); - if (lsi == p[0]) - { - vec_del1 (lcm->local_locator_set_indexes, it); - break; - } - } - hash_unset_mem (lcm->locator_set_index_by_name, ls->name); - } - vec_free (ls->name); - vec_free (ls->locator_indices); - pool_put (lcm->locator_set_pool, ls); - } - return 0; -} - -int -vnet_lisp_rloc_probe_enable_disable (u8 is_enable) -{ - lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - - lcm->rloc_probing = is_enable; - return 0; -} - -int -vnet_lisp_map_register_enable_disable (u8 is_enable) -{ - lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - - lcm->map_registering = is_enable; - return 0; -} - -clib_error_t * -vnet_lisp_enable_disable (u8 is_enable) -{ - u32 vni, dp_table; - clib_error_t *error = 0; - lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a; - - a->is_en = is_enable; - error = vnet_lisp_gpe_enable_disable (a); - if (error) - { - return clib_error_return (0, "failed to %s data-plane!", - a->is_en ? "enable" : "disable"); - } - - if (is_enable) - { - /* enable all l2 and l3 ifaces */ - - /* *INDENT-OFF* */ - hash_foreach(vni, dp_table, lcm->table_id_by_vni, ({ - dp_add_del_iface(lcm, vni, 0, 1); - })); - hash_foreach(vni, dp_table, lcm->bd_id_by_vni, ({ - dp_add_del_iface(lcm, vni, /* is_l2 */ 1, 1); - })); - /* *INDENT-ON* */ - } - else - { - /* clear interface table */ - hash_free (lcm->fwd_entry_by_mapping_index); - pool_free (lcm->fwd_entry_pool); - } - - /* update global flag */ - lcm->is_enabled = is_enable; - - return 0; -} - -static clib_error_t * -lisp_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - u8 is_enabled = 0; - u8 is_set = 0; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "enable")) - { - is_set = 1; - is_enabled = 1; - } - else if (unformat (line_input, "disable")) - is_set = 1; - else - { - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); - } - } - - if (!is_set) - return clib_error_return (0, "state not set"); - - vnet_lisp_enable_disable (is_enabled); - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_cp_enable_disable_command) = { - .path = "lisp", - .short_help = "lisp [enable|disable]", - .function = lisp_enable_disable_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -lisp_map_register_enable_disable_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - u8 is_enabled = 0; - u8 is_set = 0; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "enable")) - { - is_set = 1; - is_enabled = 1; - } - else if (unformat (line_input, "disable")) - is_set = 1; - else - { - vlib_cli_output (vm, "parse error: '%U'", format_unformat_error, - line_input); - return 0; - } - } - - if (!is_set) - { - vlib_cli_output (vm, "state not set!"); - return 0; - } - - vnet_lisp_map_register_enable_disable (is_enabled); - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_map_register_enable_disable_command) = { - .path = "lisp map-register", - .short_help = "lisp map-register [enable|disable]", - .function = lisp_map_register_enable_disable_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -lisp_rloc_probe_enable_disable_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - u8 is_enabled = 0; - u8 is_set = 0; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "enable")) + ls = pool_elt_at_index (lcm->locator_set_pool, p[0]); + if (!ls) { - is_set = 1; - is_enabled = 1; + clib_warning ("locator-set with index %d doesn't exists", p[0]); + return -1; } - else if (unformat (line_input, "disable")) - is_set = 1; - else + + if (lcm->mreq_itr_rlocs == p[0]) { - vlib_cli_output (vm, "parse error: '%U'", format_unformat_error, - line_input); - return 0; + clib_warning ("Can't delete the locator-set used to constrain " + "the itr-rlocs in map-requests!"); + return -1; } - } - if (!is_set) - { - vlib_cli_output (vm, "state not set!"); - return 0; - } + if (vec_len (lcm->locator_set_to_eids) != 0) + { + eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids, p[0]); + if (vec_len (eid_indexes[0]) != 0) + { + clib_warning + ("Can't delete a locator that supports a mapping!"); + return -1; + } + } - vnet_lisp_rloc_probe_enable_disable (is_enabled); - return 0; -} + /* clean locator to locator-sets data */ + clean_locator_to_locator_set (lcm, p[0]); -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_rloc_probe_enable_disable_command) = { - .path = "lisp rloc-probe", - .short_help = "lisp rloc-probe [enable|disable]", - .function = lisp_rloc_probe_enable_disable_command_fn, -}; -/* *INDENT-ON* */ + if (ls->local) + { + u32 it, lsi; -u8 -vnet_lisp_enable_disable_status (void) -{ - lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - return lcm->is_enabled; + vec_foreach_index (it, lcm->local_locator_set_indexes) + { + lsi = vec_elt (lcm->local_locator_set_indexes, it); + if (lsi == p[0]) + { + vec_del1 (lcm->local_locator_set_indexes, it); + break; + } + } + hash_unset_mem (lcm->locator_set_index_by_name, ls->name); + } + vec_free (ls->name); + vec_free (ls->locator_indices); + pool_put (lcm->locator_set_pool, ls); + } + return 0; } -static u8 * -format_lisp_status (u8 * s, va_list * args) +int +vnet_lisp_rloc_probe_enable_disable (u8 is_enable) { lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - return format (s, "%s", lcm->is_enabled ? "enabled" : "disabled"); -} -static clib_error_t * -lisp_show_status_command_fn (vlib_main_t * vm, unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - u8 *msg = 0; - msg = format (msg, "feature: %U\ngpe: %U\n", - format_lisp_status, format_vnet_lisp_gpe_status); - vlib_cli_output (vm, "%v", msg); - vec_free (msg); + lcm->rloc_probing = is_enable; return 0; } -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_show_status_command) = { - .path = "show lisp status", - .short_help = "show lisp status", - .function = lisp_show_status_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -lisp_show_eid_table_map_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) +int +vnet_lisp_map_register_enable_disable (u8 is_enable) { - hash_pair_t *p; - unformat_input_t _line_input, *line_input = &_line_input; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - uword *vni_table = 0; - u8 is_l2 = 0; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "l2")) - { - vni_table = lcm->bd_id_by_vni; - is_l2 = 1; - } - else if (unformat (line_input, "l3")) - { - vni_table = lcm->table_id_by_vni; - is_l2 = 0; - } - else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); - } - - if (!vni_table) - { - vlib_cli_output (vm, "Error: expected l2|l3 param!\n"); - return 0; - } - - vlib_cli_output (vm, "%=10s%=10s", "VNI", is_l2 ? "BD" : "VRF"); - - /* *INDENT-OFF* */ - hash_foreach_pair (p, vni_table, - ({ - vlib_cli_output (vm, "%=10d%=10d", p->key, p->value[0]); - })); - /* *INDENT-ON* */ + lcm->map_registering = is_enable; return 0; } -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_show_eid_table_map_command) = { - .path = "show lisp eid-table map", - .short_help = "show lisp eid-table l2|l3", - .function = lisp_show_eid_table_map_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -lisp_add_del_locator_set_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) +clib_error_t * +vnet_lisp_enable_disable (u8 is_enable) { - lisp_gpe_main_t *lgm = &lisp_gpe_main; - vnet_main_t *vnm = lgm->vnet_main; - unformat_input_t _line_input, *line_input = &_line_input; - u8 is_add = 1; + u32 vni, dp_table; clib_error_t *error = 0; - u8 *locator_set_name = 0; - locator_t locator, *locators = 0; - vnet_lisp_add_del_locator_set_args_t _a, *a = &_a; - u32 ls_index = 0; - int rv = 0; - - memset (&locator, 0, sizeof (locator)); - memset (a, 0, sizeof (a[0])); - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a; - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + a->is_en = is_enable; + error = vnet_lisp_gpe_enable_disable (a); + if (error) { - if (unformat (line_input, "add %_%v%_", &locator_set_name)) - is_add = 1; - else if (unformat (line_input, "del %_%v%_", &locator_set_name)) - is_add = 0; - else if (unformat (line_input, "iface %U p %d w %d", - unformat_vnet_sw_interface, vnm, - &locator.sw_if_index, &locator.priority, - &locator.weight)) - { - locator.local = 1; - vec_add1 (locators, locator); - } - else - { - error = unformat_parse_error (line_input); - goto done; - } + return clib_error_return (0, "failed to %s data-plane!", + a->is_en ? "enable" : "disable"); } - a->name = locator_set_name; - a->locators = locators; - a->is_add = is_add; - a->local = 1; - - rv = vnet_lisp_add_del_locator_set (a, &ls_index); - if (0 != rv) + if (is_enable) { - error = clib_error_return (0, "failed to %s locator-set!", - is_add ? "add" : "delete"); - } - -done: - vec_free (locators); - if (locator_set_name) - vec_free (locator_set_name); - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_cp_add_del_locator_set_command) = { - .path = "lisp locator-set", - .short_help = "lisp locator-set add/del [iface " - "p w ]", - .function = lisp_add_del_locator_set_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -lisp_add_del_locator_in_set_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - vnet_main_t *vnm = lgm->vnet_main; - unformat_input_t _line_input, *line_input = &_line_input; - u8 is_add = 1; - clib_error_t *error = 0; - u8 *locator_set_name = 0; - u8 locator_set_name_set = 0; - locator_t locator, *locators = 0; - vnet_lisp_add_del_locator_set_args_t _a, *a = &_a; - u32 ls_index = 0; - - memset (&locator, 0, sizeof (locator)); - memset (a, 0, sizeof (a[0])); - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; + /* enable all l2 and l3 ifaces */ - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "add")) - is_add = 1; - else if (unformat (line_input, "del")) - is_add = 0; - else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name)) - locator_set_name_set = 1; - else if (unformat (line_input, "iface %U p %d w %d", - unformat_vnet_sw_interface, vnm, - &locator.sw_if_index, &locator.priority, - &locator.weight)) - { - locator.local = 1; - vec_add1 (locators, locator); - } - else - { - error = unformat_parse_error (line_input); - goto done; - } + /* *INDENT-OFF* */ + hash_foreach(vni, dp_table, lcm->table_id_by_vni, ({ + dp_add_del_iface(lcm, vni, 0, 1); + })); + hash_foreach(vni, dp_table, lcm->bd_id_by_vni, ({ + dp_add_del_iface(lcm, vni, /* is_l2 */ 1, 1); + })); + /* *INDENT-ON* */ } - - if (!locator_set_name_set) + else { - error = clib_error_return (0, "locator_set name not set!"); - goto done; + /* clear interface table */ + hash_free (lcm->fwd_entry_by_mapping_index); + pool_free (lcm->fwd_entry_pool); } - a->name = locator_set_name; - a->locators = locators; - a->is_add = is_add; - a->local = 1; - - vnet_lisp_add_del_locator (a, 0, &ls_index); + /* update global flag */ + lcm->is_enabled = is_enable; -done: - vec_free (locators); - vec_free (locator_set_name); - return error; + return 0; } -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_cp_add_del_locator_in_set_command) = { - .path = "lisp locator", - .short_help = "lisp locator add/del locator-set iface " - "p w ", - .function = lisp_add_del_locator_in_set_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -lisp_cp_show_locator_sets_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) +u8 +vnet_lisp_enable_disable_status (void) { - locator_set_t *lsit; - locator_t *loc; - u32 *locit; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - - vlib_cli_output (vm, "%s%=16s%=16s%=16s", "Locator-set", "Locator", - "Priority", "Weight"); - - /* *INDENT-OFF* */ - pool_foreach (lsit, lcm->locator_set_pool, - ({ - u8 * msg = 0; - int next_line = 0; - if (lsit->local) - { - msg = format (msg, "%v", lsit->name); - } - else - { - msg = format (msg, "<%s-%d>", "remote", lsit - lcm->locator_set_pool); - } - vec_foreach (locit, lsit->locator_indices) - { - if (next_line) - { - msg = format (msg, "%16s", " "); - } - loc = pool_elt_at_index (lcm->locator_pool, locit[0]); - if (loc->local) - msg = format (msg, "%16d%16d%16d\n", loc->sw_if_index, loc->priority, - loc->weight); - else - msg = format (msg, "%16U%16d%16d\n", format_ip_address, - &gid_address_ip(&loc->address), loc->priority, - loc->weight); - next_line = 1; - } - vlib_cli_output (vm, "%v", msg); - vec_free (msg); - })); - /* *INDENT-ON* */ - return 0; + return lcm->is_enabled; } -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_cp_show_locator_sets_command) = { - .path = "show lisp locator-set", - .short_help = "Shows locator-sets", - .function = lisp_cp_show_locator_sets_command_fn, -}; -/* *INDENT-ON* */ - int vnet_lisp_add_del_map_resolver (vnet_lisp_add_del_map_resolver_args_t * a) { @@ -2972,64 +1720,6 @@ vnet_lisp_add_del_map_resolver (vnet_lisp_add_del_map_resolver_args_t * a) return 0; } -static clib_error_t * -lisp_add_del_map_resolver_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - u8 is_add = 1, addr_set = 0; - ip_address_t ip_addr; - clib_error_t *error = 0; - int rv = 0; - vnet_lisp_add_del_map_resolver_args_t _a, *a = &_a; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "add")) - is_add = 1; - else if (unformat (line_input, "del")) - is_add = 0; - else if (unformat (line_input, "%U", unformat_ip_address, &ip_addr)) - addr_set = 1; - else - { - error = unformat_parse_error (line_input); - goto done; - } - } - - if (!addr_set) - { - error = clib_error_return (0, "Map-resolver address must be set!"); - goto done; - } - - a->is_add = is_add; - a->address = ip_addr; - rv = vnet_lisp_add_del_map_resolver (a); - if (0 != rv) - { - error = clib_error_return (0, "failed to %s map-resolver!", - is_add ? "add" : "delete"); - } - -done: - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_add_del_map_resolver_command) = { - .path = "lisp map-resolver", - .short_help = "lisp map-resolver add/del ", - .function = lisp_add_del_map_resolver_command_fn, -}; -/* *INDENT-ON* */ - int vnet_lisp_add_del_mreq_itr_rlocs (vnet_lisp_add_del_mreq_itr_rloc_args_t * a) { @@ -3061,89 +1751,6 @@ vnet_lisp_add_del_mreq_itr_rlocs (vnet_lisp_add_del_mreq_itr_rloc_args_t * a) return 0; } -static clib_error_t * -lisp_add_del_mreq_itr_rlocs_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - u8 is_add = 1; - u8 *locator_set_name = 0; - clib_error_t *error = 0; - int rv = 0; - vnet_lisp_add_del_mreq_itr_rloc_args_t _a, *a = &_a; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "del")) - is_add = 0; - else if (unformat (line_input, "add %_%v%_", &locator_set_name)) - is_add = 1; - else - { - error = unformat_parse_error (line_input); - goto done; - } - } - - a->is_add = is_add; - a->locator_set_name = locator_set_name; - rv = vnet_lisp_add_del_mreq_itr_rlocs (a); - if (0 != rv) - { - error = clib_error_return (0, "failed to %s map-request itr-rlocs!", - is_add ? "add" : "delete"); - } - - vec_free (locator_set_name); - -done: - return error; - -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_add_del_map_request_command) = { - .path = "lisp map-request itr-rlocs", - .short_help = "lisp map-request itr-rlocs add/del ", - .function = lisp_add_del_mreq_itr_rlocs_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -lisp_show_mreq_itr_rlocs_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - locator_set_t *loc_set; - - vlib_cli_output (vm, "%=20s", "itr-rlocs"); - - if (~0 == lcm->mreq_itr_rlocs) - { - return 0; - } - - loc_set = pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs); - - vlib_cli_output (vm, "%=20s", loc_set->name); - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_show_map_request_command) = { - .path = "show lisp map-request itr-rlocs", - .short_help = "Shows map-request itr-rlocs", - .function = lisp_show_mreq_itr_rlocs_command_fn, -}; -/* *INDENT-ON* */ - /* Statistics (not really errors) */ #define foreach_lisp_cp_lookup_error \ _(DROP, "drop") \ @@ -4204,9 +2811,16 @@ static void remove_expired_mapping (lisp_cp_main_t * lcm, u32 mi) { mapping_t *m; + vnet_lisp_add_del_adjacency_args_t _adj_args, *adj_args = &_adj_args; + memset (adj_args, 0, sizeof (adj_args[0])); m = pool_elt_at_index (lcm->mapping_pool, mi); - lisp_add_del_adjacency (lcm, 0, &m->eid, 0 /* is_add */ ); + + gid_address_copy (&adj_args->reid, &m->eid); + adj_args->is_add = 0; + if (vnet_lisp_add_del_adjacency (adj_args)) + clib_warning ("failed to del adjacency!"); + vnet_lisp_add_del_mapping (&m->eid, 0, 0, 0, ~0, 0 /* is_add */ , 0 /* is_static */ , 0); mapping_delete_timer (lcm, mi); @@ -4272,7 +2886,15 @@ process_map_reply (map_records_arg_t * a) /* try to program forwarding only if mapping saved or updated */ if ((u32) ~ 0 != dst_map_index) { - lisp_add_del_adjacency (lcm, &pmr->src, &m->eid, 1); + vnet_lisp_add_del_adjacency_args_t _adj_args, *adj_args = &_adj_args; + memset (adj_args, 0, sizeof (adj_args[0])); + + gid_address_copy (&adj_args->leid, &pmr->src); + gid_address_copy (&adj_args->reid, &m->eid); + adj_args->is_add = 1; + if (vnet_lisp_add_del_adjacency (adj_args)) + clib_warning ("failed to add adjacency!"); + if ((u32) ~ 0 != m->ttl) mapping_start_expiration_timer (lcm, dst_map_index, m->ttl * 60); } diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index e89c6fd6..aa76a424 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -196,7 +196,7 @@ typedef struct } lisp_cp_main_t; /* lisp-gpe control plane */ -lisp_cp_main_t lisp_control_main; +extern lisp_cp_main_t lisp_control_main; extern vlib_node_registration_t lisp_cp_input_node; extern vlib_node_registration_t lisp_cp_lookup_ip4_node; diff --git a/src/vnet/lisp-cp/lisp_cli.c b/src/vnet/lisp-cp/lisp_cli.c new file mode 100644 index 00000000..bb859ff1 --- /dev/null +++ b/src/vnet/lisp-cp/lisp_cli.c @@ -0,0 +1,1423 @@ +/* + * 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. + */ + +#include +#include + +static clib_error_t * +lisp_show_adjacencies_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + lisp_adjacency_t *adjs, *adj; + vlib_cli_output (vm, "%s %40s\n", "leid", "reid"); + unformat_input_t _line_input, *line_input = &_line_input; + u32 vni = ~0; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "vni %d", &vni)) + ; + else + { + vlib_cli_output (vm, "parse error: '%U'", + format_unformat_error, line_input); + return 0; + } + } + + if (~0 == vni) + { + vlib_cli_output (vm, "error: no vni specified!"); + return 0; + } + + adjs = vnet_lisp_adjacencies_get_by_vni (vni); + + vec_foreach (adj, adjs) + { + vlib_cli_output (vm, "%U %40U\n", format_gid_address, &adj->leid, + format_gid_address, &adj->reid); + } + vec_free (adjs); + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_show_adjacencies_command) = { + .path = "show lisp adjacencies", + .short_help = "show lisp adjacencies", + .function = lisp_show_adjacencies_command_fn, +}; +/* *INDENT-ON* */ + +static clib_error_t * +lisp_add_del_map_server_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + int rv = 0; + u8 is_add = 1, ip_set = 0; + ip_address_t ip; + unformat_input_t _line_input, *line_input = &_line_input; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "add")) + is_add = 1; + else if (unformat (line_input, "del")) + is_add = 0; + else if (unformat (line_input, "%U", unformat_ip_address, &ip)) + ip_set = 1; + else + { + vlib_cli_output (vm, "parse error: '%U'", + format_unformat_error, line_input); + return 0; + } + } + + if (!ip_set) + { + vlib_cli_output (vm, "map-server ip address not set!"); + return 0; + } + + rv = vnet_lisp_add_del_map_server (&ip, is_add); + if (!rv) + vlib_cli_output (vm, "failed to %s map-server!", + is_add ? "add" : "delete"); + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_add_del_map_server_command) = { + .path = "lisp map-server", + .short_help = "lisp map-server add|del ", + .function = lisp_add_del_map_server_command_fn, +}; +/* *INDENT-ON* */ + + +static clib_error_t * +lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + unformat_input_t _line_input, *line_input = &_line_input; + u8 is_add = 1; + gid_address_t eid; + gid_address_t *eids = 0; + clib_error_t *error = 0; + u8 *locator_set_name = 0; + u32 locator_set_index = 0, map_index = 0; + uword *p; + vnet_lisp_add_del_mapping_args_t _a, *a = &_a; + int rv = 0; + u32 vni = 0; + u8 *key = 0; + u32 key_id = 0; + + memset (&eid, 0, sizeof (eid)); + memset (a, 0, sizeof (*a)); + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "add")) + is_add = 1; + else if (unformat (line_input, "del")) + is_add = 0; + else if (unformat (line_input, "eid %U", unformat_gid_address, &eid)) + ; + else if (unformat (line_input, "vni %d", &vni)) + gid_address_vni (&eid) = vni; + else if (unformat (line_input, "secret-key %_%v%_", &key)) + ; + else if (unformat (line_input, "key-id %U", unformat_hmac_key_id, + &key_id)) + ; + else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name)) + { + p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name); + if (!p) + { + error = clib_error_return (0, "locator-set %s doesn't exist", + locator_set_name); + goto done; + } + locator_set_index = p[0]; + } + else + { + error = unformat_parse_error (line_input); + goto done; + } + } + /* XXX treat batch configuration */ + + if (GID_ADDR_SRC_DST == gid_address_type (&eid)) + { + error = + clib_error_return (0, "src/dst is not supported for local EIDs!"); + goto done; + } + + if (key && (0 == key_id)) + { + vlib_cli_output (vm, "invalid key_id!"); + return 0; + } + + gid_address_copy (&a->eid, &eid); + a->is_add = is_add; + a->locator_set_index = locator_set_index; + a->local = 1; + a->key = key; + a->key_id = key_id; + + rv = vnet_lisp_add_del_local_mapping (a, &map_index); + if (0 != rv) + { + error = clib_error_return (0, "failed to %s local mapping!", + is_add ? "add" : "delete"); + } +done: + vec_free (eids); + if (locator_set_name) + vec_free (locator_set_name); + gid_address_free (&a->eid); + vec_free (a->key); + return error; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_add_del_local_eid_command) = { + .path = "lisp eid-table", + .short_help = "lisp eid-table add/del [vni ] eid " + "locator-set [key key-id sha1|sha256 ]", + .function = lisp_add_del_local_eid_command_fn, +}; +/* *INDENT-ON* */ + +static clib_error_t * +lisp_eid_table_map_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + u8 is_add = 1, is_l2 = 0; + u32 vni = 0, dp_id = 0; + unformat_input_t _line_input, *line_input = &_line_input; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "del")) + is_add = 0; + else if (unformat (line_input, "vni %d", &vni)) + ; + else if (unformat (line_input, "vrf %d", &dp_id)) + ; + else if (unformat (line_input, "bd %d", &dp_id)) + is_l2 = 1; + else + { + return unformat_parse_error (line_input); + } + } + vnet_lisp_eid_table_map (vni, dp_id, is_l2, is_add); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_eid_table_map_command) = { + .path = "lisp eid-table map", + .short_help = "lisp eid-table map [del] vni vrf | bd ", + .function = lisp_eid_table_map_command_fn, +}; +/* *INDENT-ON* */ + +/** + * Handler for add/del remote mapping CLI. + * + * @param vm vlib context + * @param input input from user + * @param cmd cmd + * @return pointer to clib error structure + */ +static clib_error_t * +lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + clib_error_t *error = 0; + unformat_input_t _line_input, *line_input = &_line_input; + u8 is_add = 1, del_all = 0; + locator_t rloc, *rlocs = 0, *curr_rloc = 0; + gid_address_t eid; + u8 eid_set = 0; + u32 vni, action = ~0, p, w; + int rv; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + memset (&eid, 0, sizeof (eid)); + memset (&rloc, 0, sizeof (rloc)); + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "del-all")) + del_all = 1; + else if (unformat (line_input, "del")) + is_add = 0; + else if (unformat (line_input, "add")) + ; + else if (unformat (line_input, "eid %U", unformat_gid_address, &eid)) + eid_set = 1; + else if (unformat (line_input, "vni %u", &vni)) + { + gid_address_vni (&eid) = vni; + } + else if (unformat (line_input, "p %d w %d", &p, &w)) + { + if (!curr_rloc) + { + clib_warning + ("No RLOC configured for setting priority/weight!"); + goto done; + } + curr_rloc->priority = p; + curr_rloc->weight = w; + } + else if (unformat (line_input, "rloc %U", unformat_ip_address, + &gid_address_ip (&rloc.address))) + { + /* since rloc is stored in ip prefix we need to set prefix length */ + ip_prefix_t *pref = &gid_address_ippref (&rloc.address); + + u8 version = gid_address_ip_version (&rloc.address); + ip_prefix_len (pref) = ip_address_max_len (version); + + vec_add1 (rlocs, rloc); + curr_rloc = &rlocs[vec_len (rlocs) - 1]; + } + else if (unformat (line_input, "action %U", + unformat_negative_mapping_action, &action)) + ; + else + { + clib_warning ("parse error"); + goto done; + } + } + + if (!eid_set) + { + clib_warning ("missing eid!"); + goto done; + } + + if (!del_all) + { + if (is_add && (~0 == action) && 0 == vec_len (rlocs)) + { + clib_warning ("no action set for negative map-reply!"); + goto done; + } + } + else + { + vnet_lisp_clear_all_remote_adjacencies (); + goto done; + } + + /* TODO build src/dst with seid */ + + /* if it's a delete, clean forwarding */ + if (!is_add) + { + vnet_lisp_add_del_adjacency_args_t _a, *a = &_a; + memset (a, 0, sizeof (a[0])); + gid_address_copy (&a->reid, &eid); + if (vnet_lisp_add_del_adjacency (a)) + { + clib_warning ("failed to delete adjacency!"); + goto done; + } + } + + /* add as static remote mapping, i.e., not authoritative and infinite + * ttl */ + rv = vnet_lisp_add_del_mapping (&eid, rlocs, action, 0, ~0, is_add, + 1 /* is_static */ , 0); + + if (rv) + clib_warning ("failed to %s remote mapping!", is_add ? "add" : "delete"); + +done: + vec_free (rlocs); + unformat_free (line_input); + return error; +} + +VLIB_CLI_COMMAND (lisp_add_del_remote_mapping_command) = +{ +.path = "lisp remote-mapping",.short_help = + "lisp remote-mapping add|del [del-all] vni " + "eid [action ] rloc p w " + "[rloc ... ]",.function = + lisp_add_del_remote_mapping_command_fn,}; + +/** + * Handler for add/del adjacency CLI. + */ +static clib_error_t * +lisp_add_del_adjacency_command_fn (vlib_main_t * vm, unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + clib_error_t *error = 0; + unformat_input_t _line_input, *line_input = &_line_input; + vnet_lisp_add_del_adjacency_args_t _a, *a = &_a; + u8 is_add = 1; + ip_prefix_t *reid_ippref, *leid_ippref; + gid_address_t leid, reid; + u8 *dmac = gid_address_mac (&reid); + u8 *smac = gid_address_mac (&leid); + u8 reid_set = 0, leid_set = 0; + u32 vni; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + memset (&reid, 0, sizeof (reid)); + memset (&leid, 0, sizeof (leid)); + + leid_ippref = &gid_address_ippref (&leid); + reid_ippref = &gid_address_ippref (&reid); + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "del")) + is_add = 0; + else if (unformat (line_input, "add")) + ; + else if (unformat (line_input, "reid %U", + unformat_ip_prefix, reid_ippref)) + { + gid_address_type (&reid) = GID_ADDR_IP_PREFIX; + reid_set = 1; + } + else if (unformat (line_input, "reid %U", unformat_mac_address, dmac)) + { + gid_address_type (&reid) = GID_ADDR_MAC; + reid_set = 1; + } + else if (unformat (line_input, "vni %u", &vni)) + { + gid_address_vni (&leid) = vni; + gid_address_vni (&reid) = vni; + } + else if (unformat (line_input, "leid %U", + unformat_ip_prefix, leid_ippref)) + { + gid_address_type (&leid) = GID_ADDR_IP_PREFIX; + leid_set = 1; + } + else if (unformat (line_input, "leid %U", unformat_mac_address, smac)) + { + gid_address_type (&leid) = GID_ADDR_MAC; + leid_set = 1; + } + else + { + clib_warning ("parse error"); + goto done; + } + } + + if (!reid_set || !leid_set) + { + clib_warning ("missing remote or local eid!"); + goto done; + } + + if ((gid_address_type (&leid) != gid_address_type (&reid)) + || (gid_address_type (&reid) == GID_ADDR_IP_PREFIX + && ip_prefix_version (reid_ippref) + != ip_prefix_version (leid_ippref))) + { + clib_warning ("remote and local EIDs are of different types!"); + return error; + } + + memset (a, 0, sizeof (a[0])); + gid_address_copy (&a->leid, &leid); + gid_address_copy (&a->reid, &reid); + a->is_add = is_add; + + if (vnet_lisp_add_del_adjacency (a)) + clib_warning ("failed to %s adjacency!", is_add ? "add" : "delete"); + +done: + unformat_free (line_input); + return error; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_add_del_adjacency_command) = { + .path = "lisp adjacency", + .short_help = "lisp adjacency add|del vni reid " + "leid ", + .function = lisp_add_del_adjacency_command_fn, +}; +/* *INDENT-ON* */ + + +static clib_error_t * +lisp_map_request_mode_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _i, *i = &_i; + map_request_mode_t mr_mode = _MR_MODE_MAX; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, i)) + return 0; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "dst-only")) + mr_mode = MR_MODE_DST_ONLY; + else if (unformat (i, "src-dst")) + mr_mode = MR_MODE_SRC_DST; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + goto done; + } + } + + if (_MR_MODE_MAX == mr_mode) + { + clib_warning ("No LISP map request mode entered!"); + return 0; + } + + vnet_lisp_set_map_request_mode (mr_mode); +done: + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_map_request_mode_command) = { + .path = "lisp map-request mode", + .short_help = "lisp map-request mode dst-only|src-dst", + .function = lisp_map_request_mode_command_fn, +}; +/* *INDENT-ON* */ + + +static u8 * +format_lisp_map_request_mode (u8 * s, va_list * args) +{ + u32 mode = va_arg (*args, u32); + + switch (mode) + { + case 0: + return format (0, "dst-only"); + case 1: + return format (0, "src-dst"); + } + return 0; +} + +static clib_error_t * +lisp_show_map_request_mode_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + vlib_cli_output (vm, "map-request mode: %U", format_lisp_map_request_mode, + vnet_lisp_get_map_request_mode ()); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_show_map_request_mode_command) = { + .path = "show lisp map-request mode", + .short_help = "show lisp map-request mode", + .function = lisp_show_map_request_mode_command_fn, +}; +/* *INDENT-ON* */ + +static clib_error_t * +lisp_show_map_resolvers_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + lisp_msmr_t *mr; + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + + vec_foreach (mr, lcm->map_resolvers) + { + vlib_cli_output (vm, "%U", format_ip_address, &mr->address); + } + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_show_map_resolvers_command) = { + .path = "show lisp map-resolvers", + .short_help = "show lisp map-resolvers", + .function = lisp_show_map_resolvers_command_fn, +}; +/* *INDENT-ON* */ + + +static clib_error_t * +lisp_pitr_set_locator_set_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + u8 locator_name_set = 0; + u8 *locator_set_name = 0; + u8 is_add = 1; + unformat_input_t _line_input, *line_input = &_line_input; + clib_error_t *error = 0; + int rv = 0; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "ls %_%v%_", &locator_set_name)) + locator_name_set = 1; + else if (unformat (line_input, "disable")) + is_add = 0; + else + return clib_error_return (0, "parse error"); + } + + if (!locator_name_set) + { + clib_warning ("No locator set specified!"); + goto done; + } + rv = vnet_lisp_pitr_set_locator_set (locator_set_name, is_add); + if (0 != rv) + { + error = clib_error_return (0, "failed to %s pitr!", + is_add ? "add" : "delete"); + } + +done: + if (locator_set_name) + vec_free (locator_set_name); + return error; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_pitr_set_locator_set_command) = { + .path = "lisp pitr", + .short_help = "lisp pitr [disable] ls ", + .function = lisp_pitr_set_locator_set_command_fn, +}; +/* *INDENT-ON* */ + +static clib_error_t * +lisp_show_pitr_command_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + mapping_t *m; + locator_set_t *ls; + u8 *tmp_str = 0; + + vlib_cli_output (vm, "%=20s%=16s", + "pitr", lcm->lisp_pitr ? "locator-set" : ""); + + if (!lcm->lisp_pitr) + { + vlib_cli_output (vm, "%=20s", "disable"); + return 0; + } + + if (~0 == lcm->pitr_map_index) + { + tmp_str = format (0, "N/A"); + } + else + { + m = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index); + if (~0 != m->locator_set_index) + { + ls = + pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index); + tmp_str = format (0, "%s", ls->name); + } + else + { + tmp_str = format (0, "N/A"); + } + } + vec_add1 (tmp_str, 0); + + vlib_cli_output (vm, "%=20s%=16s", "enable", tmp_str); + + vec_free (tmp_str); + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_show_pitr_command) = { + .path = "show lisp pitr", + .short_help = "Show pitr", + .function = lisp_show_pitr_command_fn, +}; +/* *INDENT-ON* */ + +static u8 * +format_eid_entry (u8 * s, va_list * args) +{ + vnet_main_t *vnm = va_arg (*args, vnet_main_t *); + lisp_cp_main_t *lcm = va_arg (*args, lisp_cp_main_t *); + mapping_t *mapit = va_arg (*args, mapping_t *); + locator_set_t *ls = va_arg (*args, locator_set_t *); + gid_address_t *gid = &mapit->eid; + u32 ttl = mapit->ttl; + u8 aut = mapit->authoritative; + u32 *loc_index; + u8 first_line = 1; + u8 *loc; + + u8 *type = ls->local ? format (0, "local(%s)", ls->name) + : format (0, "remote"); + + if (vec_len (ls->locator_indices) == 0) + { + s = format (s, "%-35U%-30s%-20u%-u", format_gid_address, gid, + type, ttl, aut); + } + else + { + vec_foreach (loc_index, ls->locator_indices) + { + locator_t *l = pool_elt_at_index (lcm->locator_pool, loc_index[0]); + if (l->local) + loc = format (0, "%U", format_vnet_sw_if_index_name, vnm, + l->sw_if_index); + else + loc = format (0, "%U", format_ip_address, + &gid_address_ip (&l->address)); + + if (first_line) + { + s = format (s, "%-35U%-20s%-30v%-20u%-u\n", format_gid_address, + gid, type, loc, ttl, aut); + first_line = 0; + } + else + s = format (s, "%55s%v\n", "", loc); + } + } + return s; +} + +static clib_error_t * +lisp_show_eid_table_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + mapping_t *mapit; + unformat_input_t _line_input, *line_input = &_line_input; + u32 mi; + gid_address_t eid; + u8 print_all = 1; + u8 filter = 0; + + memset (&eid, 0, sizeof (eid)); + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "eid %U", unformat_gid_address, &eid)) + print_all = 0; + else if (unformat (line_input, "local")) + filter = 1; + else if (unformat (line_input, "remote")) + filter = 2; + else + return clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + } + + vlib_cli_output (vm, "%-35s%-20s%-30s%-20s%-s", + "EID", "type", "locators", "ttl", "autoritative"); + + if (print_all) + { + /* *INDENT-OFF* */ + pool_foreach (mapit, lcm->mapping_pool, + ({ + locator_set_t * ls = pool_elt_at_index (lcm->locator_set_pool, + mapit->locator_set_index); + if (filter && !((1 == filter && ls->local) || + (2 == filter && !ls->local))) + { + continue; + } + vlib_cli_output (vm, "%U", format_eid_entry, lcm->vnet_main, + lcm, mapit, ls); + })); + /* *INDENT-ON* */ + } + else + { + mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &eid); + if ((u32) ~ 0 == mi) + return 0; + + mapit = pool_elt_at_index (lcm->mapping_pool, mi); + locator_set_t *ls = pool_elt_at_index (lcm->locator_set_pool, + mapit->locator_set_index); + + if (filter && !((1 == filter && ls->local) || + (2 == filter && !ls->local))) + { + return 0; + } + + vlib_cli_output (vm, "%U,", format_eid_entry, lcm->vnet_main, + lcm, mapit, ls); + } + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_cp_show_eid_table_command) = { + .path = "show lisp eid-table", + .short_help = "Shows EID table", + .function = lisp_show_eid_table_command_fn, +}; +/* *INDENT-ON* */ + + +static clib_error_t * +lisp_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + u8 is_enabled = 0; + u8 is_set = 0; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "enable")) + { + is_set = 1; + is_enabled = 1; + } + else if (unformat (line_input, "disable")) + is_set = 1; + else + { + return clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + } + } + + if (!is_set) + return clib_error_return (0, "state not set"); + + vnet_lisp_enable_disable (is_enabled); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_cp_enable_disable_command) = { + .path = "lisp", + .short_help = "lisp [enable|disable]", + .function = lisp_enable_disable_command_fn, +}; +/* *INDENT-ON* */ + +static clib_error_t * +lisp_map_register_enable_disable_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + u8 is_enabled = 0; + u8 is_set = 0; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "enable")) + { + is_set = 1; + is_enabled = 1; + } + else if (unformat (line_input, "disable")) + is_set = 1; + else + { + vlib_cli_output (vm, "parse error: '%U'", format_unformat_error, + line_input); + return 0; + } + } + + if (!is_set) + { + vlib_cli_output (vm, "state not set!"); + return 0; + } + + vnet_lisp_map_register_enable_disable (is_enabled); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_map_register_enable_disable_command) = { + .path = "lisp map-register", + .short_help = "lisp map-register [enable|disable]", + .function = lisp_map_register_enable_disable_command_fn, +}; +/* *INDENT-ON* */ + +static clib_error_t * +lisp_rloc_probe_enable_disable_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + u8 is_enabled = 0; + u8 is_set = 0; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "enable")) + { + is_set = 1; + is_enabled = 1; + } + else if (unformat (line_input, "disable")) + is_set = 1; + else + { + vlib_cli_output (vm, "parse error: '%U'", format_unformat_error, + line_input); + return 0; + } + } + + if (!is_set) + { + vlib_cli_output (vm, "state not set!"); + return 0; + } + + vnet_lisp_rloc_probe_enable_disable (is_enabled); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_rloc_probe_enable_disable_command) = { + .path = "lisp rloc-probe", + .short_help = "lisp rloc-probe [enable|disable]", + .function = lisp_rloc_probe_enable_disable_command_fn, +}; +/* *INDENT-ON* */ + +static u8 * +format_lisp_status (u8 * s, va_list * args) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + return format (s, "%s", lcm->is_enabled ? "enabled" : "disabled"); +} + +static clib_error_t * +lisp_show_status_command_fn (vlib_main_t * vm, unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + u8 *msg = 0; + msg = format (msg, "feature: %U\ngpe: %U\n", + format_lisp_status, format_vnet_lisp_gpe_status); + vlib_cli_output (vm, "%v", msg); + vec_free (msg); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_show_status_command) = { + .path = "show lisp status", + .short_help = "show lisp status", + .function = lisp_show_status_command_fn, +}; +/* *INDENT-ON* */ + +static clib_error_t * +lisp_show_eid_table_map_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + hash_pair_t *p; + unformat_input_t _line_input, *line_input = &_line_input; + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + uword *vni_table = 0; + u8 is_l2 = 0; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "l2")) + { + vni_table = lcm->bd_id_by_vni; + is_l2 = 1; + } + else if (unformat (line_input, "l3")) + { + vni_table = lcm->table_id_by_vni; + is_l2 = 0; + } + else + return clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + } + + if (!vni_table) + { + vlib_cli_output (vm, "Error: expected l2|l3 param!\n"); + return 0; + } + + vlib_cli_output (vm, "%=10s%=10s", "VNI", is_l2 ? "BD" : "VRF"); + + /* *INDENT-OFF* */ + hash_foreach_pair (p, vni_table, + ({ + vlib_cli_output (vm, "%=10d%=10d", p->key, p->value[0]); + })); + /* *INDENT-ON* */ + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_show_eid_table_map_command) = { + .path = "show lisp eid-table map", + .short_help = "show lisp eid-table l2|l3", + .function = lisp_show_eid_table_map_command_fn, +}; +/* *INDENT-ON* */ + + +static clib_error_t * +lisp_add_del_locator_set_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + lisp_gpe_main_t *lgm = &lisp_gpe_main; + vnet_main_t *vnm = lgm->vnet_main; + unformat_input_t _line_input, *line_input = &_line_input; + u8 is_add = 1; + clib_error_t *error = 0; + u8 *locator_set_name = 0; + locator_t locator, *locators = 0; + vnet_lisp_add_del_locator_set_args_t _a, *a = &_a; + u32 ls_index = 0; + int rv = 0; + + memset (&locator, 0, sizeof (locator)); + memset (a, 0, sizeof (a[0])); + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "add %_%v%_", &locator_set_name)) + is_add = 1; + else if (unformat (line_input, "del %_%v%_", &locator_set_name)) + is_add = 0; + else if (unformat (line_input, "iface %U p %d w %d", + unformat_vnet_sw_interface, vnm, + &locator.sw_if_index, &locator.priority, + &locator.weight)) + { + locator.local = 1; + vec_add1 (locators, locator); + } + else + { + error = unformat_parse_error (line_input); + goto done; + } + } + + a->name = locator_set_name; + a->locators = locators; + a->is_add = is_add; + a->local = 1; + + rv = vnet_lisp_add_del_locator_set (a, &ls_index); + if (0 != rv) + { + error = clib_error_return (0, "failed to %s locator-set!", + is_add ? "add" : "delete"); + } + +done: + vec_free (locators); + if (locator_set_name) + vec_free (locator_set_name); + return error; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_cp_add_del_locator_set_command) = { + .path = "lisp locator-set", + .short_help = "lisp locator-set add/del [iface " + "p w ]", + .function = lisp_add_del_locator_set_command_fn, +}; +/* *INDENT-ON* */ + +static clib_error_t * +lisp_add_del_locator_in_set_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + lisp_gpe_main_t *lgm = &lisp_gpe_main; + vnet_main_t *vnm = lgm->vnet_main; + unformat_input_t _line_input, *line_input = &_line_input; + u8 is_add = 1; + clib_error_t *error = 0; + u8 *locator_set_name = 0; + u8 locator_set_name_set = 0; + locator_t locator, *locators = 0; + vnet_lisp_add_del_locator_set_args_t _a, *a = &_a; + u32 ls_index = 0; + + memset (&locator, 0, sizeof (locator)); + memset (a, 0, sizeof (a[0])); + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "add")) + is_add = 1; + else if (unformat (line_input, "del")) + is_add = 0; + else if (unformat (line_input, "locator-set %_%v%_", &locator_set_name)) + locator_set_name_set = 1; + else if (unformat (line_input, "iface %U p %d w %d", + unformat_vnet_sw_interface, vnm, + &locator.sw_if_index, &locator.priority, + &locator.weight)) + { + locator.local = 1; + vec_add1 (locators, locator); + } + else + { + error = unformat_parse_error (line_input); + goto done; + } + } + + if (!locator_set_name_set) + { + error = clib_error_return (0, "locator_set name not set!"); + goto done; + } + + a->name = locator_set_name; + a->locators = locators; + a->is_add = is_add; + a->local = 1; + + vnet_lisp_add_del_locator (a, 0, &ls_index); + +done: + vec_free (locators); + vec_free (locator_set_name); + return error; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_cp_add_del_locator_in_set_command) = { + .path = "lisp locator", + .short_help = "lisp locator add/del locator-set iface " + "p w ", + .function = lisp_add_del_locator_in_set_command_fn, +}; +/* *INDENT-ON* */ + +static clib_error_t * +lisp_cp_show_locator_sets_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + locator_set_t *lsit; + locator_t *loc; + u32 *locit; + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + + vlib_cli_output (vm, "%s%=16s%=16s%=16s", "Locator-set", "Locator", + "Priority", "Weight"); + + /* *INDENT-OFF* */ + pool_foreach (lsit, lcm->locator_set_pool, + ({ + u8 * msg = 0; + int next_line = 0; + if (lsit->local) + { + msg = format (msg, "%v", lsit->name); + } + else + { + msg = format (msg, "<%s-%d>", "remote", lsit - lcm->locator_set_pool); + } + vec_foreach (locit, lsit->locator_indices) + { + if (next_line) + { + msg = format (msg, "%16s", " "); + } + loc = pool_elt_at_index (lcm->locator_pool, locit[0]); + if (loc->local) + msg = format (msg, "%16d%16d%16d\n", loc->sw_if_index, loc->priority, + loc->weight); + else + msg = format (msg, "%16U%16d%16d\n", format_ip_address, + &gid_address_ip(&loc->address), loc->priority, + loc->weight); + next_line = 1; + } + vlib_cli_output (vm, "%v", msg); + vec_free (msg); + })); + /* *INDENT-ON* */ + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_cp_show_locator_sets_command) = { + .path = "show lisp locator-set", + .short_help = "Shows locator-sets", + .function = lisp_cp_show_locator_sets_command_fn, +}; +/* *INDENT-ON* */ + + +static clib_error_t * +lisp_add_del_map_resolver_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + u8 is_add = 1, addr_set = 0; + ip_address_t ip_addr; + clib_error_t *error = 0; + int rv = 0; + vnet_lisp_add_del_map_resolver_args_t _a, *a = &_a; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "add")) + is_add = 1; + else if (unformat (line_input, "del")) + is_add = 0; + else if (unformat (line_input, "%U", unformat_ip_address, &ip_addr)) + addr_set = 1; + else + { + error = unformat_parse_error (line_input); + goto done; + } + } + + if (!addr_set) + { + error = clib_error_return (0, "Map-resolver address must be set!"); + goto done; + } + + a->is_add = is_add; + a->address = ip_addr; + rv = vnet_lisp_add_del_map_resolver (a); + if (0 != rv) + { + error = clib_error_return (0, "failed to %s map-resolver!", + is_add ? "add" : "delete"); + } + +done: + return error; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_add_del_map_resolver_command) = { + .path = "lisp map-resolver", + .short_help = "lisp map-resolver add/del ", + .function = lisp_add_del_map_resolver_command_fn, +}; +/* *INDENT-ON* */ + + +static clib_error_t * +lisp_add_del_mreq_itr_rlocs_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + u8 is_add = 1; + u8 *locator_set_name = 0; + clib_error_t *error = 0; + int rv = 0; + vnet_lisp_add_del_mreq_itr_rloc_args_t _a, *a = &_a; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "del")) + is_add = 0; + else if (unformat (line_input, "add %_%v%_", &locator_set_name)) + is_add = 1; + else + { + error = unformat_parse_error (line_input); + goto done; + } + } + + a->is_add = is_add; + a->locator_set_name = locator_set_name; + rv = vnet_lisp_add_del_mreq_itr_rlocs (a); + if (0 != rv) + { + error = clib_error_return (0, "failed to %s map-request itr-rlocs!", + is_add ? "add" : "delete"); + } + + vec_free (locator_set_name); + +done: + return error; + +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_add_del_map_request_command) = { + .path = "lisp map-request itr-rlocs", + .short_help = "lisp map-request itr-rlocs add/del ", + .function = lisp_add_del_mreq_itr_rlocs_command_fn, +}; +/* *INDENT-ON* */ + +static clib_error_t * +lisp_show_mreq_itr_rlocs_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + locator_set_t *loc_set; + + vlib_cli_output (vm, "%=20s", "itr-rlocs"); + + if (~0 == lcm->mreq_itr_rlocs) + { + return 0; + } + + loc_set = pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs); + + vlib_cli_output (vm, "%=20s", loc_set->name); + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_show_map_request_command) = { + .path = "show lisp map-request itr-rlocs", + .short_help = "Shows map-request itr-rlocs", + .function = lisp_show_mreq_itr_rlocs_command_fn, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ -- cgit 1.2.3-korg From ba888e46f799a1ae209c51fffdd6159d75b20cdd Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Tue, 24 Jan 2017 11:38:18 -0800 Subject: Add option to use LISP Proxy-ETR When enabled, destinations with negative mappings or those not reachable via underlay have their traffic forwarded to the PETR. Change-Id: I1056b0959736144f27fcca7b79263f921e7a8bd9 Signed-off-by: Florin Coras --- src/vnet/lisp-cp/control.c | 153 +++++++++++++++++++++++++++++++++----------- src/vnet/lisp-cp/control.h | 31 ++++++++- src/vnet/lisp-cp/lisp.api | 51 +++++++++++++++ src/vnet/lisp-cp/lisp_api.c | 49 ++++++++++++++ src/vnet/lisp-cp/lisp_cli.c | 102 +++++++++++++++++++++++++++++ 5 files changed, 349 insertions(+), 37 deletions(-) (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index 043d60fc..c3406d8c 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -432,11 +432,13 @@ static void dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index) { vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a; - mapping_t *src_map, *dst_map; + gid_address_t *rmt_eid, *lcl_eid; + mapping_t *lcl_map, *rmt_map; u32 sw_if_index; uword *feip = 0, *dpid; fwd_entry_t *fe; u8 type, is_src_dst = 0; + int rv; memset (a, 0, sizeof (*a)); @@ -445,33 +447,44 @@ dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index) if (feip) dp_del_fwd_entry (lcm, src_map_index, dst_map_index); + /* + * Determine local mapping and eid + */ if (lcm->lisp_pitr) - src_map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index); + lcl_map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index); else - src_map = pool_elt_at_index (lcm->mapping_pool, src_map_index); - dst_map = pool_elt_at_index (lcm->mapping_pool, dst_map_index); - - /* insert data plane forwarding entry */ + lcl_map = pool_elt_at_index (lcm->mapping_pool, src_map_index); + lcl_eid = &lcl_map->eid; + + /* + * Determine remote mapping and eid + */ + rmt_map = pool_elt_at_index (lcm->mapping_pool, dst_map_index); + rmt_eid = &rmt_map->eid; + + /* + * Build and insert data plane forwarding entry + */ a->is_add = 1; if (MR_MODE_SRC_DST == lcm->map_request_mode) { - if (GID_ADDR_SRC_DST == gid_address_type (&dst_map->eid)) + if (GID_ADDR_SRC_DST == gid_address_type (rmt_eid)) { - gid_address_sd_to_flat (&a->rmt_eid, &dst_map->eid, - &gid_address_sd_dst (&dst_map->eid)); - gid_address_sd_to_flat (&a->lcl_eid, &dst_map->eid, - &gid_address_sd_src (&dst_map->eid)); + gid_address_sd_to_flat (&a->rmt_eid, rmt_eid, + &gid_address_sd_dst (rmt_eid)); + gid_address_sd_to_flat (&a->lcl_eid, rmt_eid, + &gid_address_sd_src (rmt_eid)); } else { - gid_address_copy (&a->rmt_eid, &dst_map->eid); - gid_address_copy (&a->lcl_eid, &src_map->eid); + gid_address_copy (&a->rmt_eid, rmt_eid); + gid_address_copy (&a->lcl_eid, lcl_eid); } is_src_dst = 1; } else - gid_address_copy (&a->rmt_eid, &dst_map->eid); + gid_address_copy (&a->rmt_eid, rmt_eid); a->vni = gid_address_vni (&a->rmt_eid); @@ -499,17 +512,22 @@ dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index) } /* find best locator pair that 1) verifies LISP policy 2) are connected */ - if (0 == get_locator_pairs (lcm, src_map, dst_map, &a->locator_pairs)) + rv = get_locator_pairs (lcm, lcl_map, rmt_map, &a->locator_pairs); + + /* Either rmt mapping is negative or we can't find underlay path. + * Try again with petr if configured */ + if (rv == 0 && (lcm->flags & LISP_FLAG_USE_PETR)) { - /* negative entry */ - a->is_negative = 1; - a->action = dst_map->action; + rmt_map = lisp_get_petr_mapping (lcm); + rv = get_locator_pairs (lcm, lcl_map, rmt_map, &a->locator_pairs); } - /* TODO remove */ - u8 ipver = ip_prefix_version (&gid_address_ippref (&a->rmt_eid)); - a->decap_next_index = (ipver == IP4) ? - LISP_GPE_INPUT_NEXT_IP4_INPUT : LISP_GPE_INPUT_NEXT_IP6_INPUT; + /* negative entry */ + if (rv == 0) + { + a->is_negative = 1; + a->action = rmt_map->action; + } vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index); @@ -521,7 +539,7 @@ dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index) if (is_src_dst) gid_address_copy (&fe->leid, &a->lcl_eid); else - gid_address_copy (&fe->leid, &src_map->eid); + gid_address_copy (&fe->leid, lcl_eid); fe->is_src_dst = is_src_dst; hash_set (lcm->fwd_entry_by_mapping_index, dst_map_index, @@ -1191,7 +1209,6 @@ vnet_lisp_add_del_adjacency (vnet_lisp_add_del_adjacency_args_t * a) local_mi = lcm->lisp_pitr ? lcm->pitr_map_index : gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->leid); - if (GID_LOOKUP_MISS == local_mi) { clib_warning ("Local eid %U not found. Cannot add adjacency!", @@ -1273,6 +1290,69 @@ vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add) return 0; } +/** + * Configure Proxy-ETR + * + * @param ip PETR's IP address + * @param is_add Flag that indicates if this is an addition or removal + * + * return 0 on success + */ +int +vnet_lisp_use_petr (ip_address_t * ip, u8 is_add) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + u32 ls_index = ~0; + mapping_t *m; + vnet_lisp_add_del_locator_set_args_t _ls_args, *ls_args = &_ls_args; + locator_t loc; + + if (vnet_lisp_enable_disable_status () == 0) + { + clib_warning ("LISP is disabled!"); + return VNET_API_ERROR_LISP_DISABLED; + } + + memset (ls_args, 0, sizeof (*ls_args)); + + if (is_add) + { + /* Create dummy petr locator-set */ + gid_address_from_ip (&loc.address, ip); + loc.priority = 1; + loc.state = loc.weight = 1; + + ls_args->is_add = 1; + ls_args->index = ~0; + vec_add1 (ls_args->locators, loc); + vnet_lisp_add_del_locator_set (ls_args, &ls_index); + + /* Add petr mapping */ + pool_get (lcm->mapping_pool, m); + m->locator_set_index = ls_index; + lcm->petr_map_index = m - lcm->mapping_pool; + + /* Enable use-petr */ + lcm->flags |= LISP_FLAG_USE_PETR; + } + else + { + m = pool_elt_at_index (lcm->mapping_pool, lcm->petr_map_index); + + /* Remove petr locator */ + ls_args->is_add = 0; + ls_args->index = m->locator_set_index; + vnet_lisp_add_del_locator_set (ls_args, 0); + + /* Remove petr mapping */ + pool_put_index (lcm->mapping_pool, lcm->petr_map_index); + + /* Disable use-petr */ + lcm->flags &= ~LISP_FLAG_USE_PETR; + } + return 0; +} + /* cleans locator to locator-set data and removes locators not part of * any locator-set */ static void @@ -2883,21 +2963,21 @@ process_map_reply (map_records_arg_t * a) m->authoritative, m->ttl, 1, 0 /* is_static */ , &dst_map_index); + if (dst_map_index == (u32) ~ 0) + continue; + /* try to program forwarding only if mapping saved or updated */ - if ((u32) ~ 0 != dst_map_index) - { - vnet_lisp_add_del_adjacency_args_t _adj_args, *adj_args = &_adj_args; - memset (adj_args, 0, sizeof (adj_args[0])); + vnet_lisp_add_del_adjacency_args_t _adj_args, *adj_args = &_adj_args; + memset (adj_args, 0, sizeof (adj_args[0])); - gid_address_copy (&adj_args->leid, &pmr->src); - gid_address_copy (&adj_args->reid, &m->eid); - adj_args->is_add = 1; - if (vnet_lisp_add_del_adjacency (adj_args)) - clib_warning ("failed to add adjacency!"); + gid_address_copy (&adj_args->leid, &pmr->src); + gid_address_copy (&adj_args->reid, &m->eid); + adj_args->is_add = 1; + if (vnet_lisp_add_del_adjacency (adj_args)) + clib_warning ("failed to add adjacency!"); - if ((u32) ~ 0 != m->ttl) - mapping_start_expiration_timer (lcm, dst_map_index, m->ttl * 60); - } + if ((u32) ~ 0 != m->ttl) + mapping_start_expiration_timer (lcm, dst_map_index, m->ttl * 60); } /* remove pending map request entry */ @@ -3442,6 +3522,7 @@ lisp_cp_init (vlib_main_t * vm) lcm->vnet_main = vnet_get_main (); lcm->mreq_itr_rlocs = ~0; lcm->lisp_pitr = 0; + lcm->flags = 0; memset (&lcm->active_map_resolver, 0, sizeof (lcm->active_map_resolver)); gid_dictionary_init (&lcm->mapping_index_by_gid); diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index aa76a424..14f3baec 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -94,8 +94,27 @@ typedef enum _MR_MODE_MAX } map_request_mode_t; +#define foreach_lisp_flag_bit \ + _(USE_PETR, "Use Proxy-ETR") + +typedef enum lisp_flag_bits +{ +#define _(sym, str) LISP_FLAG_BIT_##sym, + foreach_lisp_flag_bit +#undef _ +} lisp_flag_bits_e; + +typedef enum lisp_flags +{ +#define _(sym, str) LISP_FLAG_##sym = 1 << LISP_FLAG_BIT_##sym, + foreach_lisp_flag_bit +#undef _ +} lisp_flags_e; + typedef struct { + u32 flags; + /* LISP feature status */ u8 is_enabled; @@ -170,9 +189,12 @@ typedef struct /* track l2 and l3 interfaces that have been created for vni */ uword *l2_dp_intf_by_vni; - /* Proxy ETR map index */ + /* Proxy ITR map index */ u32 pitr_map_index; + /** Proxy ETR map index */ + u32 petr_map_index; + /* LISP PITR mode */ u8 lisp_pitr; @@ -280,6 +302,7 @@ clib_error_t *vnet_lisp_enable_disable (u8 is_enabled); u8 vnet_lisp_enable_disable_status (void); int vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add); +int vnet_lisp_use_petr (ip_address_t * ip, u8 is_add); typedef struct { @@ -303,6 +326,12 @@ int vnet_lisp_map_register_enable_disable (u8 is_enable); u8 vnet_lisp_map_register_state_get (void); u8 vnet_lisp_rloc_probe_state_get (void); +always_inline mapping_t * +lisp_get_petr_mapping (lisp_cp_main_t * lcm) +{ + return pool_elt_at_index (lcm->mapping_pool, lcm->petr_map_index); +} + #endif /* VNET_CONTROL_H_ */ /* diff --git a/src/vnet/lisp-cp/lisp.api b/src/vnet/lisp-cp/lisp.api index 20c17aa3..f0feafee 100644 --- a/src/vnet/lisp-cp/lisp.api +++ b/src/vnet/lisp-cp/lisp.api @@ -220,6 +220,57 @@ define lisp_pitr_set_locator_set_reply i32 retval; }; +/** \brief configure or disable use of PETR + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param is_ip4 - Address is IPv4 if set and IPv6 otherwise + @param address - PETR IP address + @param is_add - add locator set if non-zero, else disable pitr +*/ +define lisp_use_petr +{ + u32 client_index; + u32 context; + u8 is_ip4; + u8 address[16]; + u8 is_add; +}; + +/** \brief Reply for lisp_pitr_set_locator_set + @param context - returned sender context, to match reply w/ request + @param retval - return code +*/ +define lisp_use_petr_reply +{ + u32 context; + i32 retval; +}; + +/** \brief Request for LISP PETR status + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ +define show_lisp_use_petr +{ + u32 client_index; + u32 context; +}; + +/** \brief LISP PETR status, enable or disable + @param context - sender context, to match reply w/ request + @param status - LISP PETR enable if non-zero, else disable + @param is_ip4 - Address is IPv4 if non-zero, else IPv6 + @param address - PETR IP address +*/ +define show_lisp_use_petr_reply +{ + u32 context; + i32 retval; + u8 status; + u8 is_ip4; + u8 address[16]; +}; + /** \brief Get state of LISP RLOC probing @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request diff --git a/src/vnet/lisp-cp/lisp_api.c b/src/vnet/lisp-cp/lisp_api.c index d3fc4627..6e07a5c7 100644 --- a/src/vnet/lisp-cp/lisp_api.c +++ b/src/vnet/lisp-cp/lisp_api.c @@ -73,6 +73,8 @@ _(LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS, \ _(LISP_GET_MAP_REQUEST_ITR_RLOCS, lisp_get_map_request_itr_rlocs) \ _(SHOW_LISP_PITR, show_lisp_pitr) \ _(SHOW_LISP_MAP_REQUEST_MODE, show_lisp_map_request_mode) \ +_(LISP_USE_PETR, lisp_use_petr) \ +_(SHOW_LISP_USE_PETR, show_lisp_use_petr) \ /** Used for transferring locators via VPP API */ /* *INDENT-OFF* */ @@ -398,6 +400,53 @@ vl_api_lisp_pitr_set_locator_set_t_handler (vl_api_lisp_pitr_set_locator_set_t REPLY_MACRO (VL_API_LISP_PITR_SET_LOCATOR_SET_REPLY); } +static void +vl_api_lisp_use_petr_t_handler (vl_api_lisp_use_petr_t * mp) +{ + vl_api_lisp_use_petr_reply_t *rmp; + int rv = 0; + ip_address_t addr; + + ip_address_set (&addr, &mp->address, mp->is_ip4 ? IP4 : IP6); + rv = vnet_lisp_use_petr (&addr, mp->is_add); + + REPLY_MACRO (VL_API_LISP_USE_PETR_REPLY); +} + +static void +vl_api_show_lisp_use_petr_t_handler (vl_api_show_lisp_use_petr_t * mp) +{ + unix_shared_memory_queue_t *q = NULL; + vl_api_show_lisp_use_petr_reply_t *rmp = NULL; + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + mapping_t *m; + locator_set_t *ls = 0; + int rv = 0; + locator_t *loc; + + q = vl_api_client_index_to_input_queue (mp->client_index); + if (q == 0) + { + return; + } + + rmp->status = lcm->flags & LISP_FLAG_USE_PETR; + if (rmp->status) + { + m = pool_elt_at_index (lcm->mapping_pool, lcm->petr_map_index); + if (~0 != m->locator_set_index) + { + ls = + pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index); + loc = pool_elt_at_index (lcm->locator_pool, ls->locator_indices[0]); + gid_address_put (rmp->address, &loc->address); + rmp->is_ip4 = (gid_address_ip_version (&loc->address) == IP4); + } + } + + REPLY_MACRO (VL_API_SHOW_LISP_USE_PETR_REPLY); +} + static void vl_api_lisp_add_del_map_request_itr_rlocs_t_handler (vl_api_lisp_add_del_map_request_itr_rlocs_t * mp) diff --git a/src/vnet/lisp-cp/lisp_cli.c b/src/vnet/lisp-cp/lisp_cli.c index bb859ff1..15e6acbf 100644 --- a/src/vnet/lisp-cp/lisp_cli.c +++ b/src/vnet/lisp-cp/lisp_cli.c @@ -1414,6 +1414,108 @@ VLIB_CLI_COMMAND (lisp_show_map_request_command) = { }; /* *INDENT-ON* */ +static clib_error_t * +lisp_use_petr_set_locator_set_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + u8 is_add = 1, ip_set = 0; + unformat_input_t _line_input, *line_input = &_line_input; + clib_error_t *error = 0; + ip_address_t ip; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%U", unformat_ip_address, &ip)) + ip_set = 1; + else if (unformat (line_input, "disable")) + is_add = 0; + else + return clib_error_return (0, "parse error"); + } + + if (!ip_set) + { + clib_warning ("No petr IP specified!"); + goto done; + } + + if (vnet_lisp_use_petr (&ip, is_add)) + { + error = clib_error_return (0, "failed to %s petr!", + is_add ? "add" : "delete"); + } + +done: + return error; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_use_petr_set_locator_set_command) = { + .path = "lisp use-petr", + .short_help = "lisp use-petr [disable] ", + .function = lisp_use_petr_set_locator_set_command_fn, +}; + +static clib_error_t * +lisp_show_petr_command_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + mapping_t *m; + locator_set_t *ls; + locator_t *loc; + u8 *tmp_str = 0; + u8 use_petr = lcm->flags & LISP_FLAG_USE_PETR; + vlib_cli_output (vm, "%=20s%=16s", "petr", use_petr ? "ip" : ""); + + if (!use_petr) + { + vlib_cli_output (vm, "%=20s", "disable"); + return 0; + } + + if (~0 == lcm->petr_map_index) + { + tmp_str = format (0, "N/A"); + } + else + { + m = pool_elt_at_index (lcm->mapping_pool, lcm->petr_map_index); + if (~0 != m->locator_set_index) + { + ls = pool_elt_at_index(lcm->locator_set_pool, m->locator_set_index); + loc = pool_elt_at_index (lcm->locator_pool, ls->locator_indices[0]); + tmp_str = format (0, "%U", format_ip_address, &loc->address); + } + else + { + tmp_str = format (0, "N/A"); + } + } + vec_add1 (tmp_str, 0); + + vlib_cli_output (vm, "%=20s%=16s", "enable", tmp_str); + + vec_free (tmp_str); + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lisp_show_petr_command) = { + .path = "show lisp petr", + .short_help = "Show petr", + .function = lisp_show_petr_command_fn, +}; + +/* *INDENT-ON* */ + +/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON * -- cgit 1.2.3-korg From 7eaf0e57415615b56904e0054bf0b856db6f9bc1 Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Wed, 8 Mar 2017 08:46:51 +0100 Subject: LISP: add stats API/CLI Change-Id: I5c5b4d680359cf3635c2d7b0088ea2ba6a428f93 Signed-off-by: Filip Tehlar --- src/vnet/lisp-cp/control.c | 23 +++++++++++++++++++ src/vnet/lisp-cp/control.h | 6 +++++ src/vnet/lisp-cp/one.api | 55 +++++++++++++++++++++++++++++++++++++++++++++ src/vnet/lisp-cp/one_api.c | 35 +++++++++++++++++++++++++++++ src/vnet/lisp-cp/one_cli.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 175 insertions(+) (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index ac11d890..c7853ca7 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -3801,6 +3801,29 @@ send_map_resolver_service (vlib_main_t * vm, return 0; } +vnet_api_error_t +vnet_lisp_stats_enable_disable (u8 enable) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + + if (vnet_lisp_enable_disable_status () == 0) + return VNET_API_ERROR_LISP_DISABLED; + + lcm->stats_enabled = enable; + return 0; +} + +u8 +vnet_lisp_stats_enable_disable_state (void) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + + if (vnet_lisp_enable_disable_status () == 0) + return VNET_API_ERROR_LISP_DISABLED; + + return lcm->stats_enabled; +} + /* *INDENT-OFF* */ VLIB_REGISTER_NODE (lisp_retry_service_node,static) = { .function = send_map_resolver_service, diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index 14f3baec..933b34b6 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -210,6 +210,9 @@ typedef struct /* timing wheel for mappping timeouts */ timing_wheel_t wheel; + /* statistics */ + u8 stats_enabled; + /* commodity */ ip4_main_t *im4; ip6_main_t *im6; @@ -332,6 +335,9 @@ lisp_get_petr_mapping (lisp_cp_main_t * lcm) return pool_elt_at_index (lcm->mapping_pool, lcm->petr_map_index); } +u8 vnet_lisp_stats_enable_disable_state (void); +vnet_api_error_t vnet_lisp_stats_enable_disable (u8 enable); + #endif /* VNET_CONTROL_H_ */ /* diff --git a/src/vnet/lisp-cp/one.api b/src/vnet/lisp-cp/one.api index 14f6d47f..436c8089 100644 --- a/src/vnet/lisp-cp/one.api +++ b/src/vnet/lisp-cp/one.api @@ -877,3 +877,58 @@ define show_one_pitr_reply u8 status; u8 locator_set_name[64]; }; + +define one_stats_dump +{ + u32 client_index; + u32 context; +}; + +define one_stats_details +{ + u32 context; + u32 vni; + u8 eid_type; + u8 deid[16]; + u8 seid[16]; + u8 deid_pref_len; + u8 seid_pref_len; + u8 is_ip4; + u8 rloc[16]; + u8 lloc[16]; + + u32 pkt_count; + u32 bytes; +}; + +define one_stats_enable_disable +{ + u32 client_index; + u32 context; + u8 is_en; +}; + +define one_stats_enable_disable_reply +{ + u32 context; + i32 retval; +}; + +define show_one_stats_enable_disable +{ + u32 client_index; + u32 context; +}; + +define show_one_stats_enable_disable_reply +{ + u32 context; + i32 retval; + u8 is_en; +}; + +/* + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vnet/lisp-cp/one_api.c b/src/vnet/lisp-cp/one_api.c index d0a9309b..ff00bf5b 100644 --- a/src/vnet/lisp-cp/one_api.c +++ b/src/vnet/lisp-cp/one_api.c @@ -90,6 +90,10 @@ _(SHOW_ONE_PITR, show_one_pitr) \ _(SHOW_ONE_MAP_REQUEST_MODE, show_one_map_request_mode) \ _(ONE_USE_PETR, one_use_petr) \ _(SHOW_ONE_USE_PETR, show_one_use_petr) \ +_(SHOW_ONE_STATS_ENABLE_DISABLE, show_one_stats_enable_disable) \ +_(ONE_STATS_ENABLE_DISABLE, one_stats_enable_disable) \ +_(ONE_STATS_DUMP, one_stats_dump) \ + static locator_t * unformat_one_locs (vl_api_one_remote_locator_t * rmt_locs, u32 rloc_num) @@ -1256,6 +1260,37 @@ vl_api_show_one_pitr_t_handler (vl_api_show_one_pitr_t * mp) /* *INDENT-ON* */ } +static void + vl_api_show_one_stats_enable_disable_t_handler + (vl_api_show_one_stats_enable_disable_t * mp) +{ + vl_api_show_one_stats_enable_disable_reply_t *rmp = NULL; + vnet_api_error_t rv = 0; + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_SHOW_ONE_STATS_ENABLE_DISABLE_REPLY, + ({ + rmp->is_en = vnet_lisp_stats_enable_disable_state (); + })); + /* *INDENT-ON* */ +} + +static void + vl_api_one_stats_enable_disable_t_handler + (vl_api_one_stats_enable_disable_t * mp) +{ + vl_api_one_enable_disable_reply_t *rmp = NULL; + + vnet_api_error_t rv = vnet_lisp_stats_enable_disable (mp->is_en); + REPLY_MACRO (VL_API_ONE_ENABLE_DISABLE_REPLY); +} + +static void +vl_api_one_stats_dump_t_handler (vl_api_one_stats_dump_t * mp) +{ + +} + /* * one_api_hookup * Add vpe's API message handlers to the table. diff --git a/src/vnet/lisp-cp/one_cli.c b/src/vnet/lisp-cp/one_cli.c index 05821306..2ceeaf42 100644 --- a/src/vnet/lisp-cp/one_cli.c +++ b/src/vnet/lisp-cp/one_cli.c @@ -1642,6 +1642,62 @@ VLIB_CLI_COMMAND (one_show_rloc_probe_state_command) = { }; /* *INDENT-ON* */ +static clib_error_t * +lisp_show_stats_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + u8 is_enabled = vnet_lisp_stats_enable_disable_state (); + vlib_cli_output (vm, "%s\n", is_enabled ? "enabled" : "disabled"); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (one_show_stats_command) = { + .path = "show one stats", + .short_help = "show ONE statistics", + .function = lisp_show_stats_command_fn, +}; +/* *INDENT-ON* */ + +static clib_error_t * +lisp_stats_enable_disable_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + u8 enable = 0; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "enable")) + enable = 1; + else if (unformat (line_input, "disable")) + enable = 0; + else + { + clib_warning ("Error: expected enable/disable!"); + goto done; + } + } + vnet_lisp_stats_enable_disable (enable); +done: + unformat_free (line_input); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (one_stats_enable_disable_command) = { + .path = "one stats", + .short_help = "enable/disable ONE statistics collecting", + .function = lisp_stats_enable_disable_command_fn, +}; +/* *INDENT-ON* */ + /* * fd.io coding-style-patch-verification: ON * -- cgit 1.2.3-korg From 4868ff65eddfd694a1485d6c6c355f9a8ca9011d Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Thu, 9 Mar 2017 16:48:39 +0100 Subject: LISP statistics Change-Id: I399cac46d279e020ba33459ef759d9d29d3ac716 Signed-off-by: Filip Tehlar --- src/vat/api_format.c | 208 +++++++++++++++++++++++++++++++++ src/vnet/adj/adj_l2.c | 1 + src/vnet/lisp-cp/control.c | 72 ++++++++++-- src/vnet/lisp-cp/control.h | 14 +-- src/vnet/lisp-cp/lisp_types.c | 38 ++++++ src/vnet/lisp-cp/lisp_types.h | 3 + src/vnet/lisp-cp/one_api.c | 67 +++++++++++ src/vnet/lisp-cp/one_cli.c | 61 +++++++++- src/vnet/lisp-gpe/lisp_gpe.c | 2 + src/vnet/lisp-gpe/lisp_gpe.h | 30 +++++ src/vnet/lisp-gpe/lisp_gpe_adjacency.c | 100 ++++++++++++++++ src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c | 86 ++++++++++---- src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h | 3 + 13 files changed, 639 insertions(+), 46 deletions(-) (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/vat/api_format.c b/src/vat/api_format.c index 391fe9cf..d34a97f6 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -2610,6 +2610,92 @@ vl_api_one_eid_table_details_t_handler_json (vl_api_one_eid_table_details_t vec_free (eid); } +static void +vl_api_one_stats_details_t_handler (vl_api_one_stats_details_t * mp) +{ + vat_main_t *vam = &vat_main; + u8 *seid = 0, *deid = 0; + u8 *(*format_ip_address_fcn) (u8 *, va_list *) = 0; + + deid = format (0, "%U", format_lisp_eid_vat, + mp->eid_type, mp->deid, mp->deid_pref_len, 0, 0, 0); + + seid = format (0, "%U", format_lisp_eid_vat, + mp->eid_type, mp->seid, mp->seid_pref_len, 0, 0, 0); + + vec_add1 (deid, 0); + vec_add1 (seid, 0); + + if (mp->is_ip4) + format_ip_address_fcn = format_ip4_address; + else + format_ip_address_fcn = format_ip6_address; + + + print (vam->ofp, "([%d] %s %s) (%U %U) %u %u", + clib_net_to_host_u32 (mp->vni), + seid, deid, + format_ip_address_fcn, mp->lloc, + format_ip_address_fcn, mp->rloc, + clib_net_to_host_u32 (mp->pkt_count), + clib_net_to_host_u32 (mp->bytes)); + + vec_free (deid); + vec_free (seid); +} + +static void +vl_api_one_stats_details_t_handler_json (vl_api_one_stats_details_t * mp) +{ + struct in6_addr ip6; + struct in_addr ip4; + vat_main_t *vam = &vat_main; + vat_json_node_t *node = 0; + u8 *deid = 0, *seid = 0; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + deid = format (0, "%U", format_lisp_eid_vat, + mp->eid_type, mp->deid, mp->deid_pref_len, 0, 0, 0); + + seid = format (0, "%U", format_lisp_eid_vat, + mp->eid_type, mp->seid, mp->seid_pref_len, 0, 0, 0); + + vec_add1 (deid, 0); + vec_add1 (seid, 0); + + vat_json_object_add_string_copy (node, "seid", seid); + vat_json_object_add_string_copy (node, "deid", deid); + vat_json_object_add_uint (node, "vni", clib_net_to_host_u32 (mp->vni)); + + if (mp->is_ip4) + { + clib_memcpy (&ip4, mp->lloc, sizeof (ip4)); + vat_json_object_add_ip4 (node, "lloc", ip4); + clib_memcpy (&ip4, mp->rloc, sizeof (ip4)); + vat_json_object_add_ip4 (node, "rloc", ip4); + } + else + { + clib_memcpy (&ip6, mp->lloc, sizeof (ip6)); + vat_json_object_add_ip6 (node, "lloc", ip6); + clib_memcpy (&ip6, mp->rloc, sizeof (ip6)); + vat_json_object_add_ip6 (node, "rloc", ip6); + } + vat_json_object_add_uint (node, "pkt_count", + clib_net_to_host_u32 (mp->pkt_count)); + vat_json_object_add_uint (node, "bytes", clib_net_to_host_u32 (mp->bytes)); + + vec_free (deid); + vec_free (seid); +} + static void vl_api_one_eid_table_map_details_t_handler (vl_api_one_eid_table_map_details_t * mp) @@ -2740,6 +2826,42 @@ static void vec_free (s); } +static void + vl_api_show_one_stats_enable_disable_reply_t_handler + (vl_api_show_one_stats_enable_disable_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + print (vam->ofp, "%s", mp->is_en ? "enabled" : "disabled"); +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_show_one_stats_enable_disable_reply_t_handler_json + (vl_api_show_one_stats_enable_disable_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t _node, *node = &_node; + int retval = clib_net_to_host_u32 (mp->retval); + + u8 *s = format (0, "%s", mp->is_en ? "enabled" : "disabled"); + vat_json_init_object (node); + vat_json_object_add_string_copy (node, "state", s); + + vat_json_print (vam->ofp, node); + vat_json_free (node); + + vam->retval = retval; + vam->result_ready = 1; + vec_free (s); +} + static void api_gpe_fwd_entry_net_to_host (vl_api_gpe_fwd_entry_t * e) { @@ -4040,6 +4162,7 @@ _(one_map_request_mode_reply) \ _(one_add_del_map_request_itr_rlocs_reply) \ _(one_eid_table_add_del_map_reply) \ _(one_use_petr_reply) \ +_(one_stats_enable_disable_reply) \ _(gpe_add_del_fwd_entry_reply) \ _(gpe_enable_disable_reply) \ _(gpe_set_encap_mode_reply) \ @@ -4263,6 +4386,10 @@ _(ONE_EID_TABLE_VNI_DETAILS, one_eid_table_vni_details) \ _(ONE_MAP_RESOLVER_DETAILS, one_map_resolver_details) \ _(ONE_MAP_SERVER_DETAILS, one_map_server_details) \ _(ONE_ADJACENCIES_GET_REPLY, one_adjacencies_get_reply) \ +_(ONE_STATS_DETAILS, one_stats_details) \ +_(ONE_STATS_ENABLE_DISABLE_REPLY, one_stats_enable_disable_reply) \ +_(SHOW_ONE_STATS_ENABLE_DISABLE_REPLY, \ + show_one_stats_enable_disable_reply) \ _(GPE_SET_ENCAP_MODE_REPLY, gpe_set_encap_mode_reply) \ _(GPE_GET_ENCAP_MODE_REPLY, gpe_get_encap_mode_reply) \ _(GPE_ADD_DEL_IFACE_REPLY, gpe_add_del_iface_reply) \ @@ -14214,6 +14341,64 @@ api_show_one_rloc_probe_state (vat_main_t * vam) #define api_show_lisp_rloc_probe_state api_show_one_rloc_probe_state +static int +api_one_stats_enable_disable (vat_main_t * vam) +{ + vl_api_one_stats_enable_disable_t *mp; + unformat_input_t *input = vam->input; + u8 is_set = 0; + u8 is_en = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "enable")) + { + is_set = 1; + is_en = 1; + } + else if (unformat (input, "disable")) + { + is_set = 1; + } + else + break; + } + + if (!is_set) + { + errmsg ("Value not set"); + return -99; + } + + M (ONE_STATS_ENABLE_DISABLE, mp); + mp->is_en = is_en; + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +static int +api_show_one_stats_enable_disable (vat_main_t * vam) +{ + vl_api_show_one_stats_enable_disable_t *mp; + int ret; + + M (SHOW_ONE_STATS_ENABLE_DISABLE, mp); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + static int api_show_one_map_request_mode (vat_main_t * vam) { @@ -15421,6 +15606,26 @@ api_one_map_resolver_dump (vat_main_t * vam) #define api_lisp_map_resolver_dump api_one_map_resolver_dump +static int +api_one_stats_dump (vat_main_t * vam) +{ + vl_api_one_stats_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + M (ONE_STATS_DUMP, mp); + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + M (CONTROL_PING, mp_ping); + S (mp_ping); + + /* Wait for a reply... */ + W (ret); + return ret; +} + static int api_show_one_status (vat_main_t * vam) { @@ -18389,6 +18594,8 @@ _(one_locator_set_dump, "[local | remote]") \ _(one_locator_dump, "ls_index | ls_name ") \ _(one_eid_table_dump, "[eid / | ] [vni] " \ "[local] | [remote]") \ +_(one_stats_enable_disable, "enable|disalbe") \ +_(show_one_stats_enable_disable, "") \ _(one_eid_table_vni_dump, "") \ _(one_eid_table_map_dump, "l2|l3") \ _(one_map_resolver_dump, "") \ @@ -18397,6 +18604,7 @@ _(one_adjacencies_get, "vni ") \ _(show_one_rloc_probe_state, "") \ _(show_one_map_register_state, "") \ _(show_one_status, "") \ +_(one_stats_dump, "") \ _(one_get_map_request_itr_rlocs, "") \ _(show_one_pitr, "") \ _(show_one_use_petr, "") \ diff --git a/src/vnet/adj/adj_l2.c b/src/vnet/adj/adj_l2.c index 5a083643..fb64e505 100644 --- a/src/vnet/adj/adj_l2.c +++ b/src/vnet/adj/adj_l2.c @@ -93,6 +93,7 @@ adj_l2_rewrite_inline (vlib_main_t * vm, /* Update packet buffer attributes/set output interface. */ rw_len0 = adj0[0].rewrite_header.data_bytes; vnet_buffer(p0)->ip.save_rewrite_length = rw_len0; + vnet_buffer(p0)->sw_if_index[VLIB_TX] = adj0->rewrite_header.sw_if_index; vlib_increment_combined_counter(&adjacency_counters, cpu_index, diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index 5c90c03b..47badeb9 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -284,6 +285,7 @@ dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index) if (fe->is_src_dst) gid_address_copy (&a->lcl_eid, &fe->leid); + vnet_lisp_del_fwd_stats (a, feip[0]); vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index); /* delete entry in fwd table */ @@ -1228,9 +1230,6 @@ vnet_lisp_add_del_adjacency (vnet_lisp_add_del_adjacency_args_t * a) if (a->is_add) { - /* TODO 1) check if src/dst 2) once we have src/dst working, use it in - * delete*/ - /* check if source eid has an associated mapping. If pitr mode is on, * just use the pitr's mapping */ local_mi = lcm->lisp_pitr ? lcm->pitr_map_index : @@ -2654,16 +2653,15 @@ lisp_get_vni_from_buffer_eth (lisp_cp_main_t * lcm, vlib_buffer_t * b) return vni; } -always_inline void +void get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b, - gid_address_t * src, gid_address_t * dst) + gid_address_t * src, gid_address_t * dst, + u16 type) { u32 vni = 0; - u16 type; memset (src, 0, sizeof (*src)); memset (dst, 0, sizeof (*dst)); - type = vnet_buffer (b)->lisp.overlay_afi; if (LISP_AFI_IP == type || LISP_AFI_IP6 == type) { @@ -2742,10 +2740,9 @@ lisp_cp_lookup_inline (vlib_main_t * vm, b0 = vlib_get_buffer (vm, pi0); b0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP]; - vnet_buffer (b0)->lisp.overlay_afi = overlay; /* src/dst eid pair */ - get_src_and_dst_eids_from_buffer (lcm, b0, &src, &dst); + get_src_and_dst_eids_from_buffer (lcm, b0, &src, &dst, overlay); /* if we have remote mapping for destination already in map-chache add forwarding tunnel directly. If not send a map-request */ @@ -3605,6 +3602,55 @@ lisp_cp_init (vlib_main_t * vm) return 0; } +static int +lisp_stats_api_fill (lisp_cp_main_t * lcm, lisp_gpe_main_t * lgm, + lisp_api_stats_t * stat, lisp_stats_key_t * key, + u32 stats_index) +{ + lisp_stats_t *s; + lisp_gpe_fwd_entry_key_t fwd_key; + const lisp_gpe_tunnel_t *lgt; + fwd_entry_t *fe; + + memset (stat, 0, sizeof (*stat)); + memset (&fwd_key, 0, sizeof (fwd_key)); + + fe = pool_elt_at_index (lcm->fwd_entry_pool, key->fwd_entry_index); + ASSERT (fe != 0); + + gid_to_dp_address (&fe->reid, &stat->deid); + gid_to_dp_address (&fe->leid, &stat->seid); + stat->vni = gid_address_vni (&fe->reid); + + lgt = lisp_gpe_tunnel_get (key->tunnel_index); + stat->loc_rloc = lgt->key->lcl; + stat->rmt_rloc = lgt->key->rmt; + + s = pool_elt_at_index (lgm->lisp_stats_pool, stats_index); + stat->stats = *s; + return 1; +} + +lisp_api_stats_t * +vnet_lisp_get_stats (void) +{ + lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + lisp_api_stats_t *stats = 0, stat; + lisp_stats_key_t *key; + u32 index; + + /* *INDENT-OFF* */ + hash_foreach_mem (key, index, lgm->lisp_stats_index_by_key, + { + if (lisp_stats_api_fill (lcm, lgm, &stat, key, index)) + vec_add1 (stats, stat); + }); + /* *INDENT-ON* */ + + return stats; +} + static void * send_map_request_thread_fn (void *arg) { @@ -3810,7 +3856,11 @@ vnet_lisp_stats_enable_disable (u8 enable) if (vnet_lisp_enable_disable_status () == 0) return VNET_API_ERROR_LISP_DISABLED; - lcm->stats_enabled = enable; + if (enable) + lcm->flags |= LISP_FLAG_STATS_ENABLED; + else + lcm->flags &= ~LISP_FLAG_STATS_ENABLED; + return 0; } @@ -3822,7 +3872,7 @@ vnet_lisp_stats_enable_disable_state (void) if (vnet_lisp_enable_disable_status () == 0) return VNET_API_ERROR_LISP_DISABLED; - return lcm->stats_enabled; + return lcm->flags & LISP_FLAG_STATS_ENABLED; } /* *INDENT-OFF* */ diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index 933b34b6..eae8a184 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -95,7 +95,8 @@ typedef enum } map_request_mode_t; #define foreach_lisp_flag_bit \ - _(USE_PETR, "Use Proxy-ETR") + _(USE_PETR, "Use Proxy-ETR") \ + _(STATS_ENABLED, "Statistics enabled") typedef enum lisp_flag_bits { @@ -210,9 +211,6 @@ typedef struct /* timing wheel for mappping timeouts */ timing_wheel_t wheel; - /* statistics */ - u8 stats_enabled; - /* commodity */ ip4_main_t *im4; ip6_main_t *im6; @@ -235,6 +233,11 @@ vnet_lisp_cp_get_main () return &lisp_control_main; } +void +get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b, + gid_address_t * src, gid_address_t * dst, + u16 type); + typedef struct { u8 is_add; @@ -335,9 +338,6 @@ lisp_get_petr_mapping (lisp_cp_main_t * lcm) return pool_elt_at_index (lcm->mapping_pool, lcm->petr_map_index); } -u8 vnet_lisp_stats_enable_disable_state (void); -vnet_api_error_t vnet_lisp_stats_enable_disable (u8 enable); - #endif /* VNET_CONTROL_H_ */ /* diff --git a/src/vnet/lisp-cp/lisp_types.c b/src/vnet/lisp-cp/lisp_types.c index b6466686..ad3a4bdf 100644 --- a/src/vnet/lisp-cp/lisp_types.c +++ b/src/vnet/lisp-cp/lisp_types.c @@ -573,6 +573,44 @@ ip_address_parse (void *offset, u16 iana_afi, ip_address_t * dst) return (sizeof (u16) + size); } +void +gid_to_dp_address (gid_address_t * g, dp_address_t * d) +{ + switch (gid_address_type (g)) + { + case GID_ADDR_SRC_DST: + switch (gid_address_sd_dst_type (g)) + { + case FID_ADDR_IP_PREF: + ip_prefix_copy (&d->ippref, &gid_address_sd_dst_ippref (g)); + d->type = FID_ADDR_IP_PREF; + break; + case FID_ADDR_MAC: + mac_copy (&d->mac, &gid_address_sd_dst_mac (g)); + d->type = FID_ADDR_MAC; + break; + default: + clib_warning ("Source/Dest address type %d not supported!", + gid_address_sd_dst_type (g)); + break; + } + break; + case GID_ADDR_IP_PREFIX: + ip_prefix_copy (&d->ippref, &gid_address_ippref (g)); + d->type = FID_ADDR_IP_PREF; + break; + case GID_ADDR_MAC: + mac_copy (&d->mac, &gid_address_mac (g)); + d->type = FID_ADDR_MAC; + break; + case GID_ADDR_NSH: + default: + d->nsh = gid_address_nsh (g).spi << 8 | gid_address_nsh (g).si; + d->type = FID_ADDR_NSH; + break; + } +} + u32 lcaf_hdr_parse (void *offset, lcaf_t * lcaf) { diff --git a/src/vnet/lisp-cp/lisp_types.h b/src/vnet/lisp-cp/lisp_types.h index 672835bd..a65a479e 100644 --- a/src/vnet/lisp-cp/lisp_types.h +++ b/src/vnet/lisp-cp/lisp_types.h @@ -126,6 +126,8 @@ typedef struct typedef fid_address_t dp_address_t; #define fid_addr_ippref(_a) (_a)->ippref +#define fid_addr_prefix_length(_a) ip_prefix_len(&fid_addr_ippref(_a)) +#define fid_addr_ip_version(_a) ip_prefix_version(&fid_addr_ippref(_a)) #define fid_addr_mac(_a) (_a)->mac #define fid_addr_nsh(_a) (_a)->nsh #define fid_addr_type(_a) (_a)->type @@ -359,6 +361,7 @@ void build_src_dst (gid_address_t * sd, gid_address_t * src, gid_address_t * dst); void gid_address_from_ip (gid_address_t * g, ip_address_t * ip); +void gid_to_dp_address (gid_address_t * g, dp_address_t * d); #endif /* VNET_LISP_GPE_LISP_TYPES_H_ */ diff --git a/src/vnet/lisp-cp/one_api.c b/src/vnet/lisp-cp/one_api.c index 4faf6240..ab9e7a63 100644 --- a/src/vnet/lisp-cp/one_api.c +++ b/src/vnet/lisp-cp/one_api.c @@ -58,6 +58,21 @@ #include +#define REPLY_DETAILS(t, body) \ +do { \ + unix_shared_memory_queue_t * q; \ + rv = vl_msg_api_pd_handler (mp, rv); \ + q = vl_api_client_index_to_input_queue (mp->client_index); \ + if (!q) \ + return; \ + \ + rmp = vl_msg_api_alloc (sizeof (*rmp)); \ + rmp->_vl_msg_id = ntohs((t)); \ + rmp->context = mp->context; \ + do {body;} while (0); \ + vl_msg_api_send_shmem (q, (u8 *)&rmp); \ +} while(0); + #define foreach_vpe_api_msg \ _(ONE_ADD_DEL_LOCATOR_SET, one_add_del_locator_set) \ _(ONE_ADD_DEL_LOCATOR, one_add_del_locator) \ @@ -1300,10 +1315,62 @@ static void REPLY_MACRO (VL_API_ONE_ENABLE_DISABLE_REPLY); } +static void +lisp_fid_addr_to_api (fid_address_t * fid, u8 * dst, u8 * api_eid_type, + u8 * prefix_length) +{ + switch (fid_addr_type (fid)) + { + case FID_ADDR_IP_PREF: + *prefix_length = fid_addr_prefix_length (fid); + if (fid_addr_ip_version (fid) == IP4) + { + *api_eid_type = 0; /* ipv4 type */ + clib_memcpy (dst, &fid_addr_ippref (fid), 4); + } + else + { + *api_eid_type = 1; /* ipv6 type */ + clib_memcpy (dst, &fid_addr_ippref (fid), 16); + } + break; + case FID_ADDR_MAC: + *api_eid_type = 2; /* l2 mac type */ + mac_copy (dst, fid_addr_mac (fid)); + break; + default: + ASSERT (0); + } +} + static void vl_api_one_stats_dump_t_handler (vl_api_one_stats_dump_t * mp) { + vl_api_one_stats_details_t *rmp; + lisp_api_stats_t *stats, *stat; + u8 rv = 0; + stats = vnet_lisp_get_stats (); + vec_foreach (stat, stats) + { + /* *INDENT-OFF* */ + REPLY_DETAILS (VL_API_ONE_STATS_DETAILS, + ({ + lisp_fid_addr_to_api (&stat->deid, rmp->deid, &rmp->eid_type, + &rmp->deid_pref_len); + lisp_fid_addr_to_api (&stat->seid, rmp->seid, &rmp->eid_type, + &rmp->seid_pref_len); + rmp->vni = clib_host_to_net_u32 (stat->vni); + + rmp->is_ip4 = ip_addr_version (&stat->rmt_rloc) == IP4 ? 1 : 0; + ip_address_copy_addr (rmp->rloc, &stat->rmt_rloc); + ip_address_copy_addr (rmp->lloc, &stat->loc_rloc); + + rmp->pkt_count = clib_host_to_net_u32 (stat->stats.pkt_count); + rmp->bytes = clib_host_to_net_u32 (stat->stats.bytes); + })); + /* *INDENT-ON* */ + } } /* diff --git a/src/vnet/lisp-cp/one_cli.c b/src/vnet/lisp-cp/one_cli.c index 2ceeaf42..b5bc5292 100644 --- a/src/vnet/lisp-cp/one_cli.c +++ b/src/vnet/lisp-cp/one_cli.c @@ -352,7 +352,7 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm, } } - if (!eid_set) + if (!del_all && !eid_set) { clib_warning ("missing eid!"); goto done; @@ -372,8 +372,6 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm, goto done; } - /* TODO build src/dst with seid */ - /* if it's a delete, clean forwarding */ if (!is_add) { @@ -1654,12 +1652,46 @@ lisp_show_stats_command_fn (vlib_main_t * vm, /* *INDENT-OFF* */ VLIB_CLI_COMMAND (one_show_stats_command) = { - .path = "show one stats", - .short_help = "show ONE statistics", + .path = "show one statistics status", + .short_help = "show ONE statistics enable/disable status", .function = lisp_show_stats_command_fn, }; /* *INDENT-ON* */ +static clib_error_t * +lisp_show_stats_details_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + lisp_api_stats_t *stat, *stats = vnet_lisp_get_stats (); + + if (vec_len (stats) > 0) + vlib_cli_output (vm, + "[src-EID, dst-EID] [loc-rloc, rmt-rloc] count bytes\n"); + else + vlib_cli_output (vm, "No statistics found.\n"); + + vec_foreach (stat, stats) + { + vlib_cli_output (vm, "[%U, %U] [%U, %U] %7u %7u\n", + format_fid_address, &stat->seid, + format_fid_address, &stat->deid, + format_ip_address, &stat->loc_rloc, + format_ip_address, &stat->rmt_rloc, + stat->stats.pkt_count, stat->stats.bytes); + } + vec_free (stats); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (one_show_stats_details_command) = { + .path = "show one statistics details", + .short_help = "show ONE statistics", + .function = lisp_show_stats_details_command_fn, +}; +/* *INDENT-ON* */ + static clib_error_t * lisp_stats_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t * input, @@ -1692,12 +1724,29 @@ done: /* *INDENT-OFF* */ VLIB_CLI_COMMAND (one_stats_enable_disable_command) = { - .path = "one stats", + .path = "one statistics", .short_help = "enable/disable ONE statistics collecting", .function = lisp_stats_enable_disable_command_fn, }; /* *INDENT-ON* */ +static clib_error_t * +lisp_stats_flush_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + vnet_lisp_flush_stats (); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (one_stats_flush_command) = { + .path = "one statistics flush", + .short_help = "Flush ONE statistics", + .function = lisp_stats_flush_command_fn, +}; +/* *INDENT-ON* */ + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vnet/lisp-gpe/lisp_gpe.c b/src/vnet/lisp-gpe/lisp_gpe.c index 446ad445..1241ab9c 100644 --- a/src/vnet/lisp-gpe/lisp_gpe.c +++ b/src/vnet/lisp-gpe/lisp_gpe.c @@ -424,6 +424,8 @@ lisp_gpe_init (vlib_main_t * vm) udp_register_dst_port (vm, UDP_DST_PORT_lisp_gpe6, lisp_gpe_ip6_input_node.index, 0 /* is_ip4 */ ); + lgm->lisp_stats_index_by_key = + hash_create_mem (0, sizeof (lisp_stats_key_t), sizeof (uword)); return 0; } diff --git a/src/vnet/lisp-gpe/lisp_gpe.h b/src/vnet/lisp-gpe/lisp_gpe.h index b5a50ec6..be447024 100644 --- a/src/vnet/lisp-gpe/lisp_gpe.h +++ b/src/vnet/lisp-gpe/lisp_gpe.h @@ -90,6 +90,28 @@ typedef struct tunnel_lookup uword *vni_by_sw_if_index; } tunnel_lookup_t; +typedef struct +{ + u32 fwd_entry_index; + u32 tunnel_index; +} lisp_stats_key_t; + +typedef struct +{ + u32 pkt_count; + u32 bytes; +} lisp_stats_t; + +typedef struct +{ + u32 vni; + dp_address_t deid; + dp_address_t seid; + ip_address_t loc_rloc; + ip_address_t rmt_rloc; + + lisp_stats_t stats; +} lisp_api_stats_t; typedef enum gpe_encap_mode_e { @@ -143,6 +165,9 @@ typedef struct lisp_gpe_main gpe_encap_mode_t encap_mode; + lisp_stats_t *lisp_stats_pool; + uword *lisp_stats_index_by_key; + /** convenience */ vlib_main_t *vlib_main; vnet_main_t *vnet_main; @@ -283,6 +308,11 @@ lisp_api_gpe_fwd_entry_t *vnet_lisp_gpe_fwd_entries_get_by_vni (u32 vni); gpe_encap_mode_t vnet_gpe_get_encap_mode (void); int vnet_gpe_set_encap_mode (gpe_encap_mode_t mode); +u8 vnet_lisp_stats_enable_disable_state (void); +vnet_api_error_t vnet_lisp_stats_enable_disable (u8 enable); +lisp_api_stats_t *vnet_lisp_get_stats (void); +void vnet_lisp_flush_stats (void); + #endif /* included_vnet_lisp_gpe_h */ /* diff --git a/src/vnet/lisp-gpe/lisp_gpe_adjacency.c b/src/vnet/lisp-gpe/lisp_gpe_adjacency.c index dbcf7134..50662dd6 100644 --- a/src/vnet/lisp-gpe/lisp_gpe_adjacency.c +++ b/src/vnet/lisp-gpe/lisp_gpe_adjacency.c @@ -19,6 +19,7 @@ */ #include +#include #include #include #include @@ -223,9 +224,108 @@ lisp_gpe_adj_proto_from_vnet_link_type (vnet_link_t linkt) #define is_v4_packet(_h) ((*(u8*) _h) & 0xF0) == 0x40 +static lisp_afi_e +lisp_afi_from_vnet_link_type (vnet_link_t link) +{ + switch (link) + { + case VNET_LINK_IP4: + return LISP_AFI_IP; + case VNET_LINK_IP6: + return LISP_AFI_IP6; + case VNET_LINK_ETHERNET: + return LISP_AFI_MAC; + default: + return LISP_AFI_NO_ADDR; + } +} + +static void +lisp_gpe_increment_stats_counters (lisp_cp_main_t * lcm, ip_adjacency_t * adj, + vlib_buffer_t * b) +{ + lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); + lisp_gpe_adjacency_t *ladj; + ip_address_t rloc; + index_t lai; + u32 si, di; + gid_address_t src, dst; + lisp_stats_t *stats; + uword *feip; + + ip46_address_to_ip_address (&adj->sub_type.nbr.next_hop, &rloc); + si = vnet_buffer (b)->sw_if_index[VLIB_TX]; + lai = lisp_adj_find (&rloc, si); + ASSERT (INDEX_INVALID != lai); + + ladj = pool_elt_at_index (lisp_adj_pool, lai); + + u8 *lisp_data = (u8 *) vlib_buffer_get_current (b); + + /* skip IP header */ + if (is_v4_packet (lisp_data)) + lisp_data += sizeof (ip4_header_t); + else + lisp_data += sizeof (ip6_header_t); + + /* skip UDP header */ + lisp_data += sizeof (udp_header_t); + // TODO: skip TCP? + + /* skip LISP GPE header */ + lisp_data += sizeof (lisp_gpe_header_t); + + i16 saved_current_data = b->current_data; + b->current_data = lisp_data - b->data; + + lisp_afi_e afi = lisp_afi_from_vnet_link_type (adj->ia_link); + get_src_and_dst_eids_from_buffer (lcm, b, &src, &dst, afi); + b->current_data = saved_current_data; + di = gid_dictionary_sd_lookup (&lcm->mapping_index_by_gid, &dst, &src); + if (PREDICT_FALSE (~0 == di)) + { + clib_warning ("dst mapping not found (%U, %U)", format_gid_address, + &src, format_gid_address, &dst); + return; + } + + feip = hash_get (lcm->fwd_entry_by_mapping_index, di); + if (PREDICT_FALSE (!feip)) + return; + + lisp_stats_key_t key; + memset (&key, 0, sizeof (key)); + key.fwd_entry_index = feip[0]; + key.tunnel_index = ladj->tunnel_index; + + uword *p = hash_get_mem (lgm->lisp_stats_index_by_key, &key); + if (p) + { + stats = pool_elt_at_index (lgm->lisp_stats_pool, p[0]); + } + else + { + pool_get (lgm->lisp_stats_pool, stats); + memset (stats, 0, sizeof (*stats)); + + lisp_stats_key_t *key_copy = clib_mem_alloc (sizeof (*key_copy)); + memcpy (key_copy, &key, sizeof (*key_copy)); + hash_set_mem (lgm->lisp_stats_index_by_key, key_copy, + stats - lgm->lisp_stats_pool); + } + stats->pkt_count++; + /* compute payload length starting after GPE */ + stats->bytes += b->current_length - (lisp_data - b->data - b->current_data); +} + static void lisp_gpe_fixup (vlib_main_t * vm, ip_adjacency_t * adj, vlib_buffer_t * b) { + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + + if (lcm->flags & LISP_FLAG_STATS_ENABLED) + lisp_gpe_increment_stats_counters (lcm, adj, b); + /* Fixup the checksum and len fields in the LISP tunnel encap * that was applied at the midchain node */ ip_udp_fixup_one (vm, b, is_v4_packet (vlib_buffer_get_current (b))); diff --git a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c index 2eb5ced6..f458a14c 100644 --- a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c +++ b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c @@ -329,28 +329,6 @@ delete_fib_entries (lisp_gpe_fwd_entry_t * lfe) lfe->eid_fib_index, &lfe->key->rmt.ippref); } -static void -gid_to_dp_address (gid_address_t * g, dp_address_t * d) -{ - switch (gid_address_type (g)) - { - case GID_ADDR_IP_PREFIX: - case GID_ADDR_SRC_DST: - ip_prefix_copy (&d->ippref, &gid_address_ippref (g)); - d->type = FID_ADDR_IP_PREF; - break; - case GID_ADDR_MAC: - mac_copy (&d->mac, &gid_address_mac (g)); - d->type = FID_ADDR_MAC; - break; - case GID_ADDR_NSH: - default: - d->nsh = gid_address_nsh (g).spi << 8 | gid_address_nsh (g).si; - d->type = FID_ADDR_NSH; - break; - } -} - static lisp_gpe_fwd_entry_t * find_fwd_entry (lisp_gpe_main_t * lgm, vnet_lisp_gpe_add_del_fwd_entry_args_t * a, @@ -1177,6 +1155,70 @@ vnet_lisp_gpe_add_del_fwd_entry (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, } } +void +vnet_lisp_flush_stats (void) +{ + lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); + lisp_stats_t *stat; + + /* *INDENT-OFF* */ + pool_foreach (stat, lgm->lisp_stats_pool, + { + stat->pkt_count = 0; + stat->bytes = 0; + }); + /* *INDENT-ON* */ +} + +static void +lisp_del_adj_stats (lisp_gpe_main_t * lgm, u32 fwd_entry_index, u32 ti) +{ + hash_pair_t *hp; + lisp_stats_key_t key; + void *key_copy; + uword *p; + lisp_stats_t *s; + + memset (&key, 0, sizeof (key)); + key.fwd_entry_index = fwd_entry_index; + key.tunnel_index = ti; + + p = hash_get_mem (lgm->lisp_stats_index_by_key, &key); + if (p) + { + s = pool_elt_at_index (lgm->lisp_stats_pool, p[0]); + hp = hash_get_pair (lgm->lisp_stats_index_by_key, &key); + key_copy = (void *) (hp->key); + hash_unset_mem (lgm->lisp_stats_index_by_key, &key); + clib_mem_free (key_copy); + pool_put (lgm->lisp_stats_pool, s); + } +} + +void +vnet_lisp_del_fwd_stats (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, + u32 fwd_entry_index) +{ + lisp_gpe_main_t *lgm = &lisp_gpe_main; + lisp_gpe_fwd_entry_key_t fe_key; + lisp_gpe_fwd_entry_t *lfe; + lisp_fwd_path_t *path; + const lisp_gpe_adjacency_t *ladj; + + lfe = find_fwd_entry (lgm, a, &fe_key); + if (!lfe) + return; + + if (LISP_GPE_FWD_ENTRY_TYPE_NORMAL != lfe->type) + return; + + vec_foreach (path, lfe->paths) + { + ladj = lisp_gpe_adjacency_get (path->lisp_adj); + lisp_del_adj_stats (lgm, fwd_entry_index, ladj->tunnel_index); + } +} + /** * @brief Flush all the forwrding entries */ diff --git a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h index d58895a3..618f7b53 100644 --- a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h +++ b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h @@ -206,6 +206,9 @@ extern u32 lisp_l2_fib_lookup (lisp_gpe_main_t * lgm, extern const dpo_id_t *lisp_nsh_fib_lookup (lisp_gpe_main_t * lgm, u32 spi_si); +extern void +vnet_lisp_del_fwd_stats (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, + u32 fwd_entry_index); #endif /* -- cgit 1.2.3-korg From 816f437d943688f67d61fb6b9708eff59432b2ee Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Wed, 26 Apr 2017 16:09:06 +0200 Subject: Fix vnet unit tests Change-Id: Ibe55e4399c6b78d83268d7c49ed498cab7bfdb43 Signed-off-by: Filip Tehlar --- build-data/packages/vpp.mk | 4 +++ src/tests/vnet/lisp-cp/test_cp_serdes.c | 51 ++++++++++++++++++++++++++++++-- src/tests/vnet/lisp-cp/test_lisp_types.c | 45 +++++++++++++++++++++------- src/tests/vnet/lisp-gpe/test.c | 18 ----------- src/vlib/buffer.h | 12 ++++++++ src/vnet.am | 13 -------- src/vnet/lisp-cp/control.c | 14 ++++----- src/vnet/lisp-cp/control.h | 9 ++++++ src/vnet/lisp-cp/lisp_msg_serdes.c | 8 +++++ src/vnet/lisp-cp/lisp_types.c | 31 ++++++++++--------- src/vpp.am | 1 - src/vpp/api/test_client.c | 11 ------- src/vppinfra/test_tw_timer.c | 8 ++--- 13 files changed, 142 insertions(+), 83 deletions(-) delete mode 100644 src/tests/vnet/lisp-gpe/test.c (limited to 'src/vnet/lisp-cp/control.h') diff --git a/build-data/packages/vpp.mk b/build-data/packages/vpp.mk index 64eb0d89..1acc59b2 100644 --- a/build-data/packages/vpp.mk +++ b/build-data/packages/vpp.mk @@ -30,3 +30,7 @@ ifeq ($($(PLATFORM)_uses_dpdk_mlx5_pmd),yes) vpp_configure_args += --with-dpdk-mlx5-pmd endif endif + +ifeq ($($(PLATFORM)_enable_tests),yes) +vpp_configure_args += --enable-tests +endif diff --git a/src/tests/vnet/lisp-cp/test_cp_serdes.c b/src/tests/vnet/lisp-cp/test_cp_serdes.c index 0766bee1..8e8c8455 100644 --- a/src/tests/vnet/lisp-cp/test_cp_serdes.c +++ b/src/tests/vnet/lisp-cp/test_cp_serdes.c @@ -21,9 +21,6 @@ #include #include -/* FIXME */ -#include - #define _assert(e) \ error = CLIB_ERROR_ASSERT (e); \ if (error) \ @@ -489,6 +486,53 @@ done: return error; } +static vlib_buffer_t * +create_buffer (u8 * data, u32 data_len) +{ + vlib_buffer_t *b; + + u8 *buf_data = clib_mem_alloc(500); + memset (buf_data, 0, 500); + b = (vlib_buffer_t *)buf_data; + + u8 * p = vlib_buffer_put_uninit (b, data_len); + clib_memcpy (p, data, data_len); + + return b; +} + +static clib_error_t * +test_lisp_parse_map_reply () +{ + clib_error_t * error = 0; + u8 map_reply_data[] = + { + 0x00, 0x00, 0x00, 0x01, /* type; rsvd; mapping count */ + 0x00, 0x00, 0x00, 0x00, + }; + vlib_buffer_t *b = create_buffer (map_reply_data, sizeof (map_reply_data)); + map_records_arg_t *mrecs = parse_map_reply (b); + _assert (0 == mrecs); + clib_mem_free (b); + + u8 map_reply_data2[] = + { + 0x00, 0x00, 0x00, 0x01, /* type; rsvd */ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /* nonce */ + + /* 1. record - incomplete */ + 0x01, 0x02, 0x03, 0x04, /* record TTL */ + 0x01, /* locator count */ + }; + b = create_buffer (map_reply_data2, sizeof (map_reply_data2)); + mrecs = parse_map_reply (b); + _assert (0 == mrecs); +done: + clib_mem_free (b); + return error; +} + static clib_error_t * test_lisp_parse_lcaf () { @@ -610,6 +654,7 @@ done: _(lisp_msg_push_ecm) \ _(lisp_msg_parse) \ _(lisp_msg_parse_mapping_record) \ + _(lisp_parse_map_reply) \ _(lisp_parse_lcaf) \ _(lisp_map_register) diff --git a/src/tests/vnet/lisp-cp/test_lisp_types.c b/src/tests/vnet/lisp-cp/test_lisp_types.c index fa34a3c6..21575015 100644 --- a/src/tests/vnet/lisp-cp/test_lisp_types.c +++ b/src/tests/vnet/lisp-cp/test_lisp_types.c @@ -18,9 +18,6 @@ #include #include -/* FIXME */ -#include - #define _assert(e) \ error = CLIB_ERROR_ASSERT (e); \ if (error) \ @@ -265,7 +262,6 @@ done: } #endif -#if 0 /* uncomment this once VNI is supported */ static clib_error_t * test_write_mac_in_lcaf (void) { clib_error_t * error = 0; @@ -276,13 +272,12 @@ static clib_error_t * test_write_mac_in_lcaf (void) gid_address_t g = { .mac = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6}, - .vni = 0x30, + .vni = 0x01020304, .vni_mask = 0x10, .type = GID_ADDR_MAC, }; u16 len = gid_address_put (b, &g); - _assert (8 == len); u8 expected[] = { @@ -290,20 +285,20 @@ static clib_error_t * test_write_mac_in_lcaf (void) 0x00, /* reserved1 */ 0x00, /* flags */ 0x02, /* LCAF type = Instance ID */ - 0x20, /* IID/VNI mask len */ - 0x00, 0x0a, /* length */ + 0x10, /* IID/IID mask len */ + 0x00, 0x0c, /* length */ 0x01, 0x02, 0x03, 0x04, /* Instance ID / VNI */ - 0x00, 0x06, /* AFI = MAC */ + 0x40, 0x05, /* AFI = MAC */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 /* MAC */ - } + }; + _assert (sizeof (expected) == len); _assert (0 == memcmp (expected, b, len)); done: clib_mem_free (b); return error; } -#endif static clib_error_t * test_mac_address_write (void) { @@ -417,6 +412,32 @@ done: return error; } +static clib_error_t * +test_src_dst_deser_bad_afi (void) +{ + clib_error_t * error = 0; + + u8 expected_data[] = + { + 0x40, 0x03, 0x00, 0x00, /* AFI = LCAF, reserved1, flags */ + 0x0c, 0x00, 0x00, 0x14, /* LCAF type = source/dest key, rsvd, length */ + 0x00, 0x00, 0x00, 0x00, /* reserved; source-ML, Dest-ML */ + + 0xde, 0xad, /* AFI = bad value */ + 0x11, 0x22, 0x33, 0x44, + 0x55, 0x66, /* source */ + + 0x40, 0x05, /* AFI = MAC */ + 0x10, 0x21, 0x32, 0x43, + 0x54, 0x65, /* destination */ + }; + + gid_address_t p; + _assert (~0 == gid_address_parse (expected_data, &p)); +done: + return error; +} + static clib_error_t * test_src_dst_serdes (void) { @@ -537,6 +558,8 @@ done: _(mac_address_write) \ _(gid_address_write) \ _(src_dst_serdes) \ + _(write_mac_in_lcaf) \ + _(src_dst_deser_bad_afi) \ _(src_dst_with_vni_serdes) int run_tests (void) diff --git a/src/tests/vnet/lisp-gpe/test.c b/src/tests/vnet/lisp-gpe/test.c deleted file mode 100644 index dde633ae..00000000 --- a/src/tests/vnet/lisp-gpe/test.c +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ - -int main(int argc, char **argv) { - return 0; -} diff --git a/src/vlib/buffer.h b/src/vlib/buffer.h index 69c8c7cc..18e2437d 100644 --- a/src/vlib/buffer.h +++ b/src/vlib/buffer.h @@ -205,6 +205,18 @@ vlib_buffer_advance (vlib_buffer_t * b, word l) b->current_length -= l; } +/** \brief Check if there is enough space in buffer to advance + + @param b - (vlib_buffer_t *) pointer to the buffer + @param l - (word) size to check + @return - 0 if there is less space than 'l' in buffer +*/ +always_inline u8 +vlib_buffer_has_space (vlib_buffer_t * b, word l) +{ + return b->current_length >= l; +} + /** \brief Reset current header & length to state they were in when packet was received. diff --git a/src/vnet.am b/src/vnet.am index 25b84616..9f3aedba 100644 --- a/src/vnet.am +++ b/src/vnet.am @@ -662,19 +662,6 @@ nobase_include_HEADERS += \ API_FILES += vnet/lisp-gpe/lisp_gpe.api -if ENABLE_TESTS -TESTS += test_test - -test_test_SOURCES = tests/vnet/lisp-gpe/test.c - -test_test_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG - -test_test_LDADD = $(LIBOBJS) - -noinst_PROGRAMS += $(TESTS) -check_PROGRAMS += $(TESTS) -endif - ######################################## # DHCP client ######################################## diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index 6408b297..c0093301 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -44,13 +44,6 @@ typedef struct u8 smr_invoked; } map_request_args_t; -typedef struct -{ - u64 nonce; - u8 is_rloc_probe; - mapping_t *mappings; -} map_records_arg_t; - u8 vnet_lisp_get_map_request_mode (void) { @@ -3485,7 +3478,7 @@ done: vec_free (itr_rlocs); } -static map_records_arg_t * +map_records_arg_t * parse_map_reply (vlib_buffer_t * b) { locator_t probed; @@ -3501,6 +3494,11 @@ parse_map_reply (vlib_buffer_t * b) mrep_hdr = vlib_buffer_get_current (b); a->nonce = MREP_NONCE (mrep_hdr); a->is_rloc_probe = MREP_RLOC_PROBE (mrep_hdr); + if (!vlib_buffer_has_space (b, sizeof (*mrep_hdr))) + { + clib_mem_free (a); + return 0; + } vlib_buffer_pull (b, sizeof (*mrep_hdr)); for (i = 0; i < MREP_REC_COUNT (mrep_hdr); i++) diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index eae8a184..cb98eb09 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -273,6 +273,13 @@ typedef struct u8 key_id; } vnet_lisp_add_del_mapping_args_t; +typedef struct +{ + u64 nonce; + u8 is_rloc_probe; + mapping_t *mappings; +} map_records_arg_t; + int vnet_lisp_map_cache_add_del (vnet_lisp_add_del_mapping_args_t * a, u32 * map_index); @@ -332,6 +339,8 @@ int vnet_lisp_map_register_enable_disable (u8 is_enable); u8 vnet_lisp_map_register_state_get (void); u8 vnet_lisp_rloc_probe_state_get (void); +map_records_arg_t *parse_map_reply (vlib_buffer_t * b); + always_inline mapping_t * lisp_get_petr_mapping (lisp_cp_main_t * lcm) { diff --git a/src/vnet/lisp-cp/lisp_msg_serdes.c b/src/vnet/lisp-cp/lisp_msg_serdes.c index eee1885c..6c0a7219 100644 --- a/src/vnet/lisp-cp/lisp_msg_serdes.c +++ b/src/vnet/lisp-cp/lisp_msg_serdes.c @@ -312,6 +312,8 @@ lisp_msg_parse_loc (vlib_buffer_t * b, locator_t * loc) if (len == ~0) return ~0; + if (!vlib_buffer_has_space (b, sizeof (len))) + return ~0; vlib_buffer_pull (b, len); return len; @@ -326,6 +328,9 @@ lisp_msg_parse_mapping_record (vlib_buffer_t * b, gid_address_t * eid, int i = 0, len = 0, llen = 0; h = vlib_buffer_get_current (b); + if (!vlib_buffer_has_space (b, sizeof (mapping_record_hdr_t))) + return ~0; + vlib_buffer_pull (b, sizeof (mapping_record_hdr_t)); memset (eid, 0, sizeof (*eid)); @@ -333,6 +338,9 @@ lisp_msg_parse_mapping_record (vlib_buffer_t * b, gid_address_t * eid, if (len == ~0) return len; + if (!vlib_buffer_has_space (b, sizeof (len))) + return ~0; + vlib_buffer_pull (b, len); if (GID_ADDR_IP_PREFIX == gid_address_type (eid)) gid_address_ippref_len (eid) = MAP_REC_EID_PLEN (h); diff --git a/src/vnet/lisp-cp/lisp_types.c b/src/vnet/lisp-cp/lisp_types.c index ad3a4bdf..31a80081 100644 --- a/src/vnet/lisp-cp/lisp_types.c +++ b/src/vnet/lisp-cp/lisp_types.c @@ -657,12 +657,19 @@ fid_addr_parse (u8 * p, fid_address_t * a) return ip_address_parse (p, afi, ip_addr); case FID_ADDR_NSH: - ASSERT (0); break; } return ~0; } +#define INC(dst, exp) \ +do { \ + u16 _sum = (exp); \ + if ((u16)~0 == _sum) \ + return ~0; \ + dst += _sum; \ +} while (0); + u16 sd_parse (u8 * p, void *a) { @@ -677,8 +684,8 @@ sd_parse (u8 * p, void *a) sd_hdr = (lcaf_src_dst_hdr_t *) (p + size); size += sizeof (sd_hdr[0]); - size += fid_addr_parse (p + size, src); - size += fid_addr_parse (p + size, dst); + INC (size, fid_addr_parse (p + size, src)); + INC (size, fid_addr_parse (p + size, dst)); if (fid_addr_type (src) == FID_ADDR_IP_PREF) { @@ -704,7 +711,7 @@ try_parse_src_dst_lcaf (u8 * p, gid_address_t * a) if (LCAF_SOURCE_DEST != lcaf_type (&lcaf)) return ~0; - size += sd_parse (p + size, a); + INC (size, sd_parse (p + size, a)); return size; } @@ -724,13 +731,10 @@ vni_parse (u8 * p, void *a) u16 afi = clib_net_to_host_u16 (*((u16 *) (p + size))); if (LISP_AFI_LCAF == afi) { - u16 len = try_parse_src_dst_lcaf (p + size, g); - if ((u16) ~ 0 == len) - return ~0; - size += len; + INC (size, try_parse_src_dst_lcaf (p + size, g)); } else - size += gid_address_parse (p + size, g); + INC (size, gid_address_parse (p + size, g)); return size; } @@ -757,7 +761,7 @@ lcaf_parse (void *offset, gid_address_t * addr) clib_warning ("Unsupported LCAF type: %u", type); return ~0; } - size += (*lcaf_parse_fcts[type]) (offset + size, lcaf); + INC (size, (*lcaf_parse_fcts[type]) (offset + size, lcaf)); return sizeof (u16) + size; } @@ -1419,10 +1423,9 @@ u32 gid_address_parse (u8 * offset, gid_address_t * a) { lisp_afi_e afi; - int len = 0; + u16 len = 0; - if (!a) - return 0; + ASSERT (a); /* NOTE: since gid_address_parse may be called by vni_parse, we can't 0 * the gid address here */ @@ -1458,7 +1461,7 @@ gid_address_parse (u8 * offset, gid_address_t * a) clib_warning ("LISP AFI %d not supported!", afi); return ~0; } - return len; + return (len == (u16) ~ 0) ? ~0 : len; } void diff --git a/src/vpp.am b/src/vpp.am index 8cdc60d9..d8b3e4ec 100644 --- a/src/vpp.am +++ b/src/vpp.am @@ -100,7 +100,6 @@ bin_test_ha_SOURCES = \ bin_test_ha_LDADD = \ libvlibmemoryclient.la \ - libvlibapi.la \ libsvm.la \ libvppinfra.la \ -lpthread -lm -lrt diff --git a/src/vpp/api/test_client.c b/src/vpp/api/test_client.c index 551bdab9..231b3c18 100644 --- a/src/vpp/api/test_client.c +++ b/src/vpp/api/test_client.c @@ -541,13 +541,6 @@ static void vl_api_create_loopback_instance_reply_t_handler ntohl (mp->retval), ntohl (mp->sw_if_index)); } -static void -vl_api_sr_tunnel_add_del_reply_t_handler (vl_api_sr_tunnel_add_del_reply_t * - mp) -{ - fformat (stdout, "sr tunnel add/del reply %d\n", ntohl (mp->retval)); -} - static void vl_api_l2_patch_add_del_reply_t_handler (vl_api_l2_patch_add_del_reply_t * mp) { @@ -949,7 +942,6 @@ add_ip4_neighbor (test_main_t * tm, int add_del) mp->_vl_msg_id = ntohs (VL_API_IP_NEIGHBOR_ADD_DEL); mp->client_index = tm->my_client_index; mp->context = 0xdeadbeef; - mp->vrf_id = ntohl (11); mp->sw_if_index = ntohl (6); mp->is_add = add_del; @@ -972,7 +964,6 @@ add_ip6_neighbor (test_main_t * tm, int add_del) mp->_vl_msg_id = ntohs (VL_API_IP_NEIGHBOR_ADD_DEL); mp->client_index = tm->my_client_index; mp->context = 0xdeadbeef; - mp->vrf_id = ntohl (11); mp->sw_if_index = ntohl (6); mp->is_add = add_del; mp->is_ipv6 = 1; @@ -1055,9 +1046,7 @@ dhcp_set_proxy (test_main_t * tm, int ipv6) mp->_vl_msg_id = ntohs (VL_API_DHCP_PROXY_CONFIG); mp->client_index = tm->my_client_index; mp->context = 0xdeadbeef; - mp->vrf_id = ntohl (0); mp->is_ipv6 = ipv6; - mp->insert_circuit_id = 1; mp->is_add = 1; mp->dhcp_server[0] = 0x20; mp->dhcp_server[1] = 0x01; diff --git a/src/vppinfra/test_tw_timer.c b/src/vppinfra/test_tw_timer.c index a0287b89..26499509 100644 --- a/src/vppinfra/test_tw_timer.c +++ b/src/vppinfra/test_tw_timer.c @@ -138,7 +138,7 @@ test2_single (tw_timer_test_main_t * tm) tw_timer_wheel_init_2t_1w_2048sl (&tm->single_wheel, expired_timer_single_callback, - 1.0 /* timer interval */ ); + 1.0 /* timer interval */ , ~0); /* Prime offset */ initial_wheel_offset = 757; @@ -266,7 +266,7 @@ test2_double (tw_timer_test_main_t * tm) tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel, expired_timer_double_callback, - 1.0 /* timer interval */ ); + 1.0 /* timer interval */ , ~0); /* Prime offset */ initial_wheel_offset = 757; @@ -387,7 +387,7 @@ test1_single (tw_timer_test_main_t * tm) tw_timer_wheel_init_2t_1w_2048sl (&tm->single_wheel, expired_timer_single_callback, - 1.0 /* timer interval */ ); + 1.0 /* timer interval */ , ~0); /* * Prime offset, to make sure that the wheel starts in a @@ -454,7 +454,7 @@ test1_double (tw_timer_test_main_t * tm) tw_timer_wheel_init_16t_2w_512sl (&tm->double_wheel, expired_timer_double_callback, - 1.0 /* timer interval */ ); + 1.0 /* timer interval */ , ~0); /* * Prime offset, to make sure that the wheel starts in a -- cgit 1.2.3-korg From d5a65db98d66c66b03b057ac568be05f2456f73c Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Wed, 17 May 2017 17:21:10 +0200 Subject: LISP: L2 ARP handling Change-Id: I1ec328cda73f7eaf7867cd8a2a17852ee0cd23f1 Signed-off-by: Filip Tehlar --- src/vat/api_format.c | 233 ++++++++++++++++++++++++++++++++++++++ src/vnet/lisp-cp/control.c | 232 ++++++++++++++++++++++++++++++++----- src/vnet/lisp-cp/control.h | 15 +++ src/vnet/lisp-cp/gid_dictionary.c | 91 ++++++++++++++- src/vnet/lisp-cp/gid_dictionary.h | 25 +++- src/vnet/lisp-cp/lisp_types.c | 3 + src/vnet/lisp-cp/lisp_types.h | 15 +++ src/vnet/lisp-cp/one.api | 73 ++++++++++++ src/vnet/lisp-cp/one_api.c | 82 ++++++++++++++ src/vnet/lisp-cp/one_cli.c | 100 ++++++++++++++++ 10 files changed, 833 insertions(+), 36 deletions(-) (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/vat/api_format.c b/src/vat/api_format.c index f3e6f64c..3eff8ef0 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -3163,6 +3163,123 @@ end: vam->result_ready = 1; } +static void + vl_api_one_l2_arp_entries_get_reply_t_handler + (vl_api_one_l2_arp_entries_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + + for (i = 0; i < n; i++) + print (vam->ofp, "%U -> %U", format_ip4_address, &mp->entries[i].ip4, + format_ethernet_address, mp->entries[i].mac); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_l2_arp_entries_get_reply_t_handler_json + (vl_api_one_l2_arp_entries_get_reply_t * mp) +{ + u8 *s = 0; + vat_main_t *vam = &vat_main; + vat_json_node_t *e = 0, root; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + vl_api_one_l2_arp_entry_t *arp_entry; + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + vat_json_init_array (&root); + + for (i = 0; i < n; i++) + { + e = vat_json_array_add (&root); + arp_entry = &mp->entries[i]; + + vat_json_init_object (e); + s = format (0, "%U", format_ethernet_address, arp_entry->mac); + vec_add1 (s, 0); + + vat_json_object_add_string_copy (e, "mac", s); + vec_free (s); + + s = format (0, "%U", format_ip4_address, &arp_entry->ip4); + vec_add1 (s, 0); + vat_json_object_add_string_copy (e, "ip4", s); + vec_free (s); + } + + vat_json_print (vam->ofp, &root); + vat_json_free (&root); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_l2_arp_bd_get_reply_t_handler + (vl_api_one_l2_arp_bd_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + + for (i = 0; i < n; i++) + { + print (vam->ofp, "%d", clib_net_to_host_u32 (mp->bridge_domains[i])); + } + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_l2_arp_bd_get_reply_t_handler_json + (vl_api_one_l2_arp_bd_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t root; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + vat_json_init_array (&root); + + for (i = 0; i < n; i++) + { + vat_json_array_add_uint (&root, + clib_net_to_host_u32 (mp->bridge_domains[i])); + } + + vat_json_print (vam->ofp, &root); + vat_json_free (&root); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + static void vl_api_one_adjacencies_get_reply_t_handler (vl_api_one_adjacencies_get_reply_t * mp) @@ -4158,6 +4275,10 @@ static void vl_api_flow_classify_details_t_handler_json #define vl_api_vnet_ip6_nbr_counters_t_print vl_noop_handler #define vl_api_one_adjacencies_get_reply_t_endian vl_noop_handler #define vl_api_one_adjacencies_get_reply_t_print vl_noop_handler +#define vl_api_one_l2_arp_bd_get_reply_t_print vl_noop_handler +#define vl_api_one_l2_arp_entries_get_reply_t_endian vl_noop_handler +#define vl_api_one_l2_arp_entries_get_reply_t_print vl_noop_handler +#define vl_api_one_l2_arp_bd_get_reply_t_endian vl_noop_handler /* * Generate boilerplate reply handlers, which @@ -4267,6 +4388,7 @@ _(one_add_del_map_request_itr_rlocs_reply) \ _(one_eid_table_add_del_map_reply) \ _(one_use_petr_reply) \ _(one_stats_enable_disable_reply) \ +_(one_add_del_l2_arp_entry_reply) \ _(one_stats_flush_reply) \ _(gpe_add_del_fwd_entry_reply) \ _(gpe_enable_disable_reply) \ @@ -4499,6 +4621,9 @@ _(ONE_STATS_FLUSH_REPLY, one_stats_flush_reply) \ _(ONE_STATS_ENABLE_DISABLE_REPLY, one_stats_enable_disable_reply) \ _(SHOW_ONE_STATS_ENABLE_DISABLE_REPLY, \ show_one_stats_enable_disable_reply) \ +_(ONE_ADD_DEL_L2_ARP_ENTRY_REPLY, one_add_del_l2_arp_entry_reply) \ +_(ONE_L2_ARP_BD_GET_REPLY, one_l2_arp_bd_get_reply) \ +_(ONE_L2_ARP_ENTRIES_GET_REPLY, one_l2_arp_entries_get_reply) \ _(GPE_SET_ENCAP_MODE_REPLY, gpe_set_encap_mode_reply) \ _(GPE_GET_ENCAP_MODE_REPLY, gpe_get_encap_mode_reply) \ _(GPE_ADD_DEL_IFACE_REPLY, gpe_add_del_iface_reply) \ @@ -14736,6 +14861,111 @@ api_show_one_rloc_probe_state (vat_main_t * vam) #define api_show_lisp_rloc_probe_state api_show_one_rloc_probe_state +static int +api_one_add_del_l2_arp_entry (vat_main_t * vam) +{ + vl_api_one_add_del_l2_arp_entry_t *mp; + unformat_input_t *input = vam->input; + u8 is_add = 1; + u8 mac_set = 0; + u8 bd_set = 0; + u8 ip_set = 0; + u8 mac[6] = { 0, }; + u32 ip4 = 0, bd = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + is_add = 0; + else if (unformat (input, "mac %U", unformat_ethernet_address, mac)) + mac_set = 1; + else if (unformat (input, "ip %U", unformat_ip4_address, &ip4)) + ip_set = 1; + else if (unformat (input, "bd %d", &bd)) + bd_set = 1; + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!bd_set || !ip_set || (!mac_set && is_add)) + { + errmsg ("Missing BD, IP or MAC!"); + return -99; + } + + M (ONE_ADD_DEL_L2_ARP_ENTRY, mp); + mp->is_add = is_add; + clib_memcpy (mp->mac, mac, 6); + mp->bd = clib_host_to_net_u32 (bd); + mp->ip4 = ip4; + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +static int +api_one_l2_arp_bd_get (vat_main_t * vam) +{ + vl_api_one_l2_arp_bd_get_t *mp; + int ret; + + M (ONE_L2_ARP_BD_GET, mp); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +static int +api_one_l2_arp_entries_get (vat_main_t * vam) +{ + vl_api_one_l2_arp_entries_get_t *mp; + unformat_input_t *input = vam->input; + u8 bd_set = 0; + u32 bd = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "bd %d", &bd)) + bd_set = 1; + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!bd_set) + { + errmsg ("Expected bridge domain!"); + return -99; + } + + M (ONE_L2_ARP_ENTRIES_GET, mp); + mp->bd = clib_host_to_net_u32 (bd); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + static int api_one_stats_enable_disable (vat_main_t * vam) { @@ -19052,6 +19282,9 @@ _(one_locator_set_dump, "[local | remote]") \ _(one_locator_dump, "ls_index | ls_name ") \ _(one_eid_table_dump, "[eid / | ] [vni] " \ "[local] | [remote]") \ +_(one_add_del_l2_arp_entry, "[del] mac bd ip4 ") \ +_(one_l2_arp_bd_get, "") \ +_(one_l2_arp_entries_get, "bd ") \ _(one_stats_enable_disable, "enable|disalbe") \ _(show_one_stats_enable_disable, "") \ _(one_eid_table_vni_dump, "") \ diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index 439802c9..cea92556 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -821,6 +823,99 @@ vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a, return vnet_lisp_map_cache_add_del (a, map_index_result); } +static void +add_l2_arp_bd (BVT (clib_bihash_kv) * kvp, void *arg) +{ + u32 **ht = arg; + u32 bd = (u32) kvp->key[0]; + hash_set (ht[0], bd, 0); +} + +u32 * +vnet_lisp_l2_arp_bds_get (void) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + u32 *bds = 0; + + gid_dict_foreach_l2_arp_entry (&lcm->mapping_index_by_gid, + add_l2_arp_bd, &bds); + return bds; +} + +typedef struct +{ + void *vector; + u32 bd; +} lisp_add_l2_arp_args_t; + +static void +add_l2_arp_entry (BVT (clib_bihash_kv) * kvp, void *arg) +{ + lisp_add_l2_arp_args_t *a = arg; + lisp_api_l2_arp_entry_t **vector = a->vector, e; + + if ((u32) kvp->key[0] == a->bd) + { + mac_copy (e.mac, (void *) &kvp->value); + e.ip4 = (u32) kvp->key[1]; + vec_add1 (vector[0], e); + } +} + +lisp_api_l2_arp_entry_t * +vnet_lisp_l2_arp_entries_get_by_bd (u32 bd) +{ + lisp_api_l2_arp_entry_t *entries = 0; + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + lisp_add_l2_arp_args_t a; + + a.vector = &entries; + a.bd = bd; + + gid_dict_foreach_l2_arp_entry (&lcm->mapping_index_by_gid, + add_l2_arp_entry, &a); + return entries; +} + +int +vnet_lisp_add_del_l2_arp_entry (gid_address_t * key, u8 * mac, u8 is_add) +{ + if (vnet_lisp_enable_disable_status () == 0) + { + clib_warning ("LISP is disabled!"); + return VNET_API_ERROR_LISP_DISABLED; + } + + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + int rc = 0; + + u64 res = gid_dictionary_lookup (&lcm->mapping_index_by_gid, key); + if (is_add) + { + if (res != GID_LOOKUP_MISS_L2) + { + clib_warning ("Entry %U exists in DB!", format_gid_address, key); + return VNET_API_ERROR_ENTRY_ALREADY_EXISTS; + } + u64 val = mac_to_u64 (mac); + gid_dictionary_add_del (&lcm->mapping_index_by_gid, key, val, + 1 /* is_add */ ); + } + else + { + if (res == GID_LOOKUP_MISS_L2) + { + clib_warning ("ONE ARP entry %U not found - cannot delete!", + format_gid_address, key); + return -1; + } + gid_dictionary_add_del (&lcm->mapping_index_by_gid, key, 0, + 0 /* is_add */ ); + } + + return rc; +} + int vnet_lisp_eid_table_map (u32 vni, u32 dp_id, u8 is_l2, u8 is_add) { @@ -830,7 +925,7 @@ vnet_lisp_eid_table_map (u32 vni, u32 dp_id, u8 is_l2, u8 is_add) if (vnet_lisp_enable_disable_status () == 0) { clib_warning ("LISP is disabled!"); - return -1; + return VNET_API_ERROR_LISP_DISABLED; } dp_table_by_vni = is_l2 ? &lcm->bd_id_by_vni : &lcm->table_id_by_vni; @@ -1931,7 +2026,8 @@ vnet_lisp_add_del_mreq_itr_rlocs (vnet_lisp_add_del_mreq_itr_rloc_args_t * a) /* Statistics (not really errors) */ #define foreach_lisp_cp_lookup_error \ _(DROP, "drop") \ -_(MAP_REQUESTS_SENT, "map-request sent") +_(MAP_REQUESTS_SENT, "map-request sent") \ +_(ARP_REPLY_TX, "ARP replies sent") static char *lisp_cp_lookup_error_strings[] = { #define _(sym,string) string, @@ -1950,6 +2046,7 @@ typedef enum typedef enum { LISP_CP_LOOKUP_NEXT_DROP, + LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX, LISP_CP_LOOKUP_N_NEXT, } lisp_cp_lookup_next_t; @@ -2710,10 +2807,8 @@ lisp_get_vni_from_buffer_ip (lisp_cp_main_t * lcm, vlib_buffer_t * b, } always_inline u32 -lisp_get_vni_from_buffer_eth (lisp_cp_main_t * lcm, vlib_buffer_t * b) +lisp_get_bd_from_buffer_eth (vlib_buffer_t * b) { - uword *vnip; - u32 vni = ~0; u32 sw_if_index0; l2input_main_t *l2im = &l2input_main; @@ -2724,12 +2819,21 @@ lisp_get_vni_from_buffer_eth (lisp_cp_main_t * lcm, vlib_buffer_t * b) config = vec_elt_at_index (l2im->configs, sw_if_index0); bd_config = vec_elt_at_index (l2im->bd_configs, config->bd_index); - vnip = hash_get (lcm->vni_by_bd_id, bd_config->bd_id); + return bd_config->bd_id; +} + +always_inline u32 +lisp_get_vni_from_buffer_eth (lisp_cp_main_t * lcm, vlib_buffer_t * b) +{ + uword *vnip; + u32 vni = ~0; + u32 bd = lisp_get_bd_from_buffer_eth (b); + + vnip = hash_get (lcm->vni_by_bd_id, bd); if (vnip) vni = vnip[0]; else - clib_warning ("bridge domain %d is not mapped to any vni!", - config->bd_index); + clib_warning ("bridge domain %d is not mapped to any vni!", bd); return vni; } @@ -2744,6 +2848,9 @@ get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b, memset (src, 0, sizeof (*src)); memset (dst, 0, sizeof (*dst)); + gid_address_type (dst) = GID_ADDR_NO_ADDRESS; + gid_address_type (src) = GID_ADDR_NO_ADDRESS; + if (LISP_AFI_IP == type || LISP_AFI_IP6 == type) { ip4_header_t *ip; @@ -2767,19 +2874,35 @@ get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b, else if (LISP_AFI_MAC == type) { ethernet_header_t *eh; + ethernet_arp_header_t *ah; eh = vlib_buffer_get_current (b); - gid_address_type (src) = GID_ADDR_MAC; - gid_address_type (dst) = GID_ADDR_MAC; - mac_copy (&gid_address_mac (src), eh->src_address); - mac_copy (&gid_address_mac (dst), eh->dst_address); + if (clib_net_to_host_u16 (eh->type) == ETHERNET_TYPE_ARP) + { + ah = (ethernet_arp_header_t *) (((u8 *) eh) + sizeof (*eh)); + if (clib_net_to_host_u16 (ah->opcode) + != ETHERNET_ARP_OPCODE_request) + return; + + gid_address_type (dst) = GID_ADDR_ARP; + gid_address_arp_bd (dst) = lisp_get_bd_from_buffer_eth (b); + clib_memcpy (&gid_address_arp_ip4 (dst), + &ah->ip4_over_ethernet[1].ip4, 4); + } + else + { + gid_address_type (src) = GID_ADDR_MAC; + gid_address_type (dst) = GID_ADDR_MAC; + mac_copy (&gid_address_mac (src), eh->src_address); + mac_copy (&gid_address_mac (dst), eh->dst_address); - /* get vni */ - vni = lisp_get_vni_from_buffer_eth (lcm, b); + /* get vni */ + vni = lisp_get_vni_from_buffer_eth (lcm, b); - gid_address_vni (dst) = vni; - gid_address_vni (src) = vni; + gid_address_vni (dst) = vni; + gid_address_vni (src) = vni; + } } else if (LISP_AFI_LCAF == type) { @@ -2793,38 +2916,81 @@ lisp_cp_lookup_inline (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame, int overlay) { - u32 *from, *to_next_drop, di, si; + u32 *from, *to_next, di, si; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - u32 pkts_mapped = 0; - uword n_left_from, n_left_to_next_drop; + u32 pkts_mapped = 0, next_index; + uword n_left_from, n_left_to_next; + vnet_main_t *vnm = vnet_get_main (); from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; + next_index = node->cached_next_index; while (n_left_from > 0) { - vlib_get_next_frame (vm, node, LISP_CP_LOOKUP_NEXT_DROP, - to_next_drop, n_left_to_next_drop); + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - while (n_left_from > 0 && n_left_to_next_drop > 0) + while (n_left_from > 0 && n_left_to_next > 0) { - u32 pi0; + u32 pi0, sw_if_index0, next0; + u64 mac0; vlib_buffer_t *b0; gid_address_t src, dst; + ethernet_arp_header_t *arp0; + ethernet_header_t *eth0; + vnet_hw_interface_t *hw_if0; pi0 = from[0]; from += 1; n_left_from -= 1; - to_next_drop[0] = pi0; - to_next_drop += 1; - n_left_to_next_drop -= 1; + to_next[0] = pi0; + to_next += 1; + n_left_to_next -= 1; b0 = vlib_get_buffer (vm, pi0); - b0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP]; /* src/dst eid pair */ get_src_and_dst_eids_from_buffer (lcm, b0, &src, &dst, overlay); + if (gid_address_type (&dst) == GID_ADDR_ARP) + { + mac0 = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &dst); + if (GID_LOOKUP_MISS_L2 != mac0) + { + /* send ARP reply */ + + sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0; + + hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0); + + eth0 = vlib_buffer_get_current (b0); + arp0 = (ethernet_arp_header_t *) (((u8 *) eth0) + + sizeof (*eth0)); + arp0->opcode = + clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply); + arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0]; + clib_memcpy (arp0->ip4_over_ethernet[0].ethernet, + (u8 *) & mac0, 6); + clib_memcpy (&arp0->ip4_over_ethernet[0].ip4, + &gid_address_arp_ip4 (&dst), 4); + + /* Hardware must be ethernet-like. */ + ASSERT (vec_len (hw_if0->hw_address) == 6); + + clib_memcpy (eth0->dst_address, eth0->src_address, 6); + clib_memcpy (eth0->src_address, hw_if0->hw_address, 6); + + b0->error = node->errors[LISP_CP_LOOKUP_ERROR_ARP_REPLY_TX]; + next0 = LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX; + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, + to_next, + n_left_to_next, pi0, + next0); + } + continue; + } + /* if we have remote mapping for destination already in map-chache add forwarding tunnel directly. If not send a map-request */ di = gid_dictionary_sd_lookup (&lcm->mapping_index_by_gid, &dst, @@ -2859,6 +3025,7 @@ lisp_cp_lookup_inline (vlib_main_t * vm, pkts_mapped++; } + b0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP]; if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { lisp_cp_lookup_trace_t *tr = vlib_add_trace (vm, node, b0, @@ -2871,10 +3038,13 @@ lisp_cp_lookup_inline (vlib_main_t * vm, } gid_address_free (&dst); gid_address_free (&src); + next0 = LISP_CP_LOOKUP_NEXT_DROP; + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, + to_next, + n_left_to_next, pi0, next0); } - vlib_put_next_frame (vm, node, LISP_CP_LOOKUP_NEXT_DROP, - n_left_to_next_drop); + vlib_put_next_frame (vm, node, next_index, n_left_to_next); } vlib_node_increment_counter (vm, node->node_index, LISP_CP_LOOKUP_ERROR_MAP_REQUESTS_SENT, @@ -2926,6 +3096,7 @@ VLIB_REGISTER_NODE (lisp_cp_lookup_ip4_node) = { .next_nodes = { [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop", + [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output", }, }; /* *INDENT-ON* */ @@ -2945,6 +3116,7 @@ VLIB_REGISTER_NODE (lisp_cp_lookup_ip6_node) = { .next_nodes = { [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop", + [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output", }, }; /* *INDENT-ON* */ @@ -2964,6 +3136,7 @@ VLIB_REGISTER_NODE (lisp_cp_lookup_l2_node) = { .next_nodes = { [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop", + [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output", }, }; /* *INDENT-ON* */ @@ -2983,6 +3156,7 @@ VLIB_REGISTER_NODE (lisp_cp_lookup_nsh_node) = { .next_nodes = { [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop", + [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output", }, }; /* *INDENT-ON* */ diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index cb98eb09..feb8cfa4 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -87,6 +87,12 @@ typedef struct miss_packet_type_t type; } miss_packet_t; +typedef struct +{ + u8 mac[6]; + u32 ip4; +} lisp_api_l2_arp_entry_t; + typedef enum { MR_MODE_DST_ONLY = 0, @@ -112,6 +118,12 @@ typedef enum lisp_flags #undef _ } lisp_flags_e; +typedef struct +{ + ip_address_t addr; + u32 bd; +} lisp_l2_arp_key_t; + typedef struct { u32 flags; @@ -338,6 +350,9 @@ int vnet_lisp_rloc_probe_enable_disable (u8 is_enable); int vnet_lisp_map_register_enable_disable (u8 is_enable); u8 vnet_lisp_map_register_state_get (void); u8 vnet_lisp_rloc_probe_state_get (void); +int vnet_lisp_add_del_l2_arp_entry (gid_address_t * key, u8 * mac, u8 is_add); +u32 *vnet_lisp_l2_arp_bds_get (void); +lisp_api_l2_arp_entry_t *vnet_lisp_l2_arp_entries_get_by_bd (u32 bd); map_records_arg_t *parse_map_reply (vlib_buffer_t * b); diff --git a/src/vnet/lisp-cp/gid_dictionary.c b/src/vnet/lisp-cp/gid_dictionary.c index b01bb0e0..80d59faf 100644 --- a/src/vnet/lisp-cp/gid_dictionary.c +++ b/src/vnet/lisp-cp/gid_dictionary.c @@ -138,6 +138,15 @@ gid_dict_foreach_subprefix (gid_dictionary_t * db, gid_address_t * eid, arg); } +void +gid_dict_foreach_l2_arp_entry (gid_dictionary_t * db, void (*cb) + (BVT (clib_bihash_kv) * kvp, void *arg), + void *ht) +{ + gid_l2_arp_table_t *tab = &db->arp_table; + BV (clib_bihash_foreach_key_value_pair) (&tab->arp_lookup_table, cb, ht); +} + static void make_mac_sd_key (BVT (clib_bihash_kv) * kv, u32 vni, u8 src_mac[6], u8 dst_mac[6]) @@ -328,7 +337,30 @@ ip_sd_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t * dst, return GID_LOOKUP_MISS; } -u32 +static void +make_arp_key (BVT (clib_bihash_kv) * kv, u32 bd, ip4_address_t * addr) +{ + kv->key[0] = (u64) bd; + kv->key[1] = (u64) addr->as_u32; + kv->key[2] = (u64) 0; +} + +static u64 +arp_lookup (gid_l2_arp_table_t * db, u32 bd, ip4_address_t * key) +{ + int rv; + BVT (clib_bihash_kv) kv, value; + + make_arp_key (&kv, bd, key); + rv = BV (clib_bihash_search_inline_2) (&db->arp_lookup_table, &kv, &value); + + if (rv == 0) + return value.value; + + return GID_LOOKUP_MISS_L2; +} + +u64 gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key) { switch (gid_address_type (key)) @@ -358,6 +390,9 @@ gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key) break; } break; + case GID_ADDR_ARP: + return arp_lookup (&db->arp_table, gid_address_arp_bd (key), + &gid_address_arp_ip4 (key)); default: clib_warning ("address type %d not supported!", gid_address_type (key)); break; @@ -825,21 +860,49 @@ add_del_sd (gid_dictionary_t * db, u32 vni, source_dest_t * key, u32 value, return ~0; } +static u32 +add_del_arp (gid_l2_arp_table_t * db, u32 bd, ip4_address_t * key, u64 value, + u8 is_add) +{ + BVT (clib_bihash_kv) kv, result; + u32 old_val = ~0; + + make_arp_key (&kv, bd, key); + if (BV (clib_bihash_search) (&db->arp_lookup_table, &kv, &result) == 0) + old_val = result.value; + + if (is_add) + { + kv.value = value; + BV (clib_bihash_add_del) (&db->arp_lookup_table, &kv, 1 /* is_add */ ); + db->count++; + } + else + { + BV (clib_bihash_add_del) (&db->arp_lookup_table, &kv, 0 /* is_add */ ); + db->count--; + } + return old_val; +} + u32 -gid_dictionary_add_del (gid_dictionary_t * db, gid_address_t * key, u32 value, +gid_dictionary_add_del (gid_dictionary_t * db, gid_address_t * key, u64 value, u8 is_add) { switch (gid_address_type (key)) { case GID_ADDR_IP_PREFIX: return add_del_ip (db, gid_address_vni (key), &gid_address_ippref (key), - 0, value, is_add); + 0, (u32) value, is_add); case GID_ADDR_MAC: return add_del_mac (&db->sd_mac_table, gid_address_vni (key), - gid_address_mac (key), 0, value, is_add); + gid_address_mac (key), 0, (u32) value, is_add); case GID_ADDR_SRC_DST: return add_del_sd (db, gid_address_vni (key), &gid_address_sd (key), - value, is_add); + (u32) value, is_add); + case GID_ADDR_ARP: + return add_del_arp (&db->arp_table, gid_address_arp_bd (key), + &gid_address_arp_ip4 (key), value, is_add); default: clib_warning ("address type %d not supported!", gid_address_type (key)); break; @@ -864,12 +927,30 @@ mac_lookup_init (gid_mac_table_t * db) db->mac_lookup_table_size); } +static void +arp_lookup_init (gid_l2_arp_table_t * db) +{ + if (db->arp_lookup_table_nbuckets == 0) + db->arp_lookup_table_nbuckets = ARP_LOOKUP_DEFAULT_HASH_NUM_BUCKETS; + + db->arp_lookup_table_nbuckets = + 1 << max_log2 (db->arp_lookup_table_nbuckets); + + if (db->arp_lookup_table_size == 0) + db->arp_lookup_table_size = ARP_LOOKUP_DEFAULT_HASH_MEMORY_SIZE; + + BV (clib_bihash_init) (&db->arp_lookup_table, "arp lookup table", + db->arp_lookup_table_nbuckets, + db->arp_lookup_table_size); +} + void gid_dictionary_init (gid_dictionary_t * db) { ip4_lookup_init (&db->dst_ip4_table); ip6_lookup_init (&db->dst_ip6_table); mac_lookup_init (&db->sd_mac_table); + arp_lookup_init (&db->arp_table); } /* diff --git a/src/vnet/lisp-cp/gid_dictionary.h b/src/vnet/lisp-cp/gid_dictionary.h index 825e9856..9612fb13 100644 --- a/src/vnet/lisp-cp/gid_dictionary.h +++ b/src/vnet/lisp-cp/gid_dictionary.h @@ -22,6 +22,7 @@ #include #define GID_LOOKUP_MISS ((u32)~0) +#define GID_LOOKUP_MISS_L2 ((u64)~0) /* Default size of the ip4 hash table */ #define IP4_LOOKUP_DEFAULT_HASH_NUM_BUCKETS (64 * 1024) @@ -35,6 +36,10 @@ #define MAC_LOOKUP_DEFAULT_HASH_NUM_BUCKETS (64 * 1024) #define MAC_LOOKUP_DEFAULT_HASH_MEMORY_SIZE (32<<20) +/* Default size of the ARP hash table */ +#define ARP_LOOKUP_DEFAULT_HASH_NUM_BUCKETS (64 * 1024) +#define ARP_LOOKUP_DEFAULT_HASH_MEMORY_SIZE (32<<20) + typedef void (*foreach_subprefix_match_cb_t) (u32, void *); typedef struct @@ -81,6 +86,17 @@ typedef struct gid_mac_table typedef struct { + BVT (clib_bihash) arp_lookup_table; + u32 arp_lookup_table_nbuckets; + uword arp_lookup_table_size; + u64 count; +} gid_l2_arp_table_t; + +typedef struct +{ + /** L2 ARP table */ + gid_l2_arp_table_t arp_table; + /** destination IP LPM ip4 lookup table */ gid_ip4_table_t dst_ip4_table; @@ -99,10 +115,10 @@ typedef struct } gid_dictionary_t; u32 -gid_dictionary_add_del (gid_dictionary_t * db, gid_address_t * key, u32 value, +gid_dictionary_add_del (gid_dictionary_t * db, gid_address_t * key, u64 value, u8 is_add); -u32 gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key); +u64 gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key); u32 gid_dictionary_sd_lookup (gid_dictionary_t * db, gid_address_t * dst, gid_address_t * src); @@ -112,6 +128,11 @@ void gid_dict_foreach_subprefix (gid_dictionary_t * db, gid_address_t * eid, foreach_subprefix_match_cb_t cb, void *arg); +void +gid_dict_foreach_l2_arp_entry (gid_dictionary_t * db, void (*cb) + (BVT (clib_bihash_kv) * kvp, void *arg), + void *ht); + #endif /* VNET_LISP_GPE_GID_DICTIONARY_H_ */ /* diff --git a/src/vnet/lisp-cp/lisp_types.c b/src/vnet/lisp-cp/lisp_types.c index 31a80081..85cefae0 100644 --- a/src/vnet/lisp-cp/lisp_types.c +++ b/src/vnet/lisp-cp/lisp_types.c @@ -256,6 +256,9 @@ format_gid_address (u8 * s, va_list * args) &gid_address_mac (a)); case GID_ADDR_NSH: return format (s, "%U", format_nsh_address, &gid_address_nsh (a)); + case GID_ADDR_ARP: + return format (s, "[%d, %U]", gid_address_arp_bd (a), + format_ip4_address, &gid_address_arp_ip4 (a)); default: clib_warning ("Can't format gid type %d", type); return 0; diff --git a/src/vnet/lisp-cp/lisp_types.h b/src/vnet/lisp-cp/lisp_types.h index a65a479e..f5d2a676 100644 --- a/src/vnet/lisp-cp/lisp_types.h +++ b/src/vnet/lisp-cp/lisp_types.h @@ -90,6 +90,7 @@ typedef enum GID_ADDR_MAC, GID_ADDR_SRC_DST, GID_ADDR_NSH, + GID_ADDR_ARP, GID_ADDR_NO_ADDRESS, GID_ADDR_TYPES } gid_address_type_t; @@ -165,12 +166,22 @@ typedef struct u8 si; } nsh_t; +typedef struct +{ + ip4_address_t addr; + u32 bd; +} lcaf_arp_t; + +#define lcaf_arp_ip4(_a) (_a)->addr +#define lcaf_arp_bd(_a) (_a)->bd + typedef struct { /* the union needs to be at the beginning! */ union { source_dest_t sd; + lcaf_arp_t arp; vni_t uni; }; u8 type; @@ -189,6 +200,7 @@ typedef struct _gid_address_t lcaf_t lcaf; u8 mac[6]; source_dest_t sd; + lcaf_arp_t arp; nsh_t nsh; }; u8 type; @@ -257,6 +269,9 @@ void gid_address_ip_set (gid_address_t * dst, void *src, u8 version); #define gid_address_sd_dst(_a) sd_dst(&gid_address_sd(_a)) #define gid_address_sd_src_type(_a) sd_src_type(&gid_address_sd(_a)) #define gid_address_sd_dst_type(_a) sd_dst_type(&gid_address_sd(_a)) +#define gid_address_arp(_a) (_a)->arp +#define gid_address_arp_ip4(_a) lcaf_arp_ip4(&gid_address_arp (_a)) +#define gid_address_arp_bd(_a) lcaf_arp_bd(&gid_address_arp (_a)) /* 'sub'address functions */ #define foreach_gid_address_type_fcns \ diff --git a/src/vnet/lisp-cp/one.api b/src/vnet/lisp-cp/one.api index 2fa1edf6..7d07cc47 100644 --- a/src/vnet/lisp-cp/one.api +++ b/src/vnet/lisp-cp/one.api @@ -348,6 +348,79 @@ autoreply manual_print manual_endian define one_add_del_remote_mapping vl_api_one_remote_locator_t rlocs[rloc_num]; }; +/** \brief Add/delete L2 ARP entries + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param is_add - add if non-zero; delete otherwise + @param bd - bridge domain + @param mac - MAC address + @param ip4 - IPv4 address +*/ +autoreply define one_add_del_l2_arp_entry +{ + u32 client_index; + u32 context; + u8 is_add; + u8 mac[6]; + u32 bd; + u32 ip4; +}; + +/** \brief Request for L2 ARP entries from specified bridge domain + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param bd - bridge domain +*/ +define one_l2_arp_entries_get +{ + u32 client_index; + u32 context; + u32 bd; +}; + +typeonly manual_print manual_endian define one_l2_arp_entry +{ + u8 mac[6]; + u32 ip4; +}; + +/** \brief Reply with L2 ARP entries from specified bridge domain + @param context - sender context, to match reply w/ request + @param retval - error code + @param count - number of elements in the list + @param vl_api_one_arp_entry_t - list of entries +*/ +manual_print manual_endian define one_l2_arp_entries_get_reply +{ + u32 context; + i32 retval; + u32 count; + vl_api_one_l2_arp_entry_t entries[count]; +}; + +/** \brief Request for list of bridge domains used by L2 ARP table + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ +define one_l2_arp_bd_get +{ + u32 client_index; + u32 context; +}; + +/** \brief Reply with list of bridge domains used by L2 ARP table + @param context - sender context, to match reply w/ request + @param count - number of elements in the list + @param bridge_domains - list of BDs +*/ +manual_print manual_endian define one_l2_arp_bd_get_reply +{ + u32 context; + i32 retval; + u32 count; + u32 bridge_domains[count]; +}; + /** \brief add or delete ONE adjacency adjacency @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request diff --git a/src/vnet/lisp-cp/one_api.c b/src/vnet/lisp-cp/one_api.c index 23549afa..724e58df 100644 --- a/src/vnet/lisp-cp/one_api.c +++ b/src/vnet/lisp-cp/one_api.c @@ -42,6 +42,11 @@ #define vl_api_one_add_del_remote_mapping_t_endian vl_noop_handler #define vl_api_one_add_del_remote_mapping_t_print vl_noop_handler +#define vl_api_one_l2_arp_entry_t_endian vl_noop_handler +#define vl_api_one_l2_arp_entry_t_print vl_noop_handler +#define vl_api_one_add_del_l2_arp_entry vl_noop_handler +#define vl_api_one_l2_arp_bd_get vl_noop_handler + #define vl_typedefs /* define message structures */ #include #undef vl_typedefs @@ -109,6 +114,9 @@ _(SHOW_ONE_STATS_ENABLE_DISABLE, show_one_stats_enable_disable) \ _(ONE_STATS_ENABLE_DISABLE, one_stats_enable_disable) \ _(ONE_STATS_DUMP, one_stats_dump) \ _(ONE_STATS_FLUSH, one_stats_flush) \ +_(ONE_L2_ARP_BD_GET, one_l2_arp_bd_get) \ +_(ONE_L2_ARP_ENTRIES_GET, one_l2_arp_entries_get) \ +_(ONE_ADD_DEL_L2_ARP_ENTRY, one_add_del_l2_arp_entry) \ static locator_t * @@ -1387,6 +1395,80 @@ vl_api_one_stats_dump_t_handler (vl_api_one_stats_dump_t * mp) } } +static void + vl_api_one_add_del_l2_arp_entry_t_handler + (vl_api_one_add_del_l2_arp_entry_t * mp) +{ + vl_api_one_add_del_l2_arp_entry_reply_t *rmp; + int rv = 0; + gid_address_t _arp, *arp = &_arp; + memset (arp, 0, sizeof (*arp)); + + gid_address_type (arp) = GID_ADDR_ARP; + gid_address_arp_bd (arp) = clib_net_to_host_u32 (mp->bd); + + /* vpp keeps ip4 addresses in network byte order */ + clib_memcpy (&gid_address_arp_ip4 (arp), &mp->ip4, 4); + + rv = vnet_lisp_add_del_l2_arp_entry (arp, mp->mac, mp->is_add); + + REPLY_MACRO (VL_API_ONE_ADD_DEL_L2_ARP_ENTRY_REPLY); +} + +static void +vl_api_one_l2_arp_bd_get_t_handler (vl_api_one_l2_arp_bd_get_t * mp) +{ + vl_api_one_l2_arp_bd_get_reply_t *rmp; + int rv = 0; + u32 i = 0; + hash_pair_t *p; + + u32 *bds = vnet_lisp_l2_arp_bds_get (); + u32 size = hash_elts (bds) * sizeof (u32); + + /* *INDENT-OFF* */ + REPLY_MACRO4 (VL_API_ONE_L2_ARP_BD_GET_REPLY, size, + { + rmp->count = clib_host_to_net_u32 (hash_elts (bds)); + hash_foreach_pair (p, bds, + ({ + rmp->bridge_domains[i++] = clib_host_to_net_u32 (p->key); + })); + }); + /* *INDENT-ON* */ + + hash_free (bds); +} + +static void +vl_api_one_l2_arp_entries_get_t_handler (vl_api_one_l2_arp_entries_get_t * mp) +{ + vl_api_one_l2_arp_entries_get_reply_t *rmp; + lisp_api_l2_arp_entry_t *entries = 0, *e; + u32 i = 0; + int rv = 0; + + u32 bd = clib_net_to_host_u32 (mp->bd); + + entries = vnet_lisp_l2_arp_entries_get_by_bd (bd); + u32 size = vec_len (entries) * sizeof (u32); + + /* *INDENT-OFF* */ + REPLY_MACRO4 (VL_API_ONE_L2_ARP_ENTRIES_GET_REPLY, size, + { + rmp->count = clib_host_to_net_u32 (vec_len (entries)); + vec_foreach (e, entries) + { + mac_copy (rmp->entries[i].mac, e->mac); + rmp->entries[i].ip4 = e->ip4; + i++; + } + }); + /* *INDENT-ON* */ + + vec_free (entries); +} + /* * one_api_hookup * Add vpe's API message handlers to the table. diff --git a/src/vnet/lisp-cp/one_cli.c b/src/vnet/lisp-cp/one_cli.c index 109aca2e..db6a6c83 100644 --- a/src/vnet/lisp-cp/one_cli.c +++ b/src/vnet/lisp-cp/one_cli.c @@ -276,6 +276,106 @@ VLIB_CLI_COMMAND (one_eid_table_map_command) = { }; /* *INDENT-ON* */ +static clib_error_t * +lisp_add_del_l2_arp_entry_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + clib_error_t *error = NULL; + int rc = 0; + u8 hw_addr[6], bd = 0; + ip4_address_t ip4; + u32 hw_addr_set = 0, ip_set = 0, is_add = 1; + gid_address_t _arp, *arp = &_arp; + + memset (&ip4, 0, sizeof (ip4)); + memset (hw_addr, 0, sizeof (hw_addr)); + memset (arp, 0, sizeof (*arp)); + + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "mac %U", unformat_mac_address, hw_addr)) + hw_addr_set = 1; + else if (unformat (line_input, "ip %U", unformat_ip4_address, &ip4)) + ip_set = 1; + else if (unformat (line_input, "del")) + is_add = 0; + else if (unformat (line_input, "bd %d", &bd)) + ; + else + { + error = clib_error_return (0, "parse error"); + goto done; + } + } + + if (!ip_set || (!hw_addr_set && is_add)) + { + vlib_cli_output (vm, "expected IP and MAC addresses!"); + return 0; + } + + /* build GID address */ + gid_address_arp_ip4 (arp) = ip4; + gid_address_arp_bd (arp) = bd; + gid_address_type (arp) = GID_ADDR_ARP; + rc = vnet_lisp_add_del_l2_arp_entry (arp, hw_addr, is_add); + if (rc) + clib_warning ("Failed to %s l2 arp entry!", is_add ? "add" : "delete"); + +done: + unformat_free (line_input); + return error; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (one_add_del_l2_arp_entry_command) = { + .path = "one l2 arp", + .short_help = "one l2 arp [del] bd mac ip ", + .function = lisp_add_del_l2_arp_entry_command_fn, +}; +/* *INDENT-ON* */ + +static clib_error_t * +lisp_show_l2_arp_entries_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + u32 *ht = vnet_lisp_l2_arp_bds_get (); + lisp_api_l2_arp_entry_t *entries, *e; + hash_pair_t *p; + + /* *INDENT-OFF* */ + hash_foreach_pair (p, ht, + ({ + entries = vnet_lisp_l2_arp_entries_get_by_bd (p->key); + vlib_cli_output (vm, "Table: %d", p->key); + + vec_foreach (e, entries) + { + vlib_cli_output (vm, "\t%U -> %U", format_ip4_address, &e->ip4, + format_mac_address, e->mac); + } + vec_free (entries); + })); + /* *INDENT-ON* */ + + hash_free (ht); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (one_show_l2_arp_entries_command) = { + .path = "show one l2 arp entries", + .short_help = "Show ONE L2 ARP entries", + .function = lisp_show_l2_arp_entries_command_fn, +}; +/* *INDENT-ON* */ + /** * Handler for add/del remote mapping CLI. * -- cgit 1.2.3-korg From ef2a5bf0a31c9c0a94f9f497cb6353f46073e6ec Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Tue, 30 May 2017 07:14:46 +0200 Subject: LISP: add NSH support Change-Id: I971c110ed126f1a24a963f9d3b88cf8f8c308816 Signed-off-by: Filip Tehlar --- src/tests/vnet/lisp-cp/test_lisp_types.c | 76 ++++++++++++- src/vat/api_format.c | 180 +++++++++++++++++++++++++++++-- src/vnet/lisp-cp/control.c | 139 +++++++++++++++++++++--- src/vnet/lisp-cp/control.h | 4 + src/vnet/lisp-cp/gid_dictionary.c | 79 +++++++++++++- src/vnet/lisp-cp/gid_dictionary.h | 17 +++ src/vnet/lisp-cp/lisp_cp_messages.h | 31 ++++++ src/vnet/lisp-cp/lisp_types.c | 108 ++++++++++++++++--- src/vnet/lisp-cp/lisp_types.h | 10 +- src/vnet/lisp-cp/one.api | 49 +++++++++ src/vnet/lisp-cp/one_api.c | 105 +++++++++++++++++- src/vnet/lisp-cp/one_cli.c | 58 +++++++++- src/vnet/lisp-gpe/interface.c | 8 +- src/vnet/lisp-gpe/lisp_gpe.h | 3 + src/vpp/api/test_client.c | 3 +- 15 files changed, 826 insertions(+), 44 deletions(-) (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/tests/vnet/lisp-cp/test_lisp_types.c b/src/tests/vnet/lisp-cp/test_lisp_types.c index 21575015..7c55a9c1 100644 --- a/src/tests/vnet/lisp-cp/test_lisp_types.c +++ b/src/tests/vnet/lisp-cp/test_lisp_types.c @@ -90,7 +90,7 @@ static clib_error_t * test_gid_parse_ip_pref () { clib_error_t * error = 0; gid_address_t _gid_addr, * gid_addr = &_gid_addr; - gid_address_t _gid_addr_copy, * gid_addr_copy = &_gid_addr_copy; + gid_address_t _gid_addr_copy, * copy = &_gid_addr_copy; u8 data[] = { 0x00, 0x01, /* AFI = IPv4 */ @@ -99,8 +99,8 @@ static clib_error_t * test_gid_parse_ip_pref () u32 len = gid_address_parse (data, gid_addr); _assert (6 == len); - gid_address_copy (gid_addr_copy, gid_addr); - _assert (0 == gid_address_cmp (gid_addr_copy, gid_addr)); + gid_address_copy (copy, gid_addr); + _assert (0 == gid_address_cmp (copy, gid_addr)); done: return error; } @@ -127,6 +127,74 @@ done: return error; } +static clib_error_t * +test_gid_write_nsh (void) +{ + clib_error_t * error = 0; + + u8 * b = clib_mem_alloc(500); + memset(b, 0, 500); + + gid_address_t g = + { + .vni = 0, + .nsh.spi = 0x112233, + .nsh.si = 0x42, + .type = GID_ADDR_NSH, + }; + + u16 len = gid_address_put (b, &g); + + u8 expected[] = + { + 0x40, 0x03, 0x00, 0x00, /* AFI = LCAF*/ + 0x11, 0x00, 0x00, 0x04, /* type = SPI LCAF, length = 4 */ + + /* Service Path ID, Service index */ + 0x11, 0x22, 0x33, 0x42, /* SPI, SI */ + }; + + _assert (sizeof (expected) == len); + _assert (0 == memcmp (expected, b, len)); +done: + clib_mem_free (b); + return error; +} + +static clib_error_t * +test_gid_parse_nsh () +{ + clib_error_t * error = 0; + gid_address_t _gid_addr, * gid_addr = &_gid_addr; + gid_address_t _gid_addr_copy, * copy = &_gid_addr_copy; + + memset (gid_addr, 0, sizeof (gid_addr[0])); + memset (copy, 0, sizeof (copy[0])); + + u8 data[] = + { + 0x40, 0x03, 0x00, 0x00, /* AFI = LCAF*/ + 0x11, 0x00, 0x00, 0x04, /* type = SPI LCAF, length = 4 */ + + /* Service Path ID, Service index */ + 0x55, 0x99, 0x42, 0x09, /* SPI, SI */ + }; + + u32 len = gid_address_parse (data, gid_addr); + _assert (sizeof (data) == len); + gid_address_copy (copy, gid_addr); + _assert (0 == gid_address_cmp (gid_addr, copy)); + _assert (GID_ADDR_NSH == gid_address_type (copy)); + _assert (0 == gid_address_vni (copy)); + _assert (gid_address_nsh_spi (copy) == 0x559942); + _assert (gid_address_nsh_si (copy) == 0x09); + +done: + gid_address_free (copy); + gid_address_free (gid_addr); + return error; +} + static clib_error_t * test_gid_parse_lcaf () { clib_error_t * error = 0; @@ -555,6 +623,8 @@ done: _(gid_parse_ip_pref) \ _(gid_parse_mac) \ _(gid_parse_lcaf) \ + _(gid_parse_nsh) \ + _(gid_write_nsh) \ _(mac_address_write) \ _(gid_address_write) \ _(src_dst_serdes) \ diff --git a/src/vat/api_format.c b/src/vat/api_format.c index f33b4592..766624a0 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -2583,6 +2583,26 @@ static void vec_free (ls_name); } +typedef struct +{ + u32 spi; + u8 si; +} __attribute__ ((__packed__)) lisp_nsh_api_t; + +uword +unformat_nsh_address (unformat_input_t * input, va_list * args) +{ + lisp_nsh_api_t *nsh = va_arg (*args, lisp_nsh_api_t *); + return unformat (input, "SPI:%d SI:%d", &nsh->spi, &nsh->si); +} + +u8 * +format_nsh_address_vat (u8 * s, va_list * args) +{ + nsh_t *a = va_arg (*args, nsh_t *); + return format (s, "SPI:%d SI:%d", clib_net_to_host_u32 (a->spi), a->si); +} + static u8 * format_lisp_flat_eid (u8 * s, va_list * args) { @@ -2598,6 +2618,8 @@ format_lisp_flat_eid (u8 * s, va_list * args) return format (s, "%U/%d", format_ip6_address, eid, eid_len); case 2: return format (s, "%U", format_ethernet_address, eid); + case 3: + return format (s, "%U", format_nsh_address_vat, eid); } return 0; } @@ -2672,13 +2694,26 @@ vl_api_one_eid_table_details_t_handler_json (vl_api_one_eid_table_details_t clib_net_to_host_u32 (mp->locator_set_index)); vat_json_object_add_uint (node, "is_local", mp->is_local ? 1 : 0); - eid = format (0, "%U", format_lisp_eid_vat, - mp->eid_type, - mp->eid, - mp->eid_prefix_len, - mp->seid, mp->seid_prefix_len, mp->is_src_dst); - vec_add1 (eid, 0); - vat_json_object_add_string_copy (node, "eid", eid); + if (mp->eid_type == 3) + { + vat_json_node_t *nsh_json = vat_json_object_add (node, "eid"); + vat_json_init_object (nsh_json); + lisp_nsh_api_t *nsh = (lisp_nsh_api_t *) mp->eid; + vat_json_object_add_uint (nsh_json, "spi", + clib_net_to_host_u32 (nsh->spi)); + vat_json_object_add_uint (nsh_json, "si", nsh->si); + } + else + { + eid = format (0, "%U", format_lisp_eid_vat, + mp->eid_type, + mp->eid, + mp->eid_prefix_len, + mp->seid, mp->seid_prefix_len, mp->is_src_dst); + vec_add1 (eid, 0); + vat_json_object_add_string_copy (node, "eid", eid); + vec_free (eid); + } vat_json_object_add_uint (node, "vni", clib_net_to_host_u32 (mp->vni)); vat_json_object_add_uint (node, "ttl", clib_net_to_host_u32 (mp->ttl)); vat_json_object_add_uint (node, "authoritative", (mp->authoritative)); @@ -2689,7 +2724,6 @@ vl_api_one_eid_table_details_t_handler_json (vl_api_one_eid_table_details_t clib_net_to_host_u16 (mp->key_id)); vat_json_object_add_string_copy (node, "key", mp->key); } - vec_free (eid); } static void @@ -3665,6 +3699,52 @@ static void vam->result_ready = 1; } +static void + vl_api_show_one_nsh_mapping_reply_t_handler + (vl_api_show_one_nsh_mapping_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + if (0 <= retval) + { + print (vam->ofp, "%-20s%-16s", + mp->is_set ? "set" : "not-set", + mp->is_set ? (char *) mp->locator_set_name : ""); + } + + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_show_one_nsh_mapping_reply_t_handler_json + (vl_api_show_one_nsh_mapping_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + u8 *status = 0; + + status = format (0, "%s", mp->is_set ? "yes" : "no"); + vec_add1 (status, 0); + + vat_json_init_object (&node); + vat_json_object_add_string_copy (&node, "is_set", status); + if (mp->is_set) + { + vat_json_object_add_string_copy (&node, "locator_set", + mp->locator_set_name); + } + + vec_free (status); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + static void vl_api_show_one_pitr_reply_t_handler (vl_api_show_one_pitr_reply_t * mp) { @@ -4672,6 +4752,7 @@ _(ONE_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY, \ one_add_del_map_request_itr_rlocs_reply) \ _(ONE_GET_MAP_REQUEST_ITR_RLOCS_REPLY, \ one_get_map_request_itr_rlocs_reply) \ +_(SHOW_ONE_NSH_MAPPING_REPLY, show_one_nsh_mapping_reply) \ _(SHOW_ONE_PITR_REPLY, show_one_pitr_reply) \ _(SHOW_ONE_USE_PETR_REPLY, show_one_use_petr_reply) \ _(SHOW_ONE_MAP_REQUEST_MODE_REPLY, show_one_map_request_mode_reply) \ @@ -14044,6 +14125,12 @@ unformat_lisp_eid_vat (unformat_input_t * input, va_list * args) { a->type = 2; /* mac type */ } + else if (unformat (input, "%U", unformat_nsh_address, a->addr)) + { + a->type = 3; /* NSH type */ + lisp_nsh_api_t *nsh = (lisp_nsh_api_t *) a->addr; + nsh->spi = clib_host_to_net_u32 (nsh->spi); + } else { return 0; @@ -14068,6 +14155,8 @@ lisp_eid_size_vat (u8 type) return 16; case 2: return 6; + case 3: + return 5; } return 0; } @@ -15166,6 +15255,50 @@ api_one_pitr_set_locator_set (vat_main_t * vam) #define api_lisp_pitr_set_locator_set api_one_pitr_set_locator_set +static int +api_one_nsh_set_locator_set (vat_main_t * vam) +{ + u8 ls_name_set = 0; + unformat_input_t *input = vam->input; + vl_api_one_nsh_set_locator_set_t *mp; + u8 is_add = 1; + u8 *ls_name = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + is_add = 0; + else if (unformat (input, "ls %s", &ls_name)) + ls_name_set = 1; + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!ls_name_set && is_add) + { + errmsg ("locator-set name not set!"); + return -99; + } + + M (ONE_NSH_SET_LOCATOR_SET, mp); + + mp->is_add = is_add; + clib_memcpy (mp->ls_name, ls_name, vec_len (ls_name)); + vec_free (ls_name); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + static int api_show_one_pitr (vat_main_t * vam) { @@ -15245,6 +15378,26 @@ api_one_use_petr (vat_main_t * vam) #define api_lisp_use_petr api_one_use_petr +static int +api_show_one_nsh_mapping (vat_main_t * vam) +{ + vl_api_show_one_use_petr_t *mp; + int ret; + + if (!vam->json_output) + { + print (vam->ofp, "%=20s", "local ONE NSH mapping:"); + } + + M (SHOW_ONE_NSH_MAPPING, mp); + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + static int api_show_one_use_petr (vat_main_t * vam) { @@ -16031,6 +16184,7 @@ api_one_eid_table_dump (vat_main_t * vam) u32 prefix_length = ~0, t, vni = 0; u8 filter = 0; int ret; + lisp_nsh_api_t nsh; while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) { @@ -16051,6 +16205,11 @@ api_one_eid_table_dump (vat_main_t * vam) eid_set = 1; eid_type = 2; } + else if (unformat (i, "eid %U", unformat_nsh_address, &nsh)) + { + eid_set = 1; + eid_type = 3; + } else if (unformat (i, "vni %d", &t)) { vni = t; @@ -16097,6 +16256,9 @@ api_one_eid_table_dump (vat_main_t * vam) case 2: clib_memcpy (mp->eid, mac, sizeof (mac)); break; + case 3: + clib_memcpy (mp->eid, &nsh, sizeof (nsh)); + break; default: errmsg ("unknown EID type %d!", eid_type); return -99; @@ -19423,12 +19585,14 @@ _(one_eid_table_map_dump, "l2|l3") \ _(one_map_resolver_dump, "") \ _(one_map_server_dump, "") \ _(one_adjacencies_get, "vni ") \ +_(one_nsh_set_locator_set, "[del] ls ") \ _(show_one_rloc_probe_state, "") \ _(show_one_map_register_state, "") \ _(show_one_status, "") \ _(one_stats_dump, "") \ _(one_stats_flush, "") \ _(one_get_map_request_itr_rlocs, "") \ +_(show_one_nsh_mapping, "") \ _(show_one_pitr, "") \ _(show_one_use_petr, "") \ _(show_one_map_request_mode, "") \ diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index 19bbd618..db78678d 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -28,6 +28,8 @@ #include #include +#define MAX_VALUE_U24 0xffffff + lisp_cp_main_t lisp_control_main; u8 *format_lisp_cp_input_trace (u8 * s, va_list * args); @@ -697,6 +699,20 @@ vnet_lisp_map_cache_add_del (vnet_lisp_add_del_mapping_args_t * a, mapping_t *m, *old_map; u32 **eid_indexes; + if (gid_address_type (&a->eid) == GID_ADDR_NSH) + { + if (gid_address_vni (&a->eid) != 0) + { + clib_warning ("Supported only default VNI for NSH!"); + return VNET_API_ERROR_INVALID_ARGUMENT; + } + if (gid_address_nsh_spi (&a->eid) > MAX_VALUE_U24) + { + clib_warning ("SPI is greater than 24bit!"); + return VNET_API_ERROR_INVALID_ARGUMENT; + } + } + mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->eid); old_map = mi != ~0 ? pool_elt_at_index (lcm->mapping_pool, mi) : 0; if (a->is_add) @@ -812,7 +828,7 @@ vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a, else if (GID_ADDR_MAC == type) dp_table = hash_get (lcm->bd_id_by_vni, vni); - if (!dp_table) + if (!dp_table && GID_ADDR_NSH != type) { clib_warning ("vni %d not associated to a %s!", vni, GID_ADDR_IP_PREFIX == type ? "vrf" : "bd"); @@ -1329,8 +1345,23 @@ vnet_lisp_add_del_adjacency (vnet_lisp_add_del_adjacency_args_t * a) { /* check if source eid has an associated mapping. If pitr mode is on, * just use the pitr's mapping */ - local_mi = lcm->lisp_pitr ? lcm->pitr_map_index : - gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->leid); + if (lcm->lisp_pitr) + local_mi = lcm->pitr_map_index; + else + { + if (gid_address_type (&a->reid) == GID_ADDR_NSH) + { + if (lcm->nsh_map_index == ~0) + local_mi = GID_LOOKUP_MISS; + else + local_mi = lcm->nsh_map_index; + } + else + { + local_mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, + &a->leid); + } + } if (GID_LOOKUP_MISS == local_mi) { @@ -1370,6 +1401,57 @@ vnet_lisp_set_map_request_mode (u8 mode) return 0; } +int +vnet_lisp_nsh_set_locator_set (u8 * locator_set_name, u8 is_add) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); + u32 locator_set_index = ~0; + mapping_t *m; + uword *p; + + if (vnet_lisp_enable_disable_status () == 0) + { + clib_warning ("LISP is disabled!"); + return VNET_API_ERROR_LISP_DISABLED; + } + + if (is_add) + { + if (lcm->nsh_map_index == (u32) ~ 0) + { + p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name); + if (!p) + { + clib_warning ("locator-set %v doesn't exist", locator_set_name); + return -1; + } + locator_set_index = p[0]; + + pool_get (lcm->mapping_pool, m); + memset (m, 0, sizeof *m); + m->locator_set_index = locator_set_index; + m->local = 1; + m->nsh_set = 1; + lcm->nsh_map_index = m - lcm->mapping_pool; + + if (~0 == vnet_lisp_gpe_add_nsh_iface (lgm)) + return -1; + } + } + else + { + if (lcm->nsh_map_index != (u32) ~ 0) + { + /* remove NSH mapping */ + pool_put_index (lcm->mapping_pool, lcm->nsh_map_index); + lcm->nsh_map_index = ~0; + vnet_lisp_gpe_del_nsh_iface (lgm); + } + } + return 0; +} + int vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add) { @@ -2667,7 +2749,7 @@ _send_encapsulated_map_request (lisp_cp_main_t * lcm, } /* get locator-set for seid */ - if (!lcm->lisp_pitr) + if (!lcm->lisp_pitr && gid_address_type (deid) != GID_ADDR_NSH) { map_index = gid_dictionary_lookup (&lcm->mapping_index_by_gid, seid); if (map_index == ~0) @@ -2690,9 +2772,24 @@ _send_encapsulated_map_request (lisp_cp_main_t * lcm, } else { - map_index = lcm->pitr_map_index; - map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index); - ls_index = map->locator_set_index; + if (lcm->lisp_pitr) + { + map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index); + ls_index = map->locator_set_index; + } + else + { + if (lcm->nsh_map_index == (u32) ~ 0) + { + clib_warning ("No locator-set defined for NSH!"); + return -1; + } + else + { + map = pool_elt_at_index (lcm->mapping_pool, lcm->nsh_map_index); + ls_index = map->locator_set_index; + } + } } /* overwrite locator set if map-request itr-rlocs configured */ @@ -2843,6 +2940,7 @@ get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b, gid_address_t * src, gid_address_t * dst, u16 type) { + ethernet_header_t *eh; u32 vni = 0; memset (src, 0, sizeof (*src)); @@ -2873,7 +2971,6 @@ get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b, } else if (LISP_AFI_MAC == type) { - ethernet_header_t *eh; ethernet_arp_header_t *ah; eh = vlib_buffer_get_current (b); @@ -2906,8 +3003,19 @@ get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b, } else if (LISP_AFI_LCAF == type) { - /* Eventually extend this to support NSH and other */ - ASSERT (0); + lisp_nsh_hdr_t *nh; + eh = vlib_buffer_get_current (b); + + if (clib_net_to_host_u16 (eh->type) == ETHERNET_TYPE_NSH) + { + nh = (lisp_nsh_hdr_t *) (((u8 *) eh) + sizeof (*eh)); + u32 spi = clib_net_to_host_u32 (nh->spi_si << 8); + u8 si = (u8) clib_net_to_host_u32 (nh->spi_si); + gid_address_nsh_spi (dst) = spi; + gid_address_nsh_si (dst) = si; + + gid_address_type (dst) = GID_ADDR_NSH; + } } } @@ -3009,8 +3117,14 @@ lisp_cp_lookup_inline (vlib_main_t * vm, } else { - si = gid_dictionary_lookup (&lcm->mapping_index_by_gid, - &src); + if (GID_ADDR_NSH != gid_address_type (&dst)) + { + si = gid_dictionary_lookup (&lcm->mapping_index_by_gid, + &src); + } + else + si = lcm->nsh_map_index; + if (~0 != si) { dp_add_fwd_entry_from_mt (si, di); @@ -3862,6 +3976,7 @@ lisp_cp_init (vlib_main_t * vm) u64 now = clib_cpu_time_now (); timing_wheel_init (&lcm->wheel, now, vm->clib_time.clocks_per_second); + lcm->nsh_map_index = ~0; return 0; } diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index feb8cfa4..ad90b526 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -211,6 +211,9 @@ typedef struct /* LISP PITR mode */ u8 lisp_pitr; + /* mapping index for NSH */ + u32 nsh_map_index; + /* map request mode */ u8 map_request_mode; @@ -353,6 +356,7 @@ u8 vnet_lisp_rloc_probe_state_get (void); int vnet_lisp_add_del_l2_arp_entry (gid_address_t * key, u8 * mac, u8 is_add); u32 *vnet_lisp_l2_arp_bds_get (void); lisp_api_l2_arp_entry_t *vnet_lisp_l2_arp_entries_get_by_bd (u32 bd); +int vnet_lisp_nsh_set_locator_set (u8 * locator_set_name, u8 is_add); map_records_arg_t *parse_map_reply (vlib_buffer_t * b); diff --git a/src/vnet/lisp-cp/gid_dictionary.c b/src/vnet/lisp-cp/gid_dictionary.c index 80d59faf..cf9a741a 100644 --- a/src/vnet/lisp-cp/gid_dictionary.c +++ b/src/vnet/lisp-cp/gid_dictionary.c @@ -345,6 +345,14 @@ make_arp_key (BVT (clib_bihash_kv) * kv, u32 bd, ip4_address_t * addr) kv->key[2] = (u64) 0; } +static void +make_nsh_key (BVT (clib_bihash_kv) * kv, u32 vni, u32 spi, u8 si) +{ + kv->key[0] = (u64) vni; + kv->key[1] = (u64) spi; + kv->key[2] = (u64) si; +} + static u64 arp_lookup (gid_l2_arp_table_t * db, u32 bd, ip4_address_t * key) { @@ -360,6 +368,21 @@ arp_lookup (gid_l2_arp_table_t * db, u32 bd, ip4_address_t * key) return GID_LOOKUP_MISS_L2; } +static u32 +nsh_lookup (gid_nsh_table_t * db, u32 vni, u32 spi, u8 si) +{ + int rv; + BVT (clib_bihash_kv) kv, value; + + make_nsh_key (&kv, vni, spi, si); + rv = BV (clib_bihash_search_inline_2) (&db->nsh_lookup_table, &kv, &value); + + if (rv == 0) + return value.value; + + return GID_LOOKUP_MISS; +} + u64 gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key) { @@ -393,6 +416,9 @@ gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key) case GID_ADDR_ARP: return arp_lookup (&db->arp_table, gid_address_arp_bd (key), &gid_address_arp_ip4 (key)); + case GID_ADDR_NSH: + return nsh_lookup (&db->nsh_table, gid_address_vni (key), + gid_address_nsh_spi (key), gid_address_nsh_si (key)); default: clib_warning ("address type %d not supported!", gid_address_type (key)); break; @@ -432,6 +458,9 @@ gid_dictionary_sd_lookup (gid_dictionary_t * db, gid_address_t * dst, break; } break; + case GID_ADDR_NSH: + return gid_dictionary_lookup (db, dst); + break; default: clib_warning ("address type %d not supported!", gid_address_type (dst)); break; @@ -860,7 +889,7 @@ add_del_sd (gid_dictionary_t * db, u32 vni, source_dest_t * key, u32 value, return ~0; } -static u32 +static u64 add_del_arp (gid_l2_arp_table_t * db, u32 bd, ip4_address_t * key, u64 value, u8 is_add) { @@ -885,6 +914,31 @@ add_del_arp (gid_l2_arp_table_t * db, u32 bd, ip4_address_t * key, u64 value, return old_val; } +static u32 +add_del_nsh (gid_nsh_table_t * db, u32 vni, u32 spi, u8 si, u32 value, + u8 is_add) +{ + BVT (clib_bihash_kv) kv, result; + u32 old_val = ~0; + + make_nsh_key (&kv, vni, spi, si); + if (BV (clib_bihash_search) (&db->nsh_lookup_table, &kv, &result) == 0) + old_val = result.value; + + if (is_add) + { + kv.value = value; + BV (clib_bihash_add_del) (&db->nsh_lookup_table, &kv, 1 /* is_add */ ); + db->count++; + } + else + { + BV (clib_bihash_add_del) (&db->nsh_lookup_table, &kv, 0 /* is_add */ ); + db->count--; + } + return old_val; +} + u32 gid_dictionary_add_del (gid_dictionary_t * db, gid_address_t * key, u64 value, u8 is_add) @@ -903,6 +957,11 @@ gid_dictionary_add_del (gid_dictionary_t * db, gid_address_t * key, u64 value, case GID_ADDR_ARP: return add_del_arp (&db->arp_table, gid_address_arp_bd (key), &gid_address_arp_ip4 (key), value, is_add); + case GID_ADDR_NSH: + return add_del_nsh (&db->nsh_table, gid_address_vni (key), + gid_address_nsh_spi (key), gid_address_nsh_si (key), + value, is_add); + default: clib_warning ("address type %d not supported!", gid_address_type (key)); break; @@ -944,6 +1003,23 @@ arp_lookup_init (gid_l2_arp_table_t * db) db->arp_lookup_table_size); } +static void +nsh_lookup_init (gid_nsh_table_t * db) +{ + if (db->nsh_lookup_table_nbuckets == 0) + db->nsh_lookup_table_nbuckets = MAC_LOOKUP_DEFAULT_HASH_NUM_BUCKETS; + + db->nsh_lookup_table_nbuckets = + 1 << max_log2 (db->nsh_lookup_table_nbuckets); + + if (db->nsh_lookup_table_size == 0) + db->nsh_lookup_table_size = MAC_LOOKUP_DEFAULT_HASH_MEMORY_SIZE; + + BV (clib_bihash_init) (&db->nsh_lookup_table, "nsh lookup table", + db->nsh_lookup_table_nbuckets, + db->nsh_lookup_table_size); +} + void gid_dictionary_init (gid_dictionary_t * db) { @@ -951,6 +1027,7 @@ gid_dictionary_init (gid_dictionary_t * db) ip6_lookup_init (&db->dst_ip6_table); mac_lookup_init (&db->sd_mac_table); arp_lookup_init (&db->arp_table); + nsh_lookup_init (&db->nsh_table); } /* diff --git a/src/vnet/lisp-cp/gid_dictionary.h b/src/vnet/lisp-cp/gid_dictionary.h index 9612fb13..51806bd6 100644 --- a/src/vnet/lisp-cp/gid_dictionary.h +++ b/src/vnet/lisp-cp/gid_dictionary.h @@ -40,6 +40,10 @@ #define ARP_LOOKUP_DEFAULT_HASH_NUM_BUCKETS (64 * 1024) #define ARP_LOOKUP_DEFAULT_HASH_MEMORY_SIZE (32<<20) +/* Default size of the NSH hash table */ +#define NSH_LOOKUP_DEFAULT_HASH_NUM_BUCKETS (64 * 1024) +#define NSH_LOOKUP_DEFAULT_HASH_MEMORY_SIZE (32<<20) + typedef void (*foreach_subprefix_match_cb_t) (u32, void *); typedef struct @@ -84,6 +88,16 @@ typedef struct gid_mac_table u64 count; } gid_mac_table_t; +typedef struct gid_nsh_table +{ + BVT (clib_bihash) nsh_lookup_table; + + /* nsh lookup table config parameters */ + u32 nsh_lookup_table_nbuckets; + uword nsh_lookup_table_size; + u64 count; +} gid_nsh_table_t; + typedef struct { BVT (clib_bihash) arp_lookup_table; @@ -97,6 +111,9 @@ typedef struct /** L2 ARP table */ gid_l2_arp_table_t arp_table; + /** NSH lookup table */ + gid_nsh_table_t nsh_table; + /** destination IP LPM ip4 lookup table */ gid_ip4_table_t dst_ip4_table; diff --git a/src/vnet/lisp-cp/lisp_cp_messages.h b/src/vnet/lisp-cp/lisp_cp_messages.h index 278f60e1..69510a0e 100644 --- a/src/vnet/lisp-cp/lisp_cp_messages.h +++ b/src/vnet/lisp-cp/lisp_cp_messages.h @@ -473,6 +473,22 @@ typedef struct _lcaf_src_dst_hdr_t #define LCAF_SD_SRC_ML(_h) (_h)->src_mask_len #define LCAF_SD_DST_ML(_h) (_h)->dst_mask_len +/* + * SPI LCAF + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Service Path ID | Service index | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +typedef struct _lcaf_spi_hdr_t +{ + u32 spi_si; +} __attribute__ ((__packed__)) lcaf_spi_hdr_t; + +#define LCAF_SPI_SI(_h) (_h)->spi_si + /* * The Map-Register message format is: * @@ -602,6 +618,21 @@ typedef struct #define MNOTIFY_AUTH_DATA_LEN(h_) (MREG_HDR_CAST(h_))->auth_data_len #define MNOTIFY_DATA(h_) (MREG_HDR_CAST(h_))->data +/* + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |Ver|O|C|R|R|R|R|R|R| Length | MD type=0x1 | Next Protocol | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Service Path Identifer | Service Index | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +typedef struct +{ + u32 header; + u32 spi_si; +} __attribute__ ((__packed__)) lisp_nsh_hdr_t; + #endif /* VNET_LISP_GPE_LISP_CP_MESSAGES_H_ */ /* diff --git a/src/vnet/lisp-cp/lisp_types.c b/src/vnet/lisp-cp/lisp_types.c index 85cefae0..e50c3aa1 100644 --- a/src/vnet/lisp-cp/lisp_types.c +++ b/src/vnet/lisp-cp/lisp_types.c @@ -31,16 +31,28 @@ typedef int (*cmp_fct) (void *, void *); size_to_write_fct size_to_write_fcts[GID_ADDR_TYPES] = { ip_prefix_size_to_write, lcaf_size_to_write, mac_size_to_write, - sd_size_to_write, nsh_size_to_write + sd_size_to_write, nsh_size_to_write, 0 /* arp */ , no_addr_size_to_write }; + serdes_fct write_fcts[GID_ADDR_TYPES] = - { ip_prefix_write, lcaf_write, mac_write, sd_write, nsh_write }; + { ip_prefix_write, lcaf_write, mac_write, sd_write, nsh_write, 0 /* arp */ , + no_addr_write +}; + cast_fct cast_fcts[GID_ADDR_TYPES] = - { ip_prefix_cast, lcaf_cast, mac_cast, sd_cast, nsh_cast }; + { ip_prefix_cast, lcaf_cast, mac_cast, sd_cast, nsh_cast, 0 /* arp */ , + no_addr_cast +}; + addr_len_fct addr_len_fcts[GID_ADDR_TYPES] = - { ip_prefix_length, lcaf_length, mac_length, sd_length, nsh_length }; + { ip_prefix_length, lcaf_length, mac_length, sd_length, nsh_length, + 0 /* arp */ , no_addr_length +}; + copy_fct copy_fcts[GID_ADDR_TYPES] = - { ip_prefix_copy, lcaf_copy, mac_copy, sd_copy, nsh_copy }; + { ip_prefix_copy, lcaf_copy, mac_copy, sd_copy, nsh_copy, 0 /* arp */ , + no_addr_copy +}; #define foreach_lcaf_type \ _(1, no_addr) \ @@ -55,7 +67,12 @@ copy_fct copy_fcts[GID_ADDR_TYPES] = _(0, NULL) \ _(0, NULL) \ _(0, NULL) \ - _(1, sd) + _(1, sd) \ + _(0, NULL) \ + _(0, NULL) \ + _(0, NULL) \ + _(0, NULL) \ + _(1, nsh) #define _(cond, name) \ u16 name ## _write (u8 * p, void * a); \ @@ -254,11 +271,12 @@ format_gid_address (u8 * s, va_list * args) case GID_ADDR_MAC: return format (s, "[%d] %U", gid_address_vni (a), format_mac_address, &gid_address_mac (a)); - case GID_ADDR_NSH: - return format (s, "%U", format_nsh_address, &gid_address_nsh (a)); case GID_ADDR_ARP: return format (s, "[%d, %U]", gid_address_arp_bd (a), format_ip4_address, &gid_address_arp_ip4 (a)); + case GID_ADDR_NSH: + return format (s, "%U", format_nsh_address, &gid_address_nsh (a)); + default: clib_warning ("Can't format gid type %d", type); return 0; @@ -287,7 +305,7 @@ unformat_fid_address (unformat_input_t * i, va_list * args) else if (unformat (i, "%U", unformat_nsh_address, &nsh)) { fid_addr_type (a) = FID_ADDR_NSH; - nsh_copy (&fid_addr_nsh (a), mac); + nsh_copy (&fid_addr_nsh (a), &nsh); } else return 0; @@ -673,6 +691,38 @@ do { \ dst += _sum; \ } while (0); +void +nsh_free (void *a) +{ + /* nothing to do */ +} + +u16 +nsh_parse (u8 * p, void *a) +{ + lcaf_spi_hdr_t *h = (lcaf_spi_hdr_t *) p; + gid_address_t *g = a; + + gid_address_type (g) = GID_ADDR_NSH; + gid_address_nsh_spi (g) = clib_net_to_host_u32 (LCAF_SPI_SI (h)) >> 8; + gid_address_nsh_si (g) = (u8) clib_net_to_host_u32 (LCAF_SPI_SI (h)); + + return sizeof (lcaf_spi_hdr_t); +} + +int +nsh_cmp (void *a1, void *a2) +{ + nsh_t *n1 = a1; + nsh_t *n2 = a2; + + if (n1->spi != n2->spi) + return 1; + if (n1->si != n2->si) + return 1; + return 0; +} + u16 sd_parse (u8 * p, void *a) { @@ -1094,6 +1144,12 @@ mac_cast (gid_address_t * a) return &gid_address_mac (a); } +void * +no_addr_cast (gid_address_t * a) +{ + return (void *) a; +} + void * sd_cast (gid_address_t * a) { @@ -1227,8 +1283,33 @@ sd_write (u8 * p, void *a) u16 nsh_write (u8 * p, void *a) { - clib_warning ("not done"); - return 0; + lcaf_spi_hdr_t spi; + lcaf_hdr_t lcaf; + gid_address_t *g = a; + u16 size = 0; + + ASSERT (gid_address_type (g) == GID_ADDR_NSH); + + memset (&lcaf, 0, sizeof (lcaf)); + memset (&spi, 0, sizeof (spi)); + + LCAF_TYPE (&lcaf) = LCAF_NSH; + LCAF_LENGTH (&lcaf) = clib_host_to_net_u16 (sizeof (lcaf_spi_hdr_t)); + + u32 s = clib_host_to_net_u32 (gid_address_nsh_spi (g) << 8 | + gid_address_nsh_si (g)); + LCAF_SPI_SI (&spi) = s; + + *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF); + size += sizeof (u16); + + clib_memcpy (p + size, &lcaf, sizeof (lcaf)); + size += sizeof (lcaf); + + clib_memcpy (p + size, &spi, sizeof (spi)); + size += sizeof (spi); + + return size; } u16 @@ -1354,7 +1435,7 @@ mac_size_to_write (void *a) u16 nsh_size_to_write (void *a) { - return sizeof (u16) + 4; + return sizeof (u16) + sizeof (lcaf_hdr_t) + sizeof (lcaf_spi_hdr_t); } u8 @@ -1581,6 +1662,9 @@ gid_address_cmp (gid_address_t * a1, gid_address_t * a2) case GID_ADDR_SRC_DST: cmp = sd_cmp (&gid_address_sd (a1), &gid_address_sd (a2)); break; + case GID_ADDR_NSH: + cmp = nsh_cmp (&gid_address_nsh (a1), &gid_address_nsh (a2)); + break; default: break; } diff --git a/src/vnet/lisp-cp/lisp_types.h b/src/vnet/lisp-cp/lisp_types.h index f5d2a676..b7ad0f27 100644 --- a/src/vnet/lisp-cp/lisp_types.h +++ b/src/vnet/lisp-cp/lisp_types.h @@ -102,6 +102,7 @@ typedef enum LCAF_AFI_LIST_TYPE, LCAF_INSTANCE_ID, LCAF_SOURCE_DEST = 12, + LCAF_NSH = 17, LCAF_TYPES } lcaf_type_t; @@ -166,6 +167,9 @@ typedef struct u8 si; } nsh_t; +#define nsh_spi(_a) (_a)->spi +#define nsh_si(_a) (_a)->si + typedef struct { ip4_address_t addr; @@ -258,6 +262,8 @@ void gid_address_ip_set (gid_address_t * dst, void *src, u8 version); #define gid_address_lcaf(_a) (_a)->lcaf #define gid_address_mac(_a) (_a)->mac #define gid_address_nsh(_a) (_a)->nsh +#define gid_address_nsh_spi(_a) nsh_spi(&gid_address_nsh(_a)) +#define gid_address_nsh_si(_a) nsh_si(&gid_address_nsh(_a)) #define gid_address_vni(_a) (_a)->vni #define gid_address_vni_mask(_a) (_a)->vni_mask #define gid_address_sd_dst_ippref(_a) sd_dst_ippref(&(_a)->sd) @@ -275,6 +281,7 @@ void gid_address_ip_set (gid_address_t * dst, void *src, u8 version); /* 'sub'address functions */ #define foreach_gid_address_type_fcns \ + _(no_addr) \ _(ip_prefix) \ _(lcaf) \ _(mac) \ @@ -350,7 +357,8 @@ typedef struct /* valid only for remote mappings */ u8 is_static:1; u8 pitr_set:1; - u8 rsvd:4; + u8 nsh_set:1; + u8 rsvd:3; u8 *key; diff --git a/src/vnet/lisp-cp/one.api b/src/vnet/lisp-cp/one.api index 7d07cc47..31811a34 100644 --- a/src/vnet/lisp-cp/one.api +++ b/src/vnet/lisp-cp/one.api @@ -146,6 +146,20 @@ autoreply define one_enable_disable u8 is_en; }; +/** \brief configure or delete ONE NSH mapping + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param ls_name - locator set name + @param is_add - add locator set if non-zero; delete otherwise +*/ +autoreply define one_nsh_set_locator_set +{ + u32 client_index; + u32 context; + u8 is_add; + u8 ls_name[64]; +}; + /** \brief configure or disable ONE PITR node @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @@ -325,6 +339,12 @@ typeonly manual_endian manual_print define one_remote_locator 0 : ipv4 1 : ipv6 2 : mac + 3 : NSH : both information (service path ID and service index) are + encoded in 'eid' field in a following way: + + |4 B |1 B | + ----------- + |SPI | SI | @param deid - dst EID @param seid - src EID, valid only if is_src_dst is enabled @param rloc_num - number of remote locators @@ -596,6 +616,12 @@ define one_eid_table_details 0: EID is IPv4 1: EID is IPv6 2: EID is ethernet address + 3 : NSH : both information (service path ID and service index) are + encoded in 'eid' field in a following way: + + |4 B |1 B | + ----------- + |SPI | SI | @param eid - endpoint identifier @param filter - filter type; Support values: @@ -787,6 +813,29 @@ define one_get_map_request_itr_rlocs_reply u8 locator_set_name[64]; }; +/** \brief Request for ONE NSH mapping + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ +define show_one_nsh_mapping +{ + u32 client_index; + u32 context; +}; + +/** \brief Reply for ONE NSH mapping + @param context - sender context, to match reply w/ request + @param is_set - is ONE NSH mapping set + @param locator_set_name - name of the locator_set if NSH mapping is set +*/ +define show_one_nsh_mapping_reply +{ + u32 context; + i32 retval; + u8 is_set; + u8 locator_set_name[64]; +}; + /** \brief Request for ONE PITR status @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request diff --git a/src/vnet/lisp-cp/one_api.c b/src/vnet/lisp-cp/one_api.c index 724e58df..18235fa4 100644 --- a/src/vnet/lisp-cp/one_api.c +++ b/src/vnet/lisp-cp/one_api.c @@ -90,6 +90,7 @@ _(ONE_MAP_REGISTER_ENABLE_DISABLE, one_map_register_enable_disable) \ _(ONE_ADD_DEL_REMOTE_MAPPING, one_add_del_remote_mapping) \ _(ONE_ADD_DEL_ADJACENCY, one_add_del_adjacency) \ _(ONE_PITR_SET_LOCATOR_SET, one_pitr_set_locator_set) \ +_(ONE_NSH_SET_LOCATOR_SET, one_nsh_set_locator_set) \ _(ONE_MAP_REQUEST_MODE, one_map_request_mode) \ _(ONE_EID_TABLE_ADD_DEL_MAP, one_eid_table_add_del_map) \ _(ONE_LOCATOR_SET_DUMP, one_locator_set_dump) \ @@ -100,6 +101,7 @@ _(ONE_MAP_SERVER_DUMP, one_map_server_dump) \ _(ONE_EID_TABLE_MAP_DUMP, one_eid_table_map_dump) \ _(ONE_EID_TABLE_VNI_DUMP, one_eid_table_vni_dump) \ _(ONE_ADJACENCIES_GET, one_adjacencies_get) \ +_(SHOW_ONE_NSH_MAPPING, show_one_nsh_mapping) \ _(SHOW_ONE_RLOC_PROBE_STATE, show_one_rloc_probe_state) \ _(SHOW_ONE_MAP_REGISTER_STATE, show_one_map_register_state) \ _(SHOW_ONE_STATUS, show_one_status) \ @@ -225,10 +227,18 @@ vl_api_one_add_del_locator_t_handler (vl_api_one_add_del_locator_t * mp) REPLY_MACRO (VL_API_ONE_ADD_DEL_LOCATOR_REPLY); } +typedef struct +{ + u32 spi; + u8 si; +} __attribute__ ((__packed__)) lisp_nsh_api_t; + static int unformat_one_eid_api (gid_address_t * dst, u32 vni, u8 type, void *src, u8 len) { + lisp_nsh_api_t *nsh; + switch (type) { case 0: /* ipv4 */ @@ -247,6 +257,12 @@ unformat_one_eid_api (gid_address_t * dst, u32 vni, u8 type, void *src, gid_address_type (dst) = GID_ADDR_MAC; clib_memcpy (&gid_address_mac (dst), src, 6); break; + case 3: /* NSH */ + gid_address_type (dst) = GID_ADDR_NSH; + nsh = src; + gid_address_nsh_spi (dst) = clib_net_to_host_u32 (nsh->spi); + gid_address_nsh_si (dst) = nsh->si; + break; default: /* unknown type */ return VNET_API_ERROR_INVALID_VALUE; @@ -276,6 +292,12 @@ vl_api_one_add_del_local_eid_t_handler (vl_api_one_add_del_local_eid_t * mp) if (rv) goto out; + if (gid_address_type (eid) == GID_ADDR_NSH) + { + rv = VNET_API_ERROR_INVALID_VALUE; + goto out; + } + name = format (0, "%s", mp->locator_set_name); p = hash_get_mem (lcm->locator_set_index_by_name, name); if (!p) @@ -408,6 +430,21 @@ vl_api_one_map_request_mode_t_handler (vl_api_one_map_request_mode_t * mp) REPLY_MACRO (VL_API_ONE_MAP_REQUEST_MODE_REPLY); } +static void +vl_api_one_nsh_set_locator_set_t_handler (vl_api_one_nsh_set_locator_set_t + * mp) +{ + vl_api_one_nsh_set_locator_set_reply_t *rmp; + int rv = 0; + u8 *ls_name = 0; + + ls_name = format (0, "%s", mp->ls_name); + rv = vnet_lisp_nsh_set_locator_set (ls_name, mp->is_add); + vec_free (ls_name); + + REPLY_MACRO (VL_API_ONE_PITR_SET_LOCATOR_SET_REPLY); +} + static void vl_api_one_pitr_set_locator_set_t_handler (vl_api_one_pitr_set_locator_set_t * mp) @@ -781,7 +818,7 @@ send_one_eid_table_details (mapping_t * mapit, u8 *mac = 0; ip_prefix_t *ip_prefix = NULL; - if (mapit->pitr_set) + if (mapit->pitr_set || mapit->nsh_set) return; switch (filter) @@ -851,6 +888,13 @@ send_one_eid_table_details (mapping_t * mapit, rmp->eid_type = 2; /* l2 mac type */ clib_memcpy (rmp->eid, mac, 6); break; + case GID_ADDR_NSH: + rmp->eid_type = 3; /* NSH type */ + lisp_nsh_api_t nsh; + nsh.spi = clib_host_to_net_u32 (gid_address_nsh_spi (gid)); + nsh.si = gid_address_nsh_si (gid); + clib_memcpy (rmp->eid, &nsh, sizeof (nsh)); + break; default: ASSERT (0); } @@ -1071,6 +1115,7 @@ one_adjacency_copy (vl_api_one_adjacency_t * dst, lisp_adjacency_t * adjs) lisp_adjacency_t *adj; vl_api_one_adjacency_t a; u32 i, n = vec_len (adjs); + lisp_nsh_api_t nsh; for (i = 0; i < n; i++) { @@ -1100,6 +1145,15 @@ one_adjacency_copy (vl_api_one_adjacency_t * dst, lisp_adjacency_t * adjs) mac_copy (a.reid, gid_address_mac (&adj->reid)); mac_copy (a.leid, gid_address_mac (&adj->leid)); break; + case GID_ADDR_NSH: + a.eid_type = 3; /* NSH type */ + nsh.spi = clib_host_to_net_u32 (gid_address_nsh_spi (&adj->reid)); + nsh.si = gid_address_nsh_si (&adj->reid); + clib_memcpy (a.reid, &nsh, sizeof (nsh)); + + nsh.spi = clib_host_to_net_u32 (gid_address_nsh_spi (&adj->leid)); + nsh.si = gid_address_nsh_si (&adj->leid); + clib_memcpy (a.leid, &nsh, sizeof (nsh)); default: ASSERT (0); } @@ -1255,6 +1309,55 @@ static void vec_free (tmp_str); } +static void +vl_api_show_one_nsh_mapping_t_handler (vl_api_show_one_nsh_mapping_t * mp) +{ + unix_shared_memory_queue_t *q = NULL; + vl_api_show_one_nsh_mapping_reply_t *rmp = NULL; + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + mapping_t *m; + locator_set_t *ls = 0; + u8 *tmp_str = 0; + u8 is_set = 0; + int rv = 0; + + q = vl_api_client_index_to_input_queue (mp->client_index); + if (q == 0) + { + return; + } + + if (lcm->nsh_map_index == (u32) ~ 0) + { + tmp_str = format (0, "N/A"); + } + else + { + m = pool_elt_at_index (lcm->mapping_pool, lcm->nsh_map_index); + if (~0 != m->locator_set_index) + { + ls = + pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index); + tmp_str = format (0, "%s", ls->name); + is_set = 1; + } + else + { + tmp_str = format (0, "N/A"); + } + } + vec_add1 (tmp_str, 0); + + /* *INDENT-OFF* */ + REPLY_MACRO2(VL_API_SHOW_ONE_NSH_MAPPING_REPLY, + ({ + rmp->is_set = is_set; + strncpy((char *) rmp->locator_set_name, (char *) tmp_str, + ARRAY_LEN(rmp->locator_set_name) - 1); + })); + /* *INDENT-ON* */ +} + static void vl_api_show_one_pitr_t_handler (vl_api_show_one_pitr_t * mp) { diff --git a/src/vnet/lisp-cp/one_cli.c b/src/vnet/lisp-cp/one_cli.c index db6a6c83..e3fbf5a1 100644 --- a/src/vnet/lisp-cp/one_cli.c +++ b/src/vnet/lisp-cp/one_cli.c @@ -721,6 +721,62 @@ VLIB_CLI_COMMAND (one_show_map_resolvers_command) = { }; /* *INDENT-ON* */ +static clib_error_t * +lisp_nsh_set_locator_set_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + u8 locator_name_set = 0; + u8 *locator_set_name = 0; + u8 is_add = 1; + unformat_input_t _line_input, *line_input = &_line_input; + clib_error_t *error = 0; + int rv = 0; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "ls %_%v%_", &locator_set_name)) + locator_name_set = 1; + else if (unformat (line_input, "disable")) + is_add = 0; + else + { + error = clib_error_return (0, "parse error"); + goto done; + } + } + + if (!locator_name_set) + { + clib_warning ("No locator set specified!"); + goto done; + } + + rv = vnet_lisp_nsh_set_locator_set (locator_set_name, is_add); + if (0 != rv) + { + error = clib_error_return (0, "failed to %s NSH mapping!", + is_add ? "add" : "delete"); + } + +done: + vec_free (locator_set_name); + unformat_free (line_input); + return error; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (one_nsh_set_locator_set_command) = { + .path = "one nsh-mapping", + .short_help = "one nsh-mapping [del] ls ", + .function = lisp_nsh_set_locator_set_command_fn, +}; +/* *INDENT-ON* */ + static clib_error_t * lisp_pitr_set_locator_set_command_fn (vlib_main_t * vm, @@ -923,7 +979,7 @@ lisp_show_eid_table_command_fn (vlib_main_t * vm, /* *INDENT-OFF* */ pool_foreach (mapit, lcm->mapping_pool, ({ - if (mapit->pitr_set) + if (mapit->pitr_set || mapit->nsh_set) continue; locator_set_t * ls = pool_elt_at_index (lcm->locator_set_pool, diff --git a/src/vnet/lisp-gpe/interface.c b/src/vnet/lisp-gpe/interface.c index 94703abc..52b939f0 100644 --- a/src/vnet/lisp-gpe/interface.c +++ b/src/vnet/lisp-gpe/interface.c @@ -742,7 +742,7 @@ lisp_gpe_del_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id) * @return sw_if_index. */ u32 -lisp_gpe_add_nsh_iface (lisp_gpe_main_t * lgm) +vnet_lisp_gpe_add_nsh_iface (lisp_gpe_main_t * lgm) { vnet_main_t *vnm = lgm->vnet_main; tunnel_lookup_t *nsh_ifaces = &lgm->nsh_ifaces; @@ -782,7 +782,7 @@ lisp_gpe_add_nsh_iface (lisp_gpe_main_t * lgm) * */ void -lisp_gpe_del_nsh_iface (lisp_gpe_main_t * lgm) +vnet_lisp_gpe_del_nsh_iface (lisp_gpe_main_t * lgm) { tunnel_lookup_t *nsh_ifaces = &lgm->nsh_ifaces; uword *hip; @@ -851,7 +851,7 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input, { if (is_add) { - if (~0 == lisp_gpe_add_nsh_iface (&lisp_gpe_main)) + if (~0 == vnet_lisp_gpe_add_nsh_iface (&lisp_gpe_main)) { error = clib_error_return (0, "NSH interface not created"); goto done; @@ -859,7 +859,7 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input, } else { - lisp_gpe_del_nsh_iface (&lisp_gpe_main); + vnet_lisp_gpe_del_nsh_iface (&lisp_gpe_main); } goto done; } diff --git a/src/vnet/lisp-gpe/lisp_gpe.h b/src/vnet/lisp-gpe/lisp_gpe.h index 660f8a66..5eafdd55 100644 --- a/src/vnet/lisp-gpe/lisp_gpe.h +++ b/src/vnet/lisp-gpe/lisp_gpe.h @@ -324,6 +324,9 @@ vnet_api_error_t vnet_lisp_stats_enable_disable (u8 enable); lisp_api_stats_t *vnet_lisp_get_stats (void); int vnet_lisp_flush_stats (void); int vnet_gpe_add_del_native_fwd_rpath (vnet_gpe_native_fwd_rpath_args_t * a); +u32 vnet_lisp_gpe_add_nsh_iface (lisp_gpe_main_t * lgm); +void vnet_lisp_gpe_del_nsh_iface (lisp_gpe_main_t * lgm); + #endif /* included_vnet_lisp_gpe_h */ /* diff --git a/src/vpp/api/test_client.c b/src/vpp/api/test_client.c index 231b3c18..844b9702 100644 --- a/src/vpp/api/test_client.c +++ b/src/vpp/api/test_client.c @@ -245,6 +245,7 @@ static void vl_api_ip_neighbor_add_del_reply_t_handler fformat (stdout, "ip neighbor add del reply %d\n", ntohl (mp->retval)); } +#if 0 static void vl_api_vnet_interface_counters_t_handler (vl_api_vnet_interface_counters_t * mp) @@ -332,6 +333,7 @@ vl_api_vnet_interface_counters_t_handler (vl_api_vnet_interface_counters_t * } } } +#endif /* Format an IP4 address. */ u8 * @@ -578,7 +580,6 @@ _(WANT_STATS_REPLY, want_stats_reply) \ _(WANT_OAM_EVENTS_REPLY, want_oam_events_reply) \ _(OAM_EVENT, oam_event) \ _(OAM_ADD_DEL_REPLY, oam_add_del_reply) \ -_(VNET_INTERFACE_COUNTERS, vnet_interface_counters) \ _(VNET_IP4_FIB_COUNTERS, vnet_ip4_fib_counters) \ _(VNET_IP6_FIB_COUNTERS, vnet_ip6_fib_counters) \ _(IP_ADD_DEL_ROUTE_REPLY, ip_add_del_route_reply) \ -- cgit 1.2.3-korg From acd4c63e3c6e70ea3f58527d9bace7c0e38df719 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Thu, 15 Jun 2017 14:33:48 -0700 Subject: Fix map-notify processing with multiple workers Change-Id: Id160346ebf533ee5f55bd735803624a75ed997b9 Signed-off-by: Florin Coras --- src/vnet/lisp-cp/control.c | 39 +++++++++++++++++++++++++++++++++------ src/vnet/lisp-cp/control.h | 18 +++++++++++------- 2 files changed, 44 insertions(+), 13 deletions(-) (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index db78678d..22b5c82c 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -3352,14 +3352,14 @@ mapping_start_expiration_timer (lisp_cp_main_t * lcm, u32 mi, static void map_records_arg_free (map_records_arg_t * a) { + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); mapping_t *m; vec_foreach (m, a->mappings) { vec_free (m->locators); gid_address_free (&m->eid); } - - clib_mem_free (a); + pool_put (lcm->map_records_args_pool[vlib_get_thread_index ()], a); } void * @@ -3420,7 +3420,7 @@ process_map_reply (map_records_arg_t * a) pool_put (lcm->pending_map_requests_pool, pmr); done: - map_records_arg_free (a); + a->is_free = 1; return 0; } @@ -3471,7 +3471,7 @@ process_map_notify (map_records_arg_t * a) return; } - map_records_arg_free (a); + a->is_free = 1; hash_unset (lcm->map_register_messages_by_nonce, a->nonce); } @@ -3556,6 +3556,24 @@ parse_map_records (vlib_buffer_t * b, map_records_arg_t * a, u8 count) return 0; } +static map_records_arg_t * +map_record_args_get () +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + map_records_arg_t *rec; + + /* Cleanup first */ + /* *INDENT-OFF* */ + pool_foreach (rec, lcm->map_records_args_pool[vlib_get_thread_index()], ({ + if (rec->is_free) + map_records_arg_free (rec); + })); + /* *INDENT-ON* */ + + pool_get (lcm->map_records_args_pool[vlib_get_thread_index ()], rec); + return rec; +} + static map_records_arg_t * parse_map_notify (vlib_buffer_t * b) { @@ -3567,8 +3585,9 @@ parse_map_notify (vlib_buffer_t * b) gid_address_t deid; u16 auth_data_len = 0; u8 record_count; - map_records_arg_t *a = clib_mem_alloc (sizeof (*a)); + map_records_arg_t *a; + a = map_record_args_get (); memset (a, 0, sizeof (*a)); mnotif_hdr = vlib_buffer_get_current (b); vlib_buffer_pull (b, sizeof (*mnotif_hdr)); @@ -3791,8 +3810,11 @@ parse_map_reply (vlib_buffer_t * b) u32 i, len = 0; mapping_t m; map_reply_hdr_t *mrep_hdr; - map_records_arg_t *a = clib_mem_alloc (sizeof (*a)); + map_records_arg_t *a; + + a = map_record_args_get (); memset (a, 0, sizeof (*a)); + locator_t *locators; mrep_hdr = vlib_buffer_get_current (b); @@ -3948,6 +3970,8 @@ lisp_cp_init (vlib_main_t * vm) { lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); clib_error_t *error = 0; + vlib_thread_main_t *vtm = vlib_get_thread_main (); + u32 num_threads; if ((error = vlib_call_init_function (vm, lisp_gpe_init))) return error; @@ -3965,6 +3989,9 @@ lisp_cp_init (vlib_main_t * vm) lcm->do_map_resolver_election = 1; lcm->map_request_mode = MR_MODE_DST_ONLY; + num_threads = 1 /* main thread */ + vtm->n_threads; + vec_validate (lcm->map_records_args_pool, num_threads - 1); + /* default vrf mapped to vni 0 */ hash_set (lcm->table_id_by_vni, 0, 0); hash_set (lcm->vni_by_table_id, 0, 0); diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index ad90b526..cf2eb6ef 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -124,6 +124,14 @@ typedef struct u32 bd; } lisp_l2_arp_key_t; +typedef struct +{ + u64 nonce; + u8 is_rloc_probe; + mapping_t *mappings; + volatile u8 is_free; +} map_records_arg_t; + typedef struct { u32 flags; @@ -226,6 +234,9 @@ typedef struct /* timing wheel for mappping timeouts */ timing_wheel_t wheel; + /** Per thread pool of records shared with thread0 */ + map_records_arg_t **map_records_args_pool; + /* commodity */ ip4_main_t *im4; ip6_main_t *im6; @@ -288,13 +299,6 @@ typedef struct u8 key_id; } vnet_lisp_add_del_mapping_args_t; -typedef struct -{ - u64 nonce; - u8 is_rloc_probe; - mapping_t *mappings; -} map_records_arg_t; - int vnet_lisp_map_cache_add_del (vnet_lisp_add_del_mapping_args_t * a, u32 * map_index); -- cgit 1.2.3-korg From cdc74273dfdc824f1478cafccd102307e8b2e991 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Wed, 21 Jun 2017 16:27:01 -0700 Subject: Update lisp map record default ttl to 24h Change-Id: Ib8c72f8e08e89357b64f2f69ab70d60d3a7ec506 Signed-off-by: Florin Coras --- src/vnet/lisp-cp/control.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index cf2eb6ef..577035c4 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -36,8 +36,8 @@ /* normal map-register period */ #define MAP_REGISTER_INTERVAL 60.0 -/* 15 minutes */ -#define MAP_REGISTER_DEFAULT_TTL 900 +/* 24 hours */ +#define MAP_REGISTER_DEFAULT_TTL 86400 typedef struct { -- cgit 1.2.3-korg From 5c20a0131a6a2516c14d5ccfc6db90fd13ec8a33 Mon Sep 17 00:00:00 2001 From: Dave Barach Date: Tue, 13 Jun 2017 08:48:31 -0400 Subject: switch vlib process model to tw_timer_template timer impl Change-Id: I36bb47faea55a6fea7af7ee58d87d8f6dd28f93d Signed-off-by: Dave Barach --- src/vlib/main.c | 62 +++++++++++++++++---------- src/vlib/node.h | 15 ++++--- src/vlib/node_funcs.h | 28 +++++++------ src/vlib/unix/input.c | 61 +++++++++++---------------- src/vnet/lisp-cp/control.h | 1 + src/vppinfra/tw_timer_16t_1w_2048sl.h | 4 ++ src/vppinfra/tw_timer_16t_2w_512sl.h | 4 ++ src/vppinfra/tw_timer_1t_3w_1024sl_ov.h | 4 ++ src/vppinfra/tw_timer_2t_1w_2048sl.h | 4 ++ src/vppinfra/tw_timer_4t_3w_256sl.h | 4 ++ src/vppinfra/tw_timer_4t_3w_4sl_ov.h | 4 ++ src/vppinfra/tw_timer_template.c | 74 +++++++++++++++++++++++++++++++++ src/vppinfra/tw_timer_template.h | 9 ++++ 13 files changed, 197 insertions(+), 77 deletions(-) (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/vlib/main.c b/src/vlib/main.c index 14f680e6..19d70232 100644 --- a/src/vlib/main.c +++ b/src/vlib/main.c @@ -41,6 +41,7 @@ #include #include #include +#include #include @@ -1341,9 +1342,16 @@ dispatch_process (vlib_main_t * vm, p->suspended_process_frame_index = pf - nm->suspended_process_frames; if (p->flags & VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK) - timing_wheel_insert (&nm->timing_wheel, p->resume_cpu_time, - vlib_timing_wheel_data_set_suspended_process - (node->runtime_index)); + { + TWT (tw_timer_wheel) * tw = + (TWT (tw_timer_wheel) *) nm->timing_wheel; + p->stop_timer_handle = + TW (tw_timer_start) (tw, + vlib_timing_wheel_data_set_suspended_process + (node->runtime_index) /* [sic] pool idex */ , + 0 /* timer_id */ , + p->resume_clock_interval); + } } else p->flags &= ~VLIB_PROCESS_IS_RUNNING; @@ -1416,9 +1424,14 @@ dispatch_suspended_process (vlib_main_t * vm, n_vectors = 0; p->n_suspends += 1; if (p->flags & VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK) - timing_wheel_insert (&nm->timing_wheel, p->resume_cpu_time, - vlib_timing_wheel_data_set_suspended_process - (node->runtime_index)); + { + p->stop_timer_handle = + TW (tw_timer_start) ((TWT (tw_timer_wheel) *) nm->timing_wheel, + vlib_timing_wheel_data_set_suspended_process + (node->runtime_index) /* [sic] pool idex */ , + 0 /* timer_id */ , + p->resume_clock_interval); + } } else { @@ -1465,17 +1478,6 @@ vlib_main_or_worker_loop (vlib_main_t * vm, int is_main) else cpu_time_now = clib_cpu_time_now (); - /* Arrange for first level of timing wheel to cover times we care - most about. */ - if (is_main) - { - nm->timing_wheel.min_sched_time = 10e-6; - nm->timing_wheel.max_sched_time = 10e-3; - timing_wheel_init (&nm->timing_wheel, - cpu_time_now, vm->clib_time.clocks_per_second); - vec_alloc (nm->data_from_advancing_timing_wheel, 32); - } - /* Pre-allocate interupt runtime indices and lock. */ vec_alloc (nm->pending_interrupt_node_runtime_indices, 32); vec_alloc (last_node_runtime_indices, 32); @@ -1561,12 +1563,15 @@ vlib_main_or_worker_loop (vlib_main_t * vm, int is_main) if (is_main) { /* Check if process nodes have expired from timing wheel. */ - nm->data_from_advancing_timing_wheel - = timing_wheel_advance (&nm->timing_wheel, cpu_time_now, - nm->data_from_advancing_timing_wheel, - &nm->cpu_time_next_process_ready); + ASSERT (nm->data_from_advancing_timing_wheel != 0); + + nm->data_from_advancing_timing_wheel = + TW (tw_timer_expire_timers_vec) + ((TWT (tw_timer_wheel) *) nm->timing_wheel, vlib_time_now (vm), + nm->data_from_advancing_timing_wheel); ASSERT (nm->data_from_advancing_timing_wheel != 0); + if (PREDICT_FALSE (_vec_len (nm->data_from_advancing_timing_wheel) > 0)) { @@ -1612,8 +1617,6 @@ vlib_main_or_worker_loop (vlib_main_t * vm, int is_main) dispatch_suspended_process (vm, di, cpu_time_now); } } - - /* Reset vector. */ _vec_len (nm->data_from_advancing_timing_wheel) = 0; } } @@ -1692,6 +1695,7 @@ int vlib_main (vlib_main_t * volatile vm, unformat_input_t * input) { clib_error_t *volatile error; + vlib_node_main_t *nm = &vm->node_main; vm->queue_signal_callback = dummy_queue_signal_callback; @@ -1746,6 +1750,18 @@ vlib_main (vlib_main_t * volatile vm, unformat_input_t * input) VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES, "default"); + nm->timing_wheel = clib_mem_alloc_aligned (sizeof (TWT (tw_timer_wheel)), + CLIB_CACHE_LINE_BYTES); + + vec_validate (nm->data_from_advancing_timing_wheel, 10); + _vec_len (nm->data_from_advancing_timing_wheel) = 0; + + /* Create the process timing wheel */ + TW (tw_timer_wheel_init) ((TWT (tw_timer_wheel) *) nm->timing_wheel, + 0 /* no callback */ , + 10e-6 /* timer period 10us */ , + ~0 /* max expirations per call */ ); + switch (clib_setjmp (&vm->main_loop_exit, VLIB_MAIN_LOOP_EXIT_NONE)) { case VLIB_MAIN_LOOP_EXIT_NONE: diff --git a/src/vlib/node.h b/src/vlib/node.h index 906d795f..77914272 100644 --- a/src/vlib/node.h +++ b/src/vlib/node.h @@ -43,7 +43,6 @@ #include #include #include -#include #include /* for vlib_trace_filter_t */ /* Forward declaration. */ @@ -542,8 +541,14 @@ typedef struct /* Pool of currently valid event types. */ vlib_process_event_type_t *event_type_pool; - /* When suspending saves cpu cycle counter when process is to be resumed. */ - u64 resume_cpu_time; + /* + * When suspending saves clock time (10us ticks) when process + * is to be resumed. + */ + u64 resume_clock_interval; + + /* Handle from timer code, to cancel an unexpired timer */ + u32 stop_timer_handle; /* Default output function and its argument for any CLI outputs within the process. */ @@ -664,7 +669,7 @@ typedef struct vlib_pending_frame_t *pending_frames; /* Timing wheel for scheduling time-based node dispatch. */ - timing_wheel_t timing_wheel; + void *timing_wheel; vlib_signal_timed_event_data_t *signal_timed_event_data_pool; @@ -672,7 +677,7 @@ typedef struct u32 *data_from_advancing_timing_wheel; /* CPU time of next process to be ready on timing wheel. */ - u64 cpu_time_next_process_ready; + f64 time_next_process_ready; /* Vector of process nodes. One for each node of type VLIB_NODE_TYPE_PROCESS. */ diff --git a/src/vlib/node_funcs.h b/src/vlib/node_funcs.h index 4d7cc192..d6588a74 100644 --- a/src/vlib/node_funcs.h +++ b/src/vlib/node_funcs.h @@ -46,6 +46,7 @@ #define included_vlib_node_funcs_h #include +#include /** \brief Get vlib node by index. @warning This function will ASSERT if @c i is out of range. @@ -428,14 +429,14 @@ vlib_current_process (vlib_main_t * vm) return vlib_get_current_process (vm)->node_runtime.node_index; } -/** Returns TRUE if a process suspend time is less than 1us +/** Returns TRUE if a process suspend time is less than 10us @param dt - remaining poll time in seconds - @returns 1 if dt < 1e-6, 0 otherwise + @returns 1 if dt < 10e-6, 0 otherwise */ always_inline uword vlib_process_suspend_time_is_zero (f64 dt) { - return dt < 1e-6; + return dt < 10e-6; } /** Suspend a vlib cooperative multi-tasking thread for a period of time @@ -450,7 +451,6 @@ vlib_process_suspend (vlib_main_t * vm, f64 dt) uword r; vlib_node_main_t *nm = &vm->node_main; vlib_process_t *p = vec_elt (nm->processes, nm->current_process_index); - u64 dt_cpu = dt * vm->clib_time.clocks_per_second; if (vlib_process_suspend_time_is_zero (dt)) return VLIB_PROCESS_RESUME_LONGJMP_RESUME; @@ -459,7 +459,8 @@ vlib_process_suspend (vlib_main_t * vm, f64 dt) r = clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND); if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND) { - p->resume_cpu_time = clib_cpu_time_now () + dt_cpu; + /* expiration time in 10us ticks */ + p->resume_clock_interval = dt * 1e5; clib_longjmp (&p->return_longjmp, VLIB_PROCESS_RETURN_LONGJMP_SUSPEND); } @@ -718,8 +719,7 @@ vlib_process_wait_for_event_or_clock (vlib_main_t * vm, f64 dt) r = clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND); if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND) { - p->resume_cpu_time = (clib_cpu_time_now () - + (dt * vm->clib_time.clocks_per_second)); + p->resume_clock_interval = dt * 1e5; clib_longjmp (&p->return_longjmp, VLIB_PROCESS_RETURN_LONGJMP_SUSPEND); } @@ -834,7 +834,8 @@ vlib_process_signal_event_helper (vlib_node_main_t * nm, p->flags = p_flags | VLIB_PROCESS_RESUME_PENDING; vec_add1 (nm->data_from_advancing_timing_wheel, x); if (delete_from_wheel) - timing_wheel_delete (&nm->timing_wheel, x); + TW (tw_timer_stop) ((TWT (tw_timer_wheel) *) nm->timing_wheel, + p->stop_timer_handle); } return data_to_be_written_by_caller; @@ -895,7 +896,6 @@ vlib_process_signal_event_at_time (vlib_main_t * vm, else { vlib_signal_timed_event_data_t *te; - u64 dt_cpu = dt * vm->clib_time.clocks_per_second; pool_get_aligned (nm->signal_timed_event_data_pool, te, sizeof (te[0])); @@ -911,10 +911,12 @@ vlib_process_signal_event_at_time (vlib_main_t * vm, te->process_node_index = n->runtime_index; te->event_type_index = t; - timing_wheel_insert (&nm->timing_wheel, clib_cpu_time_now () + dt_cpu, - vlib_timing_wheel_data_set_timed_event (te - - nm-> - signal_timed_event_data_pool)); + p->stop_timer_handle = + TW (tw_timer_start) ((TWT (tw_timer_wheel) *) nm->timing_wheel, + vlib_timing_wheel_data_set_timed_event + (te - nm->signal_timed_event_data_pool), + 0 /* timer_id */ , + (vlib_time_now (vm) + dt) * 1e5); /* Inline data big enough to hold event? */ if (te->n_data_bytes < sizeof (te->inline_event_data)) diff --git a/src/vlib/unix/input.c b/src/vlib/unix/input.c index 73783d13..515dae94 100644 --- a/src/vlib/unix/input.c +++ b/src/vlib/unix/input.c @@ -40,6 +40,7 @@ #include #include #include +#include /* FIXME autoconf */ #define HAVE_LINUX_EPOLL @@ -113,56 +114,44 @@ linux_epoll_input (vlib_main_t * vm, { vlib_node_main_t *nm = &vm->node_main; - u64 t = nm->cpu_time_next_process_ready; + u32 ticks_until_expiration; f64 timeout; - int timeout_ms, max_timeout_ms = 10; + int timeout_ms = 0, max_timeout_ms = 10; f64 vector_rate = vlib_last_vectors_per_main_loop (vm); - if (t == ~0ULL) + /* If we're not working very hard, decide how long to sleep */ + if (vector_rate < 2 && vm->api_queue_nonempty == 0 + && nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] == 0) { - timeout = 10e-3; - timeout_ms = max_timeout_ms; - } - else - { - timeout = - (((i64) t - (i64) clib_cpu_time_now ()) - * vm->clib_time.seconds_per_clock) - /* subtract off some slop time */ - 50e-6; + ticks_until_expiration = TW (tw_timer_first_expires_in_ticks) + ((TWT (tw_timer_wheel) *) nm->timing_wheel); - if (timeout < 1e-3) + /* Nothing on the fast wheel, sleep 10ms */ + if (ticks_until_expiration == TW_SLOTS_PER_RING) { - /* We have event happenning in less than 1 ms so - don't allow epoll to wait */ - timeout_ms = 0; + timeout = 10e-3; + timeout_ms = max_timeout_ms; } else { - timeout_ms = timeout * 1e3; - - /* Must be between 1 and 10 ms. */ - timeout_ms = clib_max (1, timeout_ms); - timeout_ms = clib_min (max_timeout_ms, timeout_ms); + timeout = (f64) ticks_until_expiration *1e-5; + if (timeout < 1e-3) + timeout_ms = 0; + else + { + timeout_ms = timeout * 1e3; + /* Must be between 1 and 10 ms. */ + timeout_ms = clib_max (1, timeout_ms); + timeout_ms = clib_min (max_timeout_ms, timeout_ms); + } } + node->input_main_loops_per_call = 0; } - - /* If we still have input nodes polling (e.g. vnet packet generator) - don't sleep. */ - if (nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] > 0) - timeout_ms = 0; - - /* - * When busy: don't wait & only epoll for input - * every 1024 times through main loop. - */ - if (vector_rate > 1 || vm->api_queue_nonempty) + else /* busy */ { - timeout_ms = 0; + /* Don't come back for a respectable number of dispatch cycles */ node->input_main_loops_per_call = 1024; } - else - /* We're not busy; go to sleep for a while. */ - node->input_main_loops_per_call = 0; /* Allow any signal to wakeup our sleep. */ { diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index 577035c4..0e63b3c7 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -19,6 +19,7 @@ #include #include #include +#include #define NUMBER_OF_RETRIES 1 #define PENDING_MREQ_EXPIRATION_TIME 3.0 /* seconds */ diff --git a/src/vppinfra/tw_timer_16t_1w_2048sl.h b/src/vppinfra/tw_timer_16t_1w_2048sl.h index 6edef17b..66cf7d37 100644 --- a/src/vppinfra/tw_timer_16t_1w_2048sl.h +++ b/src/vppinfra/tw_timer_16t_1w_2048sl.h @@ -25,6 +25,8 @@ #undef LOG2_TW_TIMERS_PER_OBJECT #undef TW_SUFFIX #undef TW_OVERFLOW_VECTOR +#undef TW_FAST_WHEEL_BITMAP +#undef TW_TIMER_ALLOW_DUPLICATE_STOP #define TW_TIMER_WHEELS 1 #define TW_SLOTS_PER_RING 2048 @@ -33,6 +35,8 @@ #define TW_TIMERS_PER_OBJECT 16 #define LOG2_TW_TIMERS_PER_OBJECT 4 #define TW_SUFFIX _16t_1w_2048sl +#define TW_FAST_WHEEL_BITMAP 0 +#define TW_TIMER_ALLOW_DUPLICATE_STOP 0 #include diff --git a/src/vppinfra/tw_timer_16t_2w_512sl.h b/src/vppinfra/tw_timer_16t_2w_512sl.h index 2497b31c..00587b8e 100644 --- a/src/vppinfra/tw_timer_16t_2w_512sl.h +++ b/src/vppinfra/tw_timer_16t_2w_512sl.h @@ -25,6 +25,8 @@ #undef LOG2_TW_TIMERS_PER_OBJECT #undef TW_SUFFIX #undef TW_OVERFLOW_VECTOR +#undef TW_FAST_WHEEL_BITMAP +#undef TW_TIMER_ALLOW_DUPLICATE_STOP #define TW_TIMER_WHEELS 2 #define TW_SLOTS_PER_RING 512 @@ -33,6 +35,8 @@ #define TW_TIMERS_PER_OBJECT 16 #define LOG2_TW_TIMERS_PER_OBJECT 4 #define TW_SUFFIX _16t_2w_512sl +#define TW_FAST_WHEEL_BITMAP 0 +#define TW_TIMER_ALLOW_DUPLICATE_STOP 0 #include diff --git a/src/vppinfra/tw_timer_1t_3w_1024sl_ov.h b/src/vppinfra/tw_timer_1t_3w_1024sl_ov.h index 7327f87b..e5e4cc19 100644 --- a/src/vppinfra/tw_timer_1t_3w_1024sl_ov.h +++ b/src/vppinfra/tw_timer_1t_3w_1024sl_ov.h @@ -25,6 +25,8 @@ #undef LOG2_TW_TIMERS_PER_OBJECT #undef TW_SUFFIX #undef TW_OVERFLOW_VECTOR +#undef TW_FAST_WHEEL_BITMAP +#undef TW_TIMER_ALLOW_DUPLICATE_STOP #define TW_TIMER_WHEELS 3 #define TW_SLOTS_PER_RING 1024 @@ -34,6 +36,8 @@ #define LOG2_TW_TIMERS_PER_OBJECT 0 #define TW_SUFFIX _1t_3w_1024sl_ov #define TW_OVERFLOW_VECTOR 1 +#define TW_FAST_WHEEL_BITMAP 1 +#define TW_TIMER_ALLOW_DUPLICATE_STOP 1 #include diff --git a/src/vppinfra/tw_timer_2t_1w_2048sl.h b/src/vppinfra/tw_timer_2t_1w_2048sl.h index 33b74405..98b548b3 100644 --- a/src/vppinfra/tw_timer_2t_1w_2048sl.h +++ b/src/vppinfra/tw_timer_2t_1w_2048sl.h @@ -25,6 +25,8 @@ #undef LOG2_TW_TIMERS_PER_OBJECT #undef TW_SUFFIX #undef TW_OVERFLOW_VECTOR +#undef TW_FAST_WHEEL_BITMAP +#undef TW_TIMER_ALLOW_DUPLICATE_STOP #define TW_TIMER_WHEELS 1 #define TW_SLOTS_PER_RING 2048 @@ -33,6 +35,8 @@ #define TW_TIMERS_PER_OBJECT 2 #define LOG2_TW_TIMERS_PER_OBJECT 1 #define TW_SUFFIX _2t_1w_2048sl +#define TW_FAST_WHEEL_BITMAP 0 +#define TW_TIMER_ALLOW_DUPLICATE_STOP 0 #include diff --git a/src/vppinfra/tw_timer_4t_3w_256sl.h b/src/vppinfra/tw_timer_4t_3w_256sl.h index 89adb7a2..07203de8 100644 --- a/src/vppinfra/tw_timer_4t_3w_256sl.h +++ b/src/vppinfra/tw_timer_4t_3w_256sl.h @@ -25,6 +25,8 @@ #undef LOG2_TW_TIMERS_PER_OBJECT #undef TW_SUFFIX #undef TW_OVERFLOW_VECTOR +#undef TW_FAST_WHEEL_BITMAP +#undef TW_TIMER_ALLOW_DUPLICATE_STOP #define TW_TIMER_WHEELS 3 #define TW_SLOTS_PER_RING 256 @@ -33,6 +35,8 @@ #define TW_TIMERS_PER_OBJECT 4 #define LOG2_TW_TIMERS_PER_OBJECT 2 #define TW_SUFFIX _4t_3w_256sl +#define TW_FAST_WHEEL_BITMAP 0 +#define TW_TIMER_ALLOW_DUPLICATE_STOP 0 #include diff --git a/src/vppinfra/tw_timer_4t_3w_4sl_ov.h b/src/vppinfra/tw_timer_4t_3w_4sl_ov.h index 0f76164d..20a01d05 100644 --- a/src/vppinfra/tw_timer_4t_3w_4sl_ov.h +++ b/src/vppinfra/tw_timer_4t_3w_4sl_ov.h @@ -25,6 +25,8 @@ #undef LOG2_TW_TIMERS_PER_OBJECT #undef TW_SUFFIX #undef TW_OVERFLOW_VECTOR +#undef TW_FAST_WHEEL_BITMAP +#undef TW_TIMER_ALLOW_DUPLICATE_STOP #define TW_TIMER_WHEELS 3 #define TW_SLOTS_PER_RING 4 @@ -34,6 +36,8 @@ #define LOG2_TW_TIMERS_PER_OBJECT 2 #define TW_SUFFIX _4t_3w_4sl_ov #define TW_OVERFLOW_VECTOR 1 +#define TW_FAST_WHEEL_BITMAP 0 +#define TW_TIMER_ALLOW_DUPLICATE_STOP 0 #include diff --git a/src/vppinfra/tw_timer_template.c b/src/vppinfra/tw_timer_template.c index 9253488c..c0a9685a 100644 --- a/src/vppinfra/tw_timer_template.c +++ b/src/vppinfra/tw_timer_template.c @@ -204,6 +204,11 @@ TW (tw_timer_start) (TWT (tw_timer_wheel) * tw, u32 pool_index, u32 timer_id, ts = &tw->w[TW_TIMER_RING_FAST][fast_ring_offset]; timer_addhead (tw->timers, ts->head_index, t - tw->timers); + +#if TW_FAST_WHEEL_BITMAP + tw->fast_slot_bitmap = clib_bitmap_set (tw->fast_slot_bitmap, + fast_ring_offset, 1); +#endif return t - tw->timers; } @@ -251,6 +256,16 @@ void TW (tw_timer_stop) (TWT (tw_timer_wheel) * tw, u32 handle) { TWT (tw_timer) * t; +#if TW_TIMER_ALLOW_DUPLICATE_STOP + /* + * A vlib process may have its timer expire, and receive + * an event before the expiration is processed. + * That results in a duplicate tw_timer_stop. + */ + if (pool_is_free_index (tw->timers, handle)) + return; +#endif + t = pool_elt_at_index (tw->timers, handle); /* in case of idiotic handle (e.g. passing a listhead index) */ @@ -481,6 +496,11 @@ static inline { ts = &tw->w[TW_TIMER_RING_FAST][t->fast_ring_offset]; timer_addhead (tw->timers, ts->head_index, t - tw->timers); +#if TW_FAST_WHEEL_BITMAP + tw->fast_slot_bitmap = + clib_bitmap_set (tw->fast_slot_bitmap, + t->fast_ring_offset, 1); +#endif } } } @@ -523,6 +543,11 @@ static inline { ts = &tw->w[TW_TIMER_RING_FAST][t->fast_ring_offset]; timer_addhead (tw->timers, ts->head_index, t - tw->timers); +#if TW_FAST_WHEEL_BITMAP + tw->fast_slot_bitmap = + clib_bitmap_set (tw->fast_slot_bitmap, + t->fast_ring_offset, 1); +#endif } else /* typical case */ { @@ -569,6 +594,11 @@ static inline /* Add to fast ring */ ts = &tw->w[TW_TIMER_RING_FAST][t->fast_ring_offset]; timer_addhead (tw->timers, ts->head_index, t - tw->timers); +#if TW_FAST_WHEEL_BITMAP + tw->fast_slot_bitmap = + clib_bitmap_set (tw->fast_slot_bitmap, + t->fast_ring_offset, 1); +#endif } } } @@ -604,6 +634,12 @@ static inline } tw->expired_timer_handles = callback_vector; } + +#if TW_FAST_WHEEL_BITMAP + tw->fast_slot_bitmap = clib_bitmap_set (tw->fast_slot_bitmap, + fast_wheel_index, 0); +#endif + tw->current_tick++; fast_wheel_index++; tw->current_index[TW_TIMER_RING_FAST] = fast_wheel_index; @@ -642,6 +678,44 @@ u32 *TW (tw_timer_expire_timers_vec) (TWT (tw_timer_wheel) * tw, f64 now, return TW (tw_timer_expire_timers_internal) (tw, now, vec); } +#if TW_FAST_WHEEL_BITMAP +/** Returns an approximation to the first timer expiration in + * timer-ticks from "now". To avoid wasting an unjustifiable + * amount of time on the problem, we maintain an approximate fast-wheel slot + * occupancy bitmap. We don't worry about clearing fast wheel bits + * when timers are removed from fast wheel slots. + */ + +u32 TW (tw_timer_first_expires_in_ticks) (TWT (tw_timer_wheel) * tw) +{ + u32 first_expiring_index, fast_ring_index; + i32 delta; + + if (clib_bitmap_is_zero (tw->fast_slot_bitmap)) + return TW_SLOTS_PER_RING; + + fast_ring_index = tw->current_index[TW_TIMER_RING_FAST]; + if (fast_ring_index == TW_SLOTS_PER_RING) + fast_ring_index = 0; + + first_expiring_index = clib_bitmap_next_set (tw->fast_slot_bitmap, + fast_ring_index); + if (first_expiring_index == ~0 && fast_ring_index != 0) + first_expiring_index = clib_bitmap_first_set (tw->fast_slot_bitmap); + + ASSERT (first_expiring_index != ~0); + + delta = (i32) first_expiring_index - (i32) fast_ring_index; + if (delta < 0) + delta += TW_SLOTS_PER_RING; + + ASSERT (delta >= 0); + + return (u32) delta; +} + +#endif + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vppinfra/tw_timer_template.h b/src/vppinfra/tw_timer_template.h index 76755609..0404e3f4 100644 --- a/src/vppinfra/tw_timer_template.h +++ b/src/vppinfra/tw_timer_template.h @@ -19,6 +19,7 @@ #include #include +#include #ifndef _twt #define _twt(a,b) a##b##_t @@ -202,6 +203,11 @@ typedef struct tw_timer_wheel_slot_t overflow; #endif +#if TW_FAST_WHEEL_BITMAP > 0 + /** Fast wheel slot occupancy bitmap */ + uword *fast_slot_bitmap; +#endif + /** expired timer callback, receives a vector of handles */ void (*expired_timer_callback) (u32 * expired_timer_handles); @@ -226,6 +232,9 @@ void TW (tw_timer_wheel_free) (TWT (tw_timer_wheel) * tw); u32 *TW (tw_timer_expire_timers) (TWT (tw_timer_wheel) * tw, f64 now); u32 *TW (tw_timer_expire_timers_vec) (TWT (tw_timer_wheel) * tw, f64 now, u32 * vec); +#if TW_FAST_WHEEL_BITMAP +u32 TW (tw_timer_first_expires_in_ticks) (TWT (tw_timer_wheel) * tw); +#endif /* * fd.io coding-style-patch-verification: ON -- cgit 1.2.3-korg From 1e553a00389fb0eb2d54b950a3cfd91dd1a72644 Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Wed, 2 Aug 2017 12:45:07 +0200 Subject: LISP: make TTL for map register messages configurable Change-Id: I38e1c6a6b033e12ef3f4345a1deff73fa4adbea0 Signed-off-by: Filip Tehlar --- src/vat/api_format.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++ src/vnet/lisp-cp/control.c | 16 ++++++++ src/vnet/lisp-cp/control.h | 5 +++ src/vnet/lisp-cp/one.api | 34 +++++++++++++++++ src/vnet/lisp-cp/one_api.c | 31 +++++++++++++++ src/vnet/lisp-cp/one_cli.c | 67 ++++++++++++++++++++++++++++++++ 6 files changed, 248 insertions(+) (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/vat/api_format.c b/src/vat/api_format.c index 6a2d36de..bbd97ba1 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -3850,6 +3850,42 @@ static void vam->result_ready = 1; } +static void + vl_api_show_one_map_register_ttl_reply_t_handler + (vl_api_show_one_map_register_ttl_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + vl_api_show_one_map_register_ttl_reply_t_endian (mp); + + if (0 <= retval) + { + print (vam->ofp, "ttl: %u", mp->ttl); + } + + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_show_one_map_register_ttl_reply_t_handler_json + (vl_api_show_one_map_register_ttl_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vl_api_show_one_map_register_ttl_reply_t_endian (mp); + vat_json_init_object (&node); + vat_json_object_add_uint (&node, "ttl", mp->ttl); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + static void vl_api_show_one_pitr_reply_t_handler (vl_api_show_one_pitr_reply_t * mp) { @@ -4601,6 +4637,7 @@ _(one_add_del_map_server_reply) \ _(one_enable_disable_reply) \ _(one_rloc_probe_enable_disable_reply) \ _(one_map_register_enable_disable_reply) \ +_(one_map_register_set_ttl_reply) \ _(one_pitr_set_locator_set_reply) \ _(one_map_request_mode_reply) \ _(one_add_del_map_request_itr_rlocs_reply) \ @@ -4825,6 +4862,7 @@ _(ONE_ADD_DEL_MAP_SERVER_REPLY, one_add_del_map_server_reply) \ _(ONE_ENABLE_DISABLE_REPLY, one_enable_disable_reply) \ _(ONE_MAP_REGISTER_ENABLE_DISABLE_REPLY, \ one_map_register_enable_disable_reply) \ +_(ONE_MAP_REGISTER_SET_TTL_REPLY, one_map_register_set_ttl_reply) \ _(ONE_RLOC_PROBE_ENABLE_DISABLE_REPLY, \ one_rloc_probe_enable_disable_reply) \ _(ONE_PITR_SET_LOCATOR_SET_REPLY, one_pitr_set_locator_set_reply) \ @@ -4871,6 +4909,7 @@ _(SHOW_ONE_MAP_REQUEST_MODE_REPLY, show_one_map_request_mode_reply) \ _(SHOW_ONE_RLOC_PROBE_STATE_REPLY, show_one_rloc_probe_state_reply) \ _(SHOW_ONE_MAP_REGISTER_STATE_REPLY, \ show_one_map_register_state_reply) \ +_(SHOW_ONE_MAP_REGISTER_TTL_REPLY, show_one_map_register_ttl_reply) \ _(AF_PACKET_CREATE_REPLY, af_packet_create_reply) \ _(AF_PACKET_DELETE_REPLY, af_packet_delete_reply) \ _(POLICER_ADD_DEL_REPLY, policer_add_del_reply) \ @@ -16051,6 +16090,60 @@ api_lisp_gpe_add_del_iface (vat_main_t * vam) return ret; } +static int +api_one_map_register_set_ttl (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_map_register_set_ttl_t *mp; + u32 ttl = 0; + u8 is_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%u", &ttl)) + is_set = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!is_set) + { + errmsg ("TTL value missing!"); + return -99; + } + + M (ONE_MAP_REGISTER_SET_TTL, mp); + mp->ttl = clib_host_to_net_u32 (ttl); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_show_one_map_register_ttl (vat_main_t * vam) +{ + vl_api_show_one_map_register_ttl_t *mp; + int ret; + + M (SHOW_ONE_MAP_REGISTER_TTL, mp); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + /** * Add/del map request itr rlocs from ONE control plane and updates * @@ -19984,10 +20077,12 @@ _(show_one_status, "") \ _(one_stats_dump, "") \ _(one_stats_flush, "") \ _(one_get_map_request_itr_rlocs, "") \ +_(one_map_register_set_ttl, "") \ _(show_one_nsh_mapping, "") \ _(show_one_pitr, "") \ _(show_one_use_petr, "") \ _(show_one_map_request_mode, "") \ +_(show_one_map_register_ttl, "") \ _(lisp_add_del_locator_set, "locator-set [iface |"\ " sw_if_index p " \ "w ] [del]") \ diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index fc860e14..a85656b3 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -2074,6 +2074,21 @@ vnet_lisp_add_del_map_resolver (vnet_lisp_add_del_map_resolver_args_t * a) return 0; } +int +vnet_lisp_map_register_set_ttl (u32 ttl) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + lcm->map_register_ttl = ttl; + return 0; +} + +u32 +vnet_lisp_map_register_get_ttl (void) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + return lcm->map_register_ttl; +} + int vnet_lisp_add_del_mreq_itr_rlocs (vnet_lisp_add_del_mreq_itr_rloc_args_t * a) { @@ -4005,6 +4020,7 @@ lisp_cp_init (vlib_main_t * vm) u64 now = clib_cpu_time_now (); timing_wheel_init (&lcm->wheel, now, vm->clib_time.clocks_per_second); lcm->nsh_map_index = ~0; + lcm->map_register_ttl = MAP_REGISTER_DEFAULT_TTL; return 0; } diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index 0e63b3c7..d030e588 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -238,6 +238,9 @@ typedef struct /** Per thread pool of records shared with thread0 */ map_records_arg_t **map_records_args_pool; + /* TTL used for all mappings when registering */ + u32 map_register_ttl; + /* commodity */ ip4_main_t *im4; ip6_main_t *im6; @@ -362,6 +365,8 @@ int vnet_lisp_add_del_l2_arp_entry (gid_address_t * key, u8 * mac, u8 is_add); u32 *vnet_lisp_l2_arp_bds_get (void); lisp_api_l2_arp_entry_t *vnet_lisp_l2_arp_entries_get_by_bd (u32 bd); int vnet_lisp_nsh_set_locator_set (u8 * locator_set_name, u8 is_add); +int vnet_lisp_map_register_set_ttl (u32 ttl); +u32 vnet_lisp_map_register_get_ttl (void); map_records_arg_t *parse_map_reply (vlib_buffer_t * b); diff --git a/src/vnet/lisp-cp/one.api b/src/vnet/lisp-cp/one.api index 31811a34..5087c634 100644 --- a/src/vnet/lisp-cp/one.api +++ b/src/vnet/lisp-cp/one.api @@ -102,6 +102,40 @@ autoreply define one_add_del_local_eid u8 key[64]; }; +/** \brief Set TTL for map register messages + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param ttl - time to live +*/ +autoreply define one_map_register_set_ttl +{ + u32 client_index; + u32 context; + u32 ttl; +}; + +/** \brief Get TTL for map register messages + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ +define show_one_map_register_ttl +{ + u32 client_index; + u32 context; +}; + +/** \brief Contains current TTL for map register messages + @param client_index - opaque cookie to identify the sender + @param retval - return code + @param ttl - time to live +*/ +define show_one_map_register_ttl_reply +{ + u32 context; + i32 retval; + u32 ttl; +}; + /** \brief Add/delete map server @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request diff --git a/src/vnet/lisp-cp/one_api.c b/src/vnet/lisp-cp/one_api.c index cac3313f..2922993f 100644 --- a/src/vnet/lisp-cp/one_api.c +++ b/src/vnet/lisp-cp/one_api.c @@ -101,9 +101,11 @@ _(ONE_MAP_SERVER_DUMP, one_map_server_dump) \ _(ONE_EID_TABLE_MAP_DUMP, one_eid_table_map_dump) \ _(ONE_EID_TABLE_VNI_DUMP, one_eid_table_vni_dump) \ _(ONE_ADJACENCIES_GET, one_adjacencies_get) \ +_(ONE_MAP_REGISTER_SET_TTL, one_map_register_set_ttl) \ _(SHOW_ONE_NSH_MAPPING, show_one_nsh_mapping) \ _(SHOW_ONE_RLOC_PROBE_STATE, show_one_rloc_probe_state) \ _(SHOW_ONE_MAP_REGISTER_STATE, show_one_map_register_state) \ +_(SHOW_ONE_MAP_REGISTER_TTL, show_one_map_register_ttl) \ _(SHOW_ONE_STATUS, show_one_status) \ _(ONE_ADD_DEL_MAP_REQUEST_ITR_RLOCS, \ one_add_del_map_request_itr_rlocs) \ @@ -143,6 +145,35 @@ unformat_one_locs (vl_api_one_remote_locator_t * rmt_locs, u32 rloc_num) return locs; } +static void +vl_api_one_map_register_set_ttl_t_handler (vl_api_one_map_register_set_ttl_t * + mp) +{ + vl_api_one_map_register_set_ttl_reply_t *rmp; + int rv = 0; + + vl_api_one_map_register_set_ttl_t_endian (mp); + rv = vnet_lisp_map_register_set_ttl (mp->ttl); + + REPLY_MACRO (VL_API_ONE_MAP_REGISTER_SET_TTL_REPLY); +} + +static void + vl_api_show_one_map_register_ttl_t_handler + (vl_api_show_one_map_register_ttl_t * mp) +{ + vl_api_show_one_map_register_ttl_reply_t *rmp; + int rv = 0; + + u32 ttl = vnet_lisp_map_register_get_ttl (); + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_SHOW_ONE_MAP_REGISTER_TTL_REPLY, + ({ + rmp->ttl = clib_host_to_net_u32 (ttl); + })); + /* *INDENT-ON* */ +} + static void vl_api_one_add_del_locator_set_t_handler (vl_api_one_add_del_locator_set_t * mp) diff --git a/src/vnet/lisp-cp/one_cli.c b/src/vnet/lisp-cp/one_cli.c index e3fbf5a1..3b411899 100644 --- a/src/vnet/lisp-cp/one_cli.c +++ b/src/vnet/lisp-cp/one_cli.c @@ -1081,6 +1081,73 @@ VLIB_CLI_COMMAND (one_cp_enable_disable_command) = { }; /* *INDENT-ON* */ +static clib_error_t * +lisp_map_register_set_ttl_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + u32 ttl = 0; + u8 is_set = 0; + clib_error_t *error = NULL; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%u", &ttl)) + is_set = 1; + else + { + vlib_cli_output (vm, "parse error: '%U'", format_unformat_error, + line_input); + goto done; + } + } + + if (!is_set) + { + vlib_cli_output (vm, "expected integer value for TTL!"); + goto done; + } + + vnet_lisp_map_register_set_ttl (ttl); + +done: + unformat_free (line_input); + return error; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (one_map_register_set_ttl_command) = { + .path = "one map-register ttl", + .short_help = "one map-register ttl", + .function = lisp_map_register_set_ttl_command_fn, +}; +/* *INDENT-ON* */ + +static clib_error_t * +lisp_map_register_show_ttl_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + u32 ttl = vnet_lisp_map_register_get_ttl (); + + vlib_cli_output (vm, "map-register TTL: %u", ttl); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (one_map_register_show_ttl_command) = { + .path = "show one map-register ttl", + .short_help = "show one map-register ttl", + .function = lisp_map_register_show_ttl_command_fn, +}; + +/* *INDENT-ON* */ + static clib_error_t * lisp_map_register_enable_disable_command_fn (vlib_main_t * vm, unformat_input_t * input, -- cgit 1.2.3-korg From 7048ff1e3af7a3979a9134cbbb8157df8e1a8a53 Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Thu, 27 Jul 2017 08:09:14 +0200 Subject: LISP: Map-server fallback feature Change-Id: I1356296e1a85b5d532f45ba70572b2184ac3f6fb Signed-off-by: Filip Tehlar --- src/vat/api_format.c | 94 +++++++++++++++++++ src/vnet/lisp-cp/control.c | 228 ++++++++++++++++++++++++++++++++++----------- src/vnet/lisp-cp/control.h | 24 ++++- src/vnet/lisp-cp/one.api | 20 ++++ src/vnet/lisp-cp/one_api.c | 33 +++++++ src/vnet/lisp-cp/one_cli.c | 64 +++++++++++++ 6 files changed, 405 insertions(+), 58 deletions(-) (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/vat/api_format.c b/src/vat/api_format.c index 27286686..f97cdeef 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -2930,6 +2930,39 @@ static void vat_json_object_add_uint (node, "vni", clib_net_to_host_u32 (mp->vni)); } +static void + vl_api_show_one_map_register_fallback_threshold_reply_t_handler + (vl_api_show_one_map_register_fallback_threshold_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + int retval = clib_net_to_host_u32 (mp->retval); + + vl_api_show_one_map_register_fallback_threshold_reply_t_endian (mp); + print (vam->ofp, "fallback threshold value: %d", mp->value); + + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_show_one_map_register_fallback_threshold_reply_t_handler_json + (vl_api_show_one_map_register_fallback_threshold_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t _node, *node = &_node; + int retval = clib_net_to_host_u32 (mp->retval); + + vl_api_show_one_map_register_fallback_threshold_reply_t_endian (mp); + vat_json_init_object (node); + vat_json_object_add_uint (node, "value", mp->value); + + vat_json_print (vam->ofp, node); + vat_json_free (node); + + vam->retval = retval; + vam->result_ready = 1; +} + static void vl_api_show_one_map_register_state_reply_t_handler (vl_api_show_one_map_register_state_reply_t * mp) @@ -4663,6 +4696,7 @@ _(one_enable_disable_reply) \ _(one_rloc_probe_enable_disable_reply) \ _(one_map_register_enable_disable_reply) \ _(one_map_register_set_ttl_reply) \ +_(one_map_register_fallback_threshold_reply) \ _(one_pitr_set_locator_set_reply) \ _(one_map_request_mode_reply) \ _(one_add_del_map_request_itr_rlocs_reply) \ @@ -4890,6 +4924,8 @@ _(ONE_ENABLE_DISABLE_REPLY, one_enable_disable_reply) \ _(ONE_MAP_REGISTER_ENABLE_DISABLE_REPLY, \ one_map_register_enable_disable_reply) \ _(ONE_MAP_REGISTER_SET_TTL_REPLY, one_map_register_set_ttl_reply) \ +_(ONE_MAP_REGISTER_FALLBACK_THRESHOLD_REPLY, \ + one_map_register_fallback_threshold_reply) \ _(ONE_RLOC_PROBE_ENABLE_DISABLE_REPLY, \ one_rloc_probe_enable_disable_reply) \ _(ONE_PITR_SET_LOCATOR_SET_REPLY, one_pitr_set_locator_set_reply) \ @@ -4937,6 +4973,8 @@ _(SHOW_ONE_RLOC_PROBE_STATE_REPLY, show_one_rloc_probe_state_reply) \ _(SHOW_ONE_MAP_REGISTER_STATE_REPLY, \ show_one_map_register_state_reply) \ _(SHOW_ONE_MAP_REGISTER_TTL_REPLY, show_one_map_register_ttl_reply) \ +_(SHOW_ONE_MAP_REGISTER_FALLBACK_THRESHOLD_REPLY, \ + show_one_map_register_fallback_threshold_reply) \ _(AF_PACKET_CREATE_REPLY, af_packet_create_reply) \ _(AF_PACKET_DELETE_REPLY, af_packet_delete_reply) \ _(POLICER_ADD_DEL_REPLY, policer_add_del_reply) \ @@ -16161,6 +16199,60 @@ api_lisp_gpe_add_del_iface (vat_main_t * vam) return ret; } +static int +api_one_map_register_fallback_threshold (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_map_register_fallback_threshold_t *mp; + u32 value = 0; + u8 is_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%u", &value)) + is_set = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!is_set) + { + errmsg ("fallback threshold value is missing!"); + return -99; + } + + M (ONE_MAP_REGISTER_FALLBACK_THRESHOLD, mp); + mp->value = clib_host_to_net_u32 (value); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_show_one_map_register_fallback_threshold (vat_main_t * vam) +{ + vl_api_show_one_map_register_fallback_threshold_t *mp; + int ret; + + M (SHOW_ONE_MAP_REGISTER_FALLBACK_THRESHOLD, mp); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + static int api_one_map_register_set_ttl (vat_main_t * vam) { @@ -20115,6 +20207,7 @@ _(one_add_del_map_resolver, " [del]") \ _(one_add_del_map_server, " [del]") \ _(one_enable_disable, "enable|disable") \ _(one_map_register_enable_disable, "enable|disable") \ +_(one_map_register_fallback_threshold, "") \ _(one_rloc_probe_enable_disable, "enable|disable") \ _(one_add_del_remote_mapping, "add|del vni eid " \ "[seid ] " \ @@ -20155,6 +20248,7 @@ _(show_one_pitr, "") \ _(show_one_use_petr, "") \ _(show_one_map_request_mode, "") \ _(show_one_map_register_ttl, "") \ +_(show_one_map_register_fallback_threshold, "") \ _(lisp_add_del_locator_set, "locator-set [iface |"\ " sw_if_index p " \ "w ] [del]") \ diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index a85656b3..72af525b 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -670,6 +670,9 @@ vnet_lisp_add_del_map_server (ip_address_t * addr, u8 is_add) memset (ms, 0, sizeof (*ms)); ip_address_copy (&ms->address, addr); vec_add1 (lcm->map_servers, ms[0]); + + if (vec_len (lcm->map_servers) == 1) + lcm->do_map_server_election = 1; } else { @@ -678,6 +681,9 @@ vnet_lisp_add_del_map_server (ip_address_t * addr, u8 is_add) ms = vec_elt_at_index (lcm->map_servers, i); if (!ip_address_cmp (&ms->address, addr)) { + if (!ip_address_cmp (&ms->address, &lcm->active_map_server)) + lcm->do_map_server_election = 1; + vec_del1 (lcm->map_servers, i); break; } @@ -1496,6 +1502,26 @@ vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add) return 0; } +int +vnet_lisp_map_register_fallback_threshold_set (u32 value) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + if (0 == value) + { + return VNET_API_ERROR_INVALID_ARGUMENT; + } + + lcm->max_expired_map_registers = value; + return 0; +} + +u32 +vnet_lisp_map_register_fallback_threshold_get (void) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + return lcm->max_expired_map_registers; +} + /** * Configure Proxy-ETR * @@ -2342,24 +2368,29 @@ reset_pending_mr_counters (pending_map_request_t * r) r->retries_num = 0; } -static int -elect_map_resolver (lisp_cp_main_t * lcm) -{ - lisp_msmr_t *mr; - - vec_foreach (mr, lcm->map_resolvers) - { - if (!mr->is_down) - { - ip_address_copy (&lcm->active_map_resolver, &mr->address); - lcm->do_map_resolver_election = 0; - return 1; - } - } - return 0; +#define foreach_msmr \ + _(server) \ + _(resolver) + +#define _(name) \ +static int \ +elect_map_ ## name (lisp_cp_main_t * lcm) \ +{ \ + lisp_msmr_t *mr; \ + vec_foreach (mr, lcm->map_ ## name ## s) \ + { \ + if (!mr->is_down) \ + { \ + ip_address_copy (&lcm->active_map_ ##name, &mr->address); \ + lcm->do_map_ ## name ## _election = 0; \ + return 1; \ + } \ + } \ + return 0; \ } - -static void +foreach_msmr +#undef _ + static void free_map_register_records (mapping_t * maps) { mapping_t *map; @@ -2488,31 +2519,32 @@ build_map_register (lisp_cp_main_t * lcm, ip_address_t * sloc, return b; } -static int -get_egress_map_resolver_ip (lisp_cp_main_t * lcm, ip_address_t * ip) -{ - lisp_msmr_t *mr; - while (lcm->do_map_resolver_election - | (0 == ip_fib_get_first_egress_ip_for_dst (lcm, - &lcm->active_map_resolver, - ip))) - { - if (0 == elect_map_resolver (lcm)) - /* all map resolvers are down */ - { - /* restart MR checking by marking all of them up */ - vec_foreach (mr, lcm->map_resolvers) mr->is_down = 0; - return -1; - } - } - return 0; +#define _(name) \ +static int \ +get_egress_map_ ##name## _ip (lisp_cp_main_t * lcm, ip_address_t * ip) \ +{ \ + lisp_msmr_t *mr; \ + while (lcm->do_map_ ## name ## _election \ + | (0 == ip_fib_get_first_egress_ip_for_dst \ + (lcm, &lcm->active_map_ ##name, ip))) \ + { \ + if (0 == elect_map_ ## name (lcm)) \ + /* all map resolvers/servers are down */ \ + { \ + /* restart MR/MS checking by marking all of them up */ \ + vec_foreach (mr, lcm->map_ ## name ## s) mr->is_down = 0; \ + return -1; \ + } \ + } \ + return 0; \ } +foreach_msmr +#undef _ /* CP output statistics */ #define foreach_lisp_cp_output_error \ _(MAP_REGISTERS_SENT, "map-registers sent") \ _(RLOC_PROBES_SENT, "rloc-probes sent") - static char *lisp_cp_output_error_strings[] = { #define _(sym,string) string, foreach_lisp_cp_output_error @@ -2588,7 +2620,6 @@ send_rloc_probe (lisp_cp_main_t * lcm, gid_address_t * deid, f->n_vectors = 1; vlib_put_frame_to_node (lcm->vlib_main, next_index, f); - hash_set (lcm->map_register_messages_by_nonce, nonce, 0); return 0; } @@ -2642,28 +2673,18 @@ send_rloc_probes (lisp_cp_main_t * lcm) static int send_map_register (lisp_cp_main_t * lcm, u8 want_map_notif) { + pending_map_register_t *pmr; u32 bi, map_registers_sent = 0; vlib_buffer_t *b; ip_address_t sloc; vlib_frame_t *f; u64 nonce = 0; u32 next_index, *to_next; - ip_address_t *ms = 0; mapping_t *records, *r, *group, *k; - // TODO: support multiple map servers and do election - if (0 == vec_len (lcm->map_servers)) + if (get_egress_map_server_ip (lcm, &sloc) < 0) return -1; - ms = &lcm->map_servers[0].address; - - if (0 == ip_fib_get_first_egress_ip_for_dst (lcm, ms, &sloc)) - { - clib_warning ("no eligible interface address found for %U!", - format_ip_address, &lcm->map_servers[0]); - return -1; - } - records = build_map_register_record_list (lcm); if (!records) return -1; @@ -2692,15 +2713,15 @@ send_map_register (lisp_cp_main_t * lcm, u8 want_map_notif) } } - b = build_map_register (lcm, &sloc, ms, &nonce, want_map_notif, group, - key_id, key, &bi); + b = build_map_register (lcm, &sloc, &lcm->active_map_server, &nonce, + want_map_notif, group, key_id, key, &bi); vec_free (group); if (!b) continue; vnet_buffer (b)->sw_if_index[VLIB_TX] = 0; - next_index = (ip_addr_version (&lcm->active_map_resolver) == IP4) ? + next_index = (ip_addr_version (&lcm->active_map_server) == IP4) ? ip4_lookup_node.index : ip6_lookup_node.index; f = vlib_get_frame_to_node (lcm->vlib_main, next_index); @@ -2712,7 +2733,11 @@ send_map_register (lisp_cp_main_t * lcm, u8 want_map_notif) vlib_put_frame_to_node (lcm->vlib_main, next_index, f); map_registers_sent++; - hash_set (lcm->map_register_messages_by_nonce, nonce, 0); + pool_get (lcm->pending_map_registers_pool, pmr); + memset (pmr, 0, sizeof (*pmr)); + pmr->time_to_expire = PENDING_MREG_EXPIRATION_TIME; + hash_set (lcm->map_register_messages_by_nonce, nonce, + pmr - lcm->pending_map_registers_pool); } free_map_register_records (records); @@ -3488,7 +3513,11 @@ process_map_notify (map_records_arg_t * a) } a->is_free = 1; + pool_put_index (lcm->pending_map_registers_pool, pmr_index[0]); hash_unset (lcm->map_register_messages_by_nonce, a->nonce); + + /* reset map-notify counter */ + lcm->expired_map_registers = 0; } static mapping_t * @@ -3635,8 +3664,8 @@ parse_map_notify (vlib_buffer_t * b) if (!is_auth_data_valid (mnotif_hdr, vlib_buffer_get_tail (b) - (u8 *) mnotif_hdr, key_id, key)) { - clib_warning ("Map-notify auth data verification failed for nonce %lu!", - a->nonce); + clib_warning ("Map-notify auth data verification failed for nonce " + "0x%lx!", a->nonce); map_records_arg_free (a); return 0; } @@ -4000,9 +4029,11 @@ lisp_cp_init (vlib_main_t * vm) lcm->lisp_pitr = 0; lcm->flags = 0; memset (&lcm->active_map_resolver, 0, sizeof (lcm->active_map_resolver)); + memset (&lcm->active_map_server, 0, sizeof (lcm->active_map_server)); gid_dictionary_init (&lcm->mapping_index_by_gid); lcm->do_map_resolver_election = 1; + lcm->do_map_server_election = 1; lcm->map_request_mode = MR_MODE_DST_ONLY; num_threads = 1 /* main thread */ + vtm->n_threads; @@ -4021,6 +4052,8 @@ lisp_cp_init (vlib_main_t * vm) timing_wheel_init (&lcm->wheel, now, vm->clib_time.clocks_per_second); lcm->nsh_map_index = ~0; lcm->map_register_ttl = MAP_REGISTER_DEFAULT_TTL; + lcm->max_expired_map_registers = MAX_EXPIRED_MAP_REGISTERS_DEFAULT; + lcm->expired_map_registers = 0; return 0; } @@ -4180,7 +4213,7 @@ remove_dead_pending_map_requests (lisp_cp_main_t * lcm) /* *INDENT-ON* */ vec_foreach (pmr_index, to_be_removed) - pool_put_index (lcm->pending_map_requests_by_nonce, pmr_index[0]); + pool_put_index (lcm->pending_map_requests_pool, pmr_index[0]); vec_free (to_be_removed); } @@ -4201,15 +4234,98 @@ update_rloc_probing (lisp_cp_main_t * lcm, f64 dt) } } +static int +update_pending_map_register (pending_map_register_t * r, f64 dt, u8 * del_all) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + lisp_msmr_t *ms; + del_all[0] = 0; + + r->time_to_expire -= dt; + + if (r->time_to_expire < 0) + { + lcm->expired_map_registers++; + + if (lcm->expired_map_registers >= lcm->max_expired_map_registers) + { + ms = get_map_server (&lcm->active_map_server); + if (!ms) + { + clib_warning ("Map server %U not found - probably deleted " + "by the user recently.", format_ip_address, + &lcm->active_map_server); + } + else + { + clib_warning ("map server %U is unreachable, ignoring", + format_ip_address, &lcm->active_map_server); + + /* mark current map server unavailable so it won't be + * elected next time */ + ms->is_down = 1; + ms->last_update = vlib_time_now (lcm->vlib_main); + } + + elect_map_server (lcm); + + /* indication for deleting all pending map registers */ + del_all[0] = 1; + lcm->expired_map_registers = 0; + return 0; + } + else + { + /* delete pending map register */ + return 0; + } + } + return 1; +} + static void update_map_register (lisp_cp_main_t * lcm, f64 dt) { + u32 *to_be_removed = 0, *pmr_index; static f64 time_left = QUICK_MAP_REGISTER_INTERVAL; static u64 mreg_sent_counter = 0; + pending_map_register_t *pmr; + u8 del_all = 0; + if (!lcm->is_enabled || !lcm->map_registering) return; + /* *INDENT-OFF* */ + pool_foreach (pmr, lcm->pending_map_registers_pool, + ({ + if (!update_pending_map_register (pmr, dt, &del_all)) + { + if (del_all) + break; + vec_add1 (to_be_removed, pmr - lcm->pending_map_registers_pool); + } + })); + /* *INDENT-ON* */ + + if (del_all) + { + /* delete all pending map register messages so they won't + * trigger another map server election.. */ + pool_free (lcm->pending_map_registers_pool); + hash_free (lcm->map_register_messages_by_nonce); + + /* ..and trigger registration against next map server (if any) */ + time_left = 0; + } + else + { + vec_foreach (pmr_index, to_be_removed) + pool_put_index (lcm->pending_map_registers_pool, pmr_index[0]); + } + + vec_free (to_be_removed); + time_left -= dt; if (time_left <= 0) { diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index d030e588..7b0380fb 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -25,18 +25,22 @@ #define PENDING_MREQ_EXPIRATION_TIME 3.0 /* seconds */ #define PENDING_MREQ_QUEUE_LEN 5 -#define PENDING_MREG_EXPIRATION_TIME 3.0 /* seconds */ #define RLOC_PROBING_INTERVAL 60.0 /* when map-registration is enabled "quick registration" takes place first. In this mode ETR sends map-register messages at an increased frequency until specified message count is reached */ -#define QUICK_MAP_REGISTER_MSG_COUNT 3 +#define QUICK_MAP_REGISTER_MSG_COUNT 5 #define QUICK_MAP_REGISTER_INTERVAL 3.0 /* normal map-register period */ #define MAP_REGISTER_INTERVAL 60.0 +/* how many tries until next map-server election */ +#define MAX_EXPIRED_MAP_REGISTERS_DEFAULT 3 + +#define PENDING_MREG_EXPIRATION_TIME 3.0 /* seconds */ + /* 24 hours */ #define MAP_REGISTER_DEFAULT_TTL 86400 @@ -51,6 +55,11 @@ typedef struct u8 to_be_removed; } pending_map_request_t; +typedef struct +{ + f64 time_to_expire; +} pending_map_register_t; + typedef struct { gid_address_t leid; @@ -180,6 +189,9 @@ typedef struct /* pool of pending map requests */ pending_map_request_t *pending_map_requests_pool; + /* pool of pending map registers */ + pending_map_register_t *pending_map_registers_pool; + /* hash map of sent map register messages */ uword *map_register_messages_by_nonce; @@ -194,8 +206,10 @@ typedef struct * since the vector may be modified during request resend/retry procedure * and break things :-) */ ip_address_t active_map_resolver; + ip_address_t active_map_server; u8 do_map_resolver_election; + u8 do_map_server_election; /* map-request locator set index */ u32 mreq_itr_rlocs; @@ -241,6 +255,10 @@ typedef struct /* TTL used for all mappings when registering */ u32 map_register_ttl; + /* control variables for map server election */ + u32 max_expired_map_registers; + u32 expired_map_registers; + /* commodity */ ip4_main_t *im4; ip6_main_t *im6; @@ -367,6 +385,8 @@ lisp_api_l2_arp_entry_t *vnet_lisp_l2_arp_entries_get_by_bd (u32 bd); int vnet_lisp_nsh_set_locator_set (u8 * locator_set_name, u8 is_add); int vnet_lisp_map_register_set_ttl (u32 ttl); u32 vnet_lisp_map_register_get_ttl (void); +int vnet_lisp_map_register_fallback_threshold_set (u32 value); +u32 vnet_lisp_map_register_fallback_threshold_get (void); map_records_arg_t *parse_map_reply (vlib_buffer_t * b); diff --git a/src/vnet/lisp-cp/one.api b/src/vnet/lisp-cp/one.api index 5087c634..3fcc9da2 100644 --- a/src/vnet/lisp-cp/one.api +++ b/src/vnet/lisp-cp/one.api @@ -942,6 +942,26 @@ define show_one_stats_enable_disable_reply u8 is_en; }; +autoreply define one_map_register_fallback_threshold +{ + u32 client_index; + u32 context; + u32 value; +}; + +define show_one_map_register_fallback_threshold +{ + u32 client_index; + u32 context; +}; + +define show_one_map_register_fallback_threshold_reply +{ + u32 context; + i32 retval; + u32 value; +}; + /* * Local Variables: * eval: (c-set-style "gnu") diff --git a/src/vnet/lisp-cp/one_api.c b/src/vnet/lisp-cp/one_api.c index db443b51..6117f935 100644 --- a/src/vnet/lisp-cp/one_api.c +++ b/src/vnet/lisp-cp/one_api.c @@ -87,6 +87,8 @@ _(ONE_ADD_DEL_MAP_SERVER, one_add_del_map_server) \ _(ONE_ENABLE_DISABLE, one_enable_disable) \ _(ONE_RLOC_PROBE_ENABLE_DISABLE, one_rloc_probe_enable_disable) \ _(ONE_MAP_REGISTER_ENABLE_DISABLE, one_map_register_enable_disable) \ +_(ONE_MAP_REGISTER_FALLBACK_THRESHOLD, \ + one_map_register_fallback_threshold) \ _(ONE_ADD_DEL_REMOTE_MAPPING, one_add_del_remote_mapping) \ _(ONE_ADD_DEL_ADJACENCY, one_add_del_adjacency) \ _(ONE_PITR_SET_LOCATOR_SET, one_pitr_set_locator_set) \ @@ -106,6 +108,8 @@ _(SHOW_ONE_NSH_MAPPING, show_one_nsh_mapping) \ _(SHOW_ONE_RLOC_PROBE_STATE, show_one_rloc_probe_state) \ _(SHOW_ONE_MAP_REGISTER_STATE, show_one_map_register_state) \ _(SHOW_ONE_MAP_REGISTER_TTL, show_one_map_register_ttl) \ +_(SHOW_ONE_MAP_REGISTER_FALLBACK_THRESHOLD, \ + show_one_map_register_fallback_threshold) \ _(SHOW_ONE_STATUS, show_one_status) \ _(ONE_ADD_DEL_MAP_REQUEST_ITR_RLOCS, \ one_add_del_map_request_itr_rlocs) \ @@ -1604,6 +1608,35 @@ vl_api_one_l2_arp_entries_get_t_handler (vl_api_one_l2_arp_entries_get_t * mp) vec_free (entries); } +static void + vl_api_one_map_register_fallback_threshold_t_handler + (vl_api_one_map_register_fallback_threshold_t * mp) +{ + vl_api_one_map_register_fallback_threshold_reply_t *rmp; + int rv = 0; + + mp->value = clib_net_to_host_u32 (mp->value); + rv = vnet_lisp_map_register_fallback_threshold_set (mp->value); + REPLY_MACRO (VL_API_ONE_MAP_REGISTER_FALLBACK_THRESHOLD); +} + +static void + vl_api_show_one_map_register_fallback_threshold_t_handler + (vl_api_show_one_map_register_fallback_threshold_t * mp) +{ + vl_api_show_one_map_register_fallback_threshold_reply_t *rmp; + int rv = 0; + + u32 value = vnet_lisp_map_register_fallback_threshold_get (); + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_SHOW_ONE_MAP_REGISTER_FALLBACK_THRESHOLD_REPLY, + ({ + rmp->value = clib_host_to_net_u32 (value); + })); + /* *INDENT-ON* */ +} + /* * one_api_hookup * Add vpe's API message handlers to the table. diff --git a/src/vnet/lisp-cp/one_cli.c b/src/vnet/lisp-cp/one_cli.c index 3b411899..e165f71c 100644 --- a/src/vnet/lisp-cp/one_cli.c +++ b/src/vnet/lisp-cp/one_cli.c @@ -777,6 +777,70 @@ VLIB_CLI_COMMAND (one_nsh_set_locator_set_command) = { }; /* *INDENT-ON* */ +static clib_error_t * +lisp_map_register_fallback_threshold_show_command_fn (vlib_main_t * vm, + unformat_input_t * + input, + vlib_cli_command_t * + cmd) +{ + u32 val = vnet_lisp_map_register_fallback_threshold_get (); + vlib_cli_output (vm, "map register fallback treshold value: %d", val); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (one_map_register_fallback_threshold_show_command) = { + .path = "show one map-register fallback-threshold", + .short_help = "show one map-register fallback-threshold", + .function = lisp_map_register_fallback_threshold_show_command_fn, +}; + +/* *INDENT-ON* */ + +static clib_error_t * +lisp_map_register_fallback_threshold_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + clib_error_t *error = 0; + u32 val = 0; + int rv = 0; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%d", &val)) + ; + else + { + error = clib_error_return (0, "parse error"); + goto done; + } + } + + rv = vnet_lisp_map_register_fallback_threshold_set (val); + if (rv) + { + error = clib_error_return (0, "setting fallback threshold failed!"); + } + +done: + unformat_free (line_input); + return error; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (one_map_register_fallback_threshold_command) = { + .path = "one map-register fallback-threshold", + .short_help = "one map-register fallback-threshold ", + .function = lisp_map_register_fallback_threshold_command_fn, +}; +/* *INDENT-ON* */ static clib_error_t * lisp_pitr_set_locator_set_command_fn (vlib_main_t * vm, -- cgit 1.2.3-korg From 809bc74b5b73634678e6f1444344fd1c0a89e877 Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Mon, 14 Aug 2017 19:15:36 +0200 Subject: LISP: re-fetch mapping before it expires Change-Id: I0581a1bddad55d8d573c546ec84b0b2760abab3d Signed-off-by: Filip Tehlar --- src/vnet/lisp-cp/control.c | 322 +++++++++++++++++++---------- src/vnet/lisp-cp/control.h | 8 +- src/vnet/lisp-cp/lisp_api.c | 15 +- src/vnet/lisp-cp/lisp_cli.c | 15 +- src/vnet/lisp-cp/lisp_types.h | 6 +- src/vnet/lisp-cp/one_api.c | 15 +- src/vnet/lisp-cp/one_cli.c | 15 +- src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c | 60 ++++-- src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h | 10 + src/vnet/lisp-gpe/lisp_gpe_sub_interface.c | 2 +- 10 files changed, 330 insertions(+), 138 deletions(-) (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index 59a45ed8..c811e789 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -30,9 +30,14 @@ #define MAX_VALUE_U24 0xffffff +/* mapping timer control constants (in seconds) */ +#define TIME_UNTIL_REFETCH_OR_DELETE 20 +#define MAPPING_TIMEOUT (((m->ttl) * 60) - TIME_UNTIL_REFETCH_OR_DELETE) + lisp_cp_main_t lisp_control_main; u8 *format_lisp_cp_input_trace (u8 * s, va_list * args); +static void *send_map_request_thread_fn (void *arg); typedef enum { @@ -1102,7 +1107,7 @@ remove_overlapping_sub_prefixes (lisp_cp_main_t * lcm, gid_address_t * eid, if (vnet_lisp_add_del_adjacency (adj_args)) clib_warning ("failed to del adjacency!"); - vnet_lisp_add_del_mapping (e, 0, 0, 0, 0, 0 /* is add */ , 0, 0); + vnet_lisp_del_mapping (e, NULL); } vec_free (a.eids_to_be_deleted); @@ -1129,24 +1134,19 @@ is_local_ip (lisp_cp_main_t * lcm, ip_address_t * addr) } /** - * Adds/removes/updates mapping. Does not program forwarding. + * Adds/updates mapping. Does not program forwarding. * - * @param eid end-host identifier + * @param a parameters of the new mapping * @param rlocs vector of remote locators - * @param action action for negative map-reply - * @param is_add add mapping if non-zero, delete otherwise - * @param res_map_index the map-index that was created/updated/removed. It is - * set to ~0 if no action is taken. - * @param is_static used for distinguishing between statically learned - remote mappings and mappings obtained from MR + * @param res_map_index index of the newly created mapping + * @param locators_changed indicator if locators were updated in the mapping * @return return code */ int -vnet_lisp_add_del_mapping (gid_address_t * eid, locator_t * rlocs, u8 action, - u8 authoritative, u32 ttl, u8 is_add, u8 is_static, - u32 * res_map_index) +vnet_lisp_add_mapping (vnet_lisp_add_del_mapping_args_t * a, + locator_t * rlocs, + u32 * res_map_index, u8 * is_updated) { - vnet_lisp_add_del_mapping_args_t _m_args, *m_args = &_m_args; vnet_lisp_add_del_locator_set_args_t _ls_args, *ls_args = &_ls_args; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); u32 mi, ls_index = 0, dst_map_index; @@ -1161,115 +1161,138 @@ vnet_lisp_add_del_mapping (gid_address_t * eid, locator_t * rlocs, u8 action, if (res_map_index) res_map_index[0] = ~0; + if (is_updated) + is_updated[0] = 0; - memset (m_args, 0, sizeof (m_args[0])); memset (ls_args, 0, sizeof (ls_args[0])); ls_args->locators = rlocs; - - mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid); + mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->eid); old_map = ((u32) ~ 0 != mi) ? pool_elt_at_index (lcm->mapping_pool, mi) : 0; - if (is_add) - { - /* check if none of the locators match localy configured address */ - vec_foreach (loc, rlocs) + /* check if none of the locators match localy configured address */ + vec_foreach (loc, rlocs) + { + ip_prefix_t *p = &gid_address_ippref (&loc->address); + if (is_local_ip (lcm, &ip_prefix_addr (p))) { - ip_prefix_t *p = &gid_address_ippref (&loc->address); - if (is_local_ip (lcm, &ip_prefix_addr (p))) - { - clib_warning ("RLOC %U matches a local address!", - format_gid_address, &loc->address); - return VNET_API_ERROR_LISP_RLOC_LOCAL; - } + clib_warning ("RLOC %U matches a local address!", + format_gid_address, &loc->address); + return VNET_API_ERROR_LISP_RLOC_LOCAL; } + } - /* overwrite: if mapping already exists, decide if locators should be - * updated and be done */ - if (old_map && gid_address_cmp (&old_map->eid, eid) == 0) + /* overwrite: if mapping already exists, decide if locators should be + * updated and be done */ + if (old_map && gid_address_cmp (&old_map->eid, &a->eid) == 0) + { + if (!a->is_static && (old_map->is_static || old_map->local)) { - if (!is_static && (old_map->is_static || old_map->local)) - { - /* do not overwrite local or static remote mappings */ - clib_warning ("mapping %U rejected due to collision with local " - "or static remote mapping!", format_gid_address, - eid); - return 0; - } - - locator_set_t *old_ls; - - /* update mapping attributes */ - old_map->action = action; - old_map->authoritative = authoritative; - old_map->ttl = ttl; - - old_ls = pool_elt_at_index (lcm->locator_set_pool, - old_map->locator_set_index); - if (compare_locators (lcm, old_ls->locator_indices, - ls_args->locators)) - { - /* set locator-set index to overwrite */ - ls_args->is_add = 1; - ls_args->index = old_map->locator_set_index; - vnet_lisp_add_del_locator_set (ls_args, 0); - if (res_map_index) - res_map_index[0] = mi; - } + /* do not overwrite local or static remote mappings */ + clib_warning ("mapping %U rejected due to collision with local " + "or static remote mapping!", format_gid_address, + &a->eid); + return 0; } - /* new mapping */ - else - { - remove_overlapping_sub_prefixes (lcm, eid, 0 == ls_args->locators); - ls_args->is_add = 1; - ls_args->index = ~0; + locator_set_t *old_ls; - vnet_lisp_add_del_locator_set (ls_args, &ls_index); + /* update mapping attributes */ + old_map->action = a->action; + if (old_map->action != a->action && NULL != is_updated) + is_updated[0] = 1; - /* add mapping */ - gid_address_copy (&m_args->eid, eid); - m_args->is_add = 1; - m_args->action = action; - m_args->locator_set_index = ls_index; - m_args->is_static = is_static; - m_args->ttl = ttl; - vnet_lisp_map_cache_add_del (m_args, &dst_map_index); + old_map->authoritative = a->authoritative; + old_map->ttl = a->ttl; - if (res_map_index) - res_map_index[0] = dst_map_index; + old_ls = pool_elt_at_index (lcm->locator_set_pool, + old_map->locator_set_index); + if (compare_locators (lcm, old_ls->locator_indices, ls_args->locators)) + { + /* set locator-set index to overwrite */ + ls_args->is_add = 1; + ls_args->index = old_map->locator_set_index; + vnet_lisp_add_del_locator_set (ls_args, 0); + if (is_updated) + is_updated[0] = 1; } + if (res_map_index) + res_map_index[0] = mi; } + /* new mapping */ else { - if (old_map == 0 || gid_address_cmp (&old_map->eid, eid) != 0) - { - clib_warning ("cannot delete mapping for eid %U", - format_gid_address, eid); - return -1; - } - - m_args->is_add = 0; - gid_address_copy (&m_args->eid, eid); - m_args->locator_set_index = old_map->locator_set_index; + remove_overlapping_sub_prefixes (lcm, &a->eid, 0 == ls_args->locators); - /* delete mapping associated from map-cache */ - vnet_lisp_map_cache_add_del (m_args, 0); + ls_args->is_add = 1; + ls_args->index = ~0; - ls_args->is_add = 0; - ls_args->index = old_map->locator_set_index; - /* delete locator set */ - vnet_lisp_add_del_locator_set (ls_args, 0); + vnet_lisp_add_del_locator_set (ls_args, &ls_index); - /* delete timer associated to the mapping if any */ - if (old_map->timer_set) - mapping_delete_timer (lcm, mi); + /* add mapping */ + a->is_add = 1; + a->locator_set_index = ls_index; + vnet_lisp_map_cache_add_del (a, &dst_map_index); - /* return old mapping index */ if (res_map_index) - res_map_index[0] = mi; + res_map_index[0] = dst_map_index; + } + + /* success */ + return 0; +} + +/** + * Removes a mapping. Does not program forwarding. + * + * @param eid end-host indetifier + * @param res_map_index index of the removed mapping + * @return return code + */ +int +vnet_lisp_del_mapping (gid_address_t * eid, u32 * res_map_index) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + vnet_lisp_add_del_mapping_args_t _m_args, *m_args = &_m_args; + vnet_lisp_add_del_locator_set_args_t _ls_args, *ls_args = &_ls_args; + mapping_t *old_map; + u32 mi; + + memset (m_args, 0, sizeof (m_args[0])); + if (res_map_index) + res_map_index[0] = ~0; + + mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid); + old_map = ((u32) ~ 0 != mi) ? pool_elt_at_index (lcm->mapping_pool, mi) : 0; + + if (old_map == 0 || gid_address_cmp (&old_map->eid, eid) != 0) + { + clib_warning ("cannot delete mapping for eid %U", + format_gid_address, eid); + return -1; } + m_args->is_add = 0; + gid_address_copy (&m_args->eid, eid); + m_args->locator_set_index = old_map->locator_set_index; + + /* delete mapping associated from map-cache */ + vnet_lisp_map_cache_add_del (m_args, 0); + + ls_args->is_add = 0; + ls_args->index = old_map->locator_set_index; + + /* delete locator set */ + vnet_lisp_add_del_locator_set (ls_args, 0); + + /* delete timer associated to the mapping if any */ + if (old_map->timer_set) + mapping_delete_timer (lcm, mi); + + /* return old mapping index */ + if (res_map_index) + res_map_index[0] = mi; + /* success */ return 0; } @@ -3372,8 +3395,7 @@ remove_expired_mapping (lisp_cp_main_t * lcm, u32 mi) if (vnet_lisp_add_del_adjacency (adj_args)) clib_warning ("failed to del adjacency!"); - vnet_lisp_add_del_mapping (&m->eid, 0, 0, 0, ~0, 0 /* is_add */ , - 0 /* is_static */ , 0); + vnet_lisp_del_mapping (&m->eid, NULL); mapping_delete_timer (lcm, mi); } @@ -3392,6 +3414,73 @@ mapping_start_expiration_timer (lisp_cp_main_t * lcm, u32 mi, timing_wheel_insert (&lcm->wheel, exp_clock_time, mi); } +static void +process_expired_mapping (lisp_cp_main_t * lcm, u32 mi) +{ + int rv; + vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a; + mapping_t *m = pool_elt_at_index (lcm->mapping_pool, mi); + uword *fei; + fwd_entry_t *fe; + vlib_counter_t c; + u8 have_stats = 0; + + if (m->delete_after_expiration) + { + remove_expired_mapping (lcm, mi); + return; + } + + fei = hash_get (lcm->fwd_entry_by_mapping_index, mi); + if (!fei) + return; + + fe = pool_elt_at_index (lcm->fwd_entry_pool, fei[0]); + + memset (a, 0, sizeof (*a)); + a->rmt_eid = fe->reid; + if (fe->is_src_dst) + a->lcl_eid = fe->leid; + a->vni = gid_address_vni (&fe->reid); + + rv = vnet_lisp_gpe_get_fwd_stats (a, &c); + if (0 == rv) + have_stats = 1; + + if (m->almost_expired) + { + m->almost_expired = 0; /* reset flag */ + if (have_stats) + { + if (m->packets != c.packets) + { + /* mapping is in use, re-fetch */ + map_request_args_t mr_args; + memset (&mr_args, 0, sizeof (mr_args)); + mr_args.seid = fe->leid; + mr_args.deid = fe->reid; + + send_map_request_thread_fn (&mr_args); + } + else + remove_expired_mapping (lcm, mi); + } + else + remove_expired_mapping (lcm, mi); + } + else + { + m->almost_expired = 1; + mapping_start_expiration_timer (lcm, mi, TIME_UNTIL_REFETCH_OR_DELETE); + + if (have_stats) + /* save counter */ + m->packets = c.packets; + else + m->delete_after_expiration = 1; + } +} + static void map_records_arg_free (map_records_arg_t * a) { @@ -3414,6 +3503,7 @@ process_map_reply (map_records_arg_t * a) pending_map_request_t *pmr; u64 *noncep; uword *pmr_index; + u8 is_changed = 0; if (a->is_rloc_probe) goto done; @@ -3429,26 +3519,36 @@ process_map_reply (map_records_arg_t * a) vec_foreach (m, a->mappings) { + vnet_lisp_add_del_mapping_args_t _m_args, *m_args = &_m_args; + memset (m_args, 0, sizeof (m_args[0])); + gid_address_copy (&m_args->eid, &m->eid); + m_args->action = m->action; + m_args->authoritative = m->authoritative; + m_args->ttl = m->ttl; + m_args->is_static = 0; + /* insert/update mappings cache */ - vnet_lisp_add_del_mapping (&m->eid, m->locators, m->action, - m->authoritative, m->ttl, - 1, 0 /* is_static */ , &dst_map_index); + vnet_lisp_add_mapping (m_args, m->locators, &dst_map_index, &is_changed); if (dst_map_index == (u32) ~ 0) continue; - /* try to program forwarding only if mapping saved or updated */ - vnet_lisp_add_del_adjacency_args_t _adj_args, *adj_args = &_adj_args; - memset (adj_args, 0, sizeof (adj_args[0])); + if (is_changed) + { + /* try to program forwarding only if mapping saved or updated */ + vnet_lisp_add_del_adjacency_args_t _adj_args, *adj_args = &_adj_args; + memset (adj_args, 0, sizeof (adj_args[0])); - gid_address_copy (&adj_args->leid, &pmr->src); - gid_address_copy (&adj_args->reid, &m->eid); - adj_args->is_add = 1; - if (vnet_lisp_add_del_adjacency (adj_args)) - clib_warning ("failed to add adjacency!"); + gid_address_copy (&adj_args->leid, &pmr->src); + gid_address_copy (&adj_args->reid, &m->eid); + adj_args->is_add = 1; + + if (vnet_lisp_add_del_adjacency (adj_args)) + clib_warning ("failed to add adjacency!"); + } if ((u32) ~ 0 != m->ttl) - mapping_start_expiration_timer (lcm, dst_map_index, m->ttl * 60); + mapping_start_expiration_timer (lcm, dst_map_index, MAPPING_TIMEOUT); } /* remove pending map request entry */ @@ -4379,7 +4479,7 @@ send_map_resolver_service (vlib_main_t * vm, u32 *mi = 0; vec_foreach (mi, expired) { - remove_expired_mapping (lcm, mi[0]); + process_expired_mapping (lcm, mi[0]); } _vec_len (expired) = 0; } diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index 7b0380fb..a3e2fc25 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -329,9 +329,11 @@ vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a, u32 * map_index_result); int -vnet_lisp_add_del_mapping (gid_address_t * deid, locator_t * dlocs, u8 action, - u8 authoritative, u32 ttl, u8 is_add, u8 is_static, - u32 * res_map_index); +vnet_lisp_add_mapping (vnet_lisp_add_del_mapping_args_t * a, + locator_t * rlocs, u32 * res_map_index, + u8 * is_changed); + +int vnet_lisp_del_mapping (gid_address_t * eid, u32 * res_map_index); typedef struct { diff --git a/src/vnet/lisp-cp/lisp_api.c b/src/vnet/lisp-cp/lisp_api.c index 6c82d4cf..f7c41971 100644 --- a/src/vnet/lisp-cp/lisp_api.c +++ b/src/vnet/lisp-cp/lisp_api.c @@ -521,8 +521,19 @@ static void /* NOTE: for now this works as a static remote mapping, i.e., * not authoritative and ttl infinite. */ - rv = vnet_lisp_add_del_mapping (eid, rlocs, mp->action, 0, ~0, - mp->is_add, 1 /* is_static */ , 0); + if (mp->is_add) + { + vnet_lisp_add_del_mapping_args_t _m_args, *m_args = &_m_args; + memset (m_args, 0, sizeof (m_args[0])); + gid_address_copy (&m_args->eid, eid); + m_args->action = mp->action; + m_args->is_static = 1; + m_args->ttl = ~0; + m_args->authoritative = 0; + rv = vnet_lisp_add_mapping (m_args, rlocs, NULL, NULL); + } + else + rv = vnet_lisp_del_mapping (eid, NULL); if (mp->del_all) vnet_lisp_clear_all_remote_adjacencies (); diff --git a/src/vnet/lisp-cp/lisp_cli.c b/src/vnet/lisp-cp/lisp_cli.c index 05df9fb6..50904601 100644 --- a/src/vnet/lisp-cp/lisp_cli.c +++ b/src/vnet/lisp-cp/lisp_cli.c @@ -394,8 +394,19 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm, /* add as static remote mapping, i.e., not authoritative and infinite * ttl */ - rv = vnet_lisp_add_del_mapping (&eid, rlocs, action, 0, ~0, is_add, - 1 /* is_static */ , 0); + if (is_add) + { + vnet_lisp_add_del_mapping_args_t _map_args, *map_args = &_map_args; + memset (map_args, 0, sizeof (map_args[0])); + gid_address_copy (&map_args->eid, &eid); + map_args->action = action; + map_args->is_static = 1; + map_args->authoritative = 0; + map_args->ttl = ~0; + rv = vnet_lisp_add_mapping (map_args, rlocs, NULL, NULL); + } + else + rv = vnet_lisp_del_mapping (&eid, NULL); if (rv) clib_warning ("failed to %s remote mapping!", is_add ? "add" : "delete"); diff --git a/src/vnet/lisp-cp/lisp_types.h b/src/vnet/lisp-cp/lisp_types.h index b7ad0f27..b17110f6 100644 --- a/src/vnet/lisp-cp/lisp_types.h +++ b/src/vnet/lisp-cp/lisp_types.h @@ -358,12 +358,14 @@ typedef struct u8 is_static:1; u8 pitr_set:1; u8 nsh_set:1; - u8 rsvd:3; - + u8 almost_expired:1; + u8 delete_after_expiration:1; + u8 rsvd:1; u8 *key; lisp_key_type_t key_id; u8 timer_set; + counter_t packets; } mapping_t; uword diff --git a/src/vnet/lisp-cp/one_api.c b/src/vnet/lisp-cp/one_api.c index 620d56fb..b8e3f704 100644 --- a/src/vnet/lisp-cp/one_api.c +++ b/src/vnet/lisp-cp/one_api.c @@ -620,8 +620,19 @@ static void /* NOTE: for now this works as a static remote mapping, i.e., * not authoritative and ttl infinite. */ - rv = vnet_lisp_add_del_mapping (eid, rlocs, mp->action, 0, ~0, - mp->is_add, 1 /* is_static */ , 0); + if (mp->is_add) + { + vnet_lisp_add_del_mapping_args_t _m_args, *m_args = &_m_args; + memset (m_args, 0, sizeof (m_args[0])); + gid_address_copy (&m_args->eid, eid); + m_args->action = mp->action; + m_args->is_static = 1; + m_args->ttl = ~0; + m_args->authoritative = 0; + rv = vnet_lisp_add_mapping (m_args, rlocs, NULL, NULL); + } + else + rv = vnet_lisp_del_mapping (eid, NULL); if (mp->del_all) vnet_lisp_clear_all_remote_adjacencies (); diff --git a/src/vnet/lisp-cp/one_cli.c b/src/vnet/lisp-cp/one_cli.c index e165f71c..3e0c4c0a 100644 --- a/src/vnet/lisp-cp/one_cli.c +++ b/src/vnet/lisp-cp/one_cli.c @@ -487,8 +487,19 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm, /* add as static remote mapping, i.e., not authoritative and infinite * ttl */ - rv = vnet_lisp_add_del_mapping (&eid, rlocs, action, 0, ~0, is_add, - 1 /* is_static */ , 0); + if (is_add) + { + vnet_lisp_add_del_mapping_args_t _map_args, *map_args = &_map_args; + memset (map_args, 0, sizeof (map_args[0])); + gid_address_copy (&map_args->eid, &eid); + map_args->action = action; + map_args->is_static = 1; + map_args->authoritative = 0; + map_args->ttl = ~0; + rv = vnet_lisp_add_mapping (map_args, rlocs, NULL, NULL); + } + else + rv = vnet_lisp_del_mapping (&eid, NULL); if (rv) clib_warning ("failed to %s remote mapping!", is_add ? "add" : "delete"); diff --git a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c index ac048149..d7d3cb86 100644 --- a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c +++ b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c @@ -193,12 +193,15 @@ ip_src_dst_fib_del_route (u32 src_fib_index, * @param[in] src_fib_index The index/ID of the SRC FIB * @param[in] src_prefix Source IP prefix. * @param[in] src_dpo The DPO the route will link to. + * + * @return fib index of the inserted prefix */ -static void +static fib_node_index_t ip_src_fib_add_route_w_dpo (u32 src_fib_index, const ip_prefix_t * src_prefix, const dpo_id_t * src_dpo) { + fib_node_index_t fei = ~0; fib_prefix_t src_fib_prefix; ip_prefix_to_fib_prefix (src_prefix, &src_fib_prefix); @@ -213,11 +216,13 @@ ip_src_fib_add_route_w_dpo (u32 src_fib_index, if (FIB_NODE_INDEX_INVALID == src_fei || !fib_entry_is_sourced (src_fei, FIB_SOURCE_LISP)) { - fib_table_entry_special_dpo_add (src_fib_index, - &src_fib_prefix, - FIB_SOURCE_LISP, - FIB_ENTRY_FLAG_EXCLUSIVE, src_dpo); + fei = fib_table_entry_special_dpo_add (src_fib_index, + &src_fib_prefix, + FIB_SOURCE_LISP, + FIB_ENTRY_FLAG_EXCLUSIVE, + src_dpo); } + return fei; } static fib_route_path_t * @@ -262,7 +267,7 @@ lisp_gpe_mk_fib_paths (const lisp_fwd_path_t * paths) * @param[in] paths The paths from which to construct the * load balance */ -static void +static fib_node_index_t ip_src_fib_add_route (u32 src_fib_index, const ip_prefix_t * src_prefix, const lisp_fwd_path_t * paths) @@ -274,10 +279,11 @@ ip_src_fib_add_route (u32 src_fib_index, rpaths = lisp_gpe_mk_fib_paths (paths); - fib_table_entry_update (src_fib_index, - &src_fib_prefix, - FIB_SOURCE_LISP, FIB_ENTRY_FLAG_NONE, rpaths); + fib_node_index_t fib_entry_index = + fib_table_entry_update (src_fib_index, &src_fib_prefix, FIB_SOURCE_LISP, + FIB_ENTRY_FLAG_NONE, rpaths); vec_free (rpaths); + return fib_entry_index; } static void @@ -311,9 +317,11 @@ gpe_native_fwd_add_del_lfe (lisp_gpe_fwd_entry_t * lfe, u8 is_add) } } -static void +static index_t create_fib_entries (lisp_gpe_fwd_entry_t * lfe) { + fib_node_index_t fi; + fib_entry_t *fe; lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); dpo_proto_t dproto; ip_prefix_t ippref; @@ -361,13 +369,15 @@ create_fib_entries (lisp_gpe_fwd_entry_t * lfe) dpo_copy (&dpo, drop_dpo_get (dproto)); break; } - ip_src_fib_add_route_w_dpo (lfe->src_fib_index, &ippref, &dpo); + fi = ip_src_fib_add_route_w_dpo (lfe->src_fib_index, &ippref, &dpo); dpo_reset (&dpo); } else { - ip_src_fib_add_route (lfe->src_fib_index, &ippref, lfe->paths); + fi = ip_src_fib_add_route (lfe->src_fib_index, &ippref, lfe->paths); } + fe = fib_entry_get (fi); + return fe->fe_lb.dpoi_index; } static void @@ -546,7 +556,7 @@ add_ip_fwd_entry (lisp_gpe_main_t * lgm, lfe->action = a->action; } - create_fib_entries (lfe); + lfe->dpoi_index = create_fib_entries (lfe); return (0); } @@ -793,6 +803,7 @@ lisp_gpe_l2_update_fwding (lisp_gpe_fwd_entry_t * lfe) lisp_l2_fib_add_del_entry (lfe->l2.eid_bd_index, fid_addr_mac (&lfe->key->lcl), fid_addr_mac (&lfe->key->rmt), &dpo, 1); + lfe->dpoi_index = dpo.dpoi_index; dpo_reset (&dpo); } @@ -1538,6 +1549,29 @@ vnet_lisp_gpe_fwd_entries_get_by_vni (u32 vni) return entries; } +int +vnet_lisp_gpe_get_fwd_stats (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, + vlib_counter_t * c) +{ + lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); + lisp_gpe_fwd_entry_t *lfe; + lisp_gpe_fwd_entry_key_t unused; + + lfe = find_fwd_entry (lgm, a, &unused); + if (NULL == lfe) + return -1; + + if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE == lfe->type) + return -1; + + if (~0 == lfe->dpoi_index) + return -1; + + vlib_get_combined_counter (&load_balance_main.lbm_to_counters, + lfe->dpoi_index, c); + return 0; +} + VLIB_INIT_FUNCTION (lisp_gpe_fwd_entry_init); /* diff --git a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h index 15803516..dfdb8b91 100644 --- a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h +++ b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h @@ -198,6 +198,12 @@ typedef struct lisp_gpe_fwd_entry_t_ */ negative_fwd_actions_e action; }; + + /** + * used for getting load balance statistics + */ + index_t dpoi_index; + } lisp_gpe_fwd_entry_t; extern int @@ -219,6 +225,10 @@ vnet_lisp_gpe_add_fwd_counters (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, u32 fwd_entry_index); extern u32 *vnet_lisp_gpe_get_fwd_entry_vnis (void); +int +vnet_lisp_gpe_get_fwd_stats (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, + vlib_counter_t * c); + #endif /* diff --git a/src/vnet/lisp-gpe/lisp_gpe_sub_interface.c b/src/vnet/lisp-gpe/lisp_gpe_sub_interface.c index 7146b380..b234d9dc 100644 --- a/src/vnet/lisp-gpe/lisp_gpe_sub_interface.c +++ b/src/vnet/lisp-gpe/lisp_gpe_sub_interface.c @@ -192,7 +192,7 @@ lisp_gpe_sub_interface_unlock (index_t l3si) lisp_gpe_sub_interface_unset_table (l3s->sw_if_index, l3s->eid_table_id); - lisp_gpe_tenant_l3_iface_unlock (clib_net_to_host_u32 (l3s->key->vni)); + lisp_gpe_tenant_l3_iface_unlock (l3s->key->vni); vnet_sw_interface_set_flags (vnet_get_main (), l3s->sw_if_index, 0); vnet_delete_sub_interface (l3s->sw_if_index); -- cgit 1.2.3-korg From 8d66f9d3f83a419fde67efbb2ee8697038922b7a Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez-Natal Date: Sat, 9 Sep 2017 14:15:15 -0700 Subject: Remove associated lisp-gpe entries when removing lisp local mapping. Change-Id: Ifda4d22c9d1de210165932a0996f75cc8428ae7a Signed-off-by: Alberto Rodriguez-Natal --- src/vnet/lisp-cp/control.c | 77 +++++++++++++++++++++++++++++++++++++++++----- src/vnet/lisp-cp/control.h | 6 ++++ 2 files changed, 76 insertions(+), 7 deletions(-) (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index c811e789..74597a6b 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -265,7 +265,7 @@ dp_add_del_iface (lisp_cp_main_t * lcm, u32 vni, u8 is_l2, u8 is_add) } static void -dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index) +dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 dst_map_index) { vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a; fwd_entry_t *fe = 0; @@ -438,8 +438,8 @@ dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index) vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a; gid_address_t *rmt_eid, *lcl_eid; mapping_t *lcl_map, *rmt_map; - u32 sw_if_index; - uword *feip = 0, *dpid; + u32 sw_if_index, **rmts, rmts_idx; + uword *feip = 0, *dpid, *rmts_stored_idxp = 0; fwd_entry_t *fe; u8 type, is_src_dst = 0; int rv; @@ -449,7 +449,7 @@ dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index) /* remove entry if it already exists */ feip = hash_get (lcm->fwd_entry_by_mapping_index, dst_map_index); if (feip) - dp_del_fwd_entry (lcm, src_map_index, dst_map_index); + dp_del_fwd_entry (lcm, dst_map_index); /* * Determine local mapping and eid @@ -557,6 +557,23 @@ dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index) fe->is_src_dst = is_src_dst; hash_set (lcm->fwd_entry_by_mapping_index, dst_map_index, fe - lcm->fwd_entry_pool); + + /* Add rmt mapping to the vector of adjacent mappings to lcl mapping */ + rmts_stored_idxp = + hash_get (lcm->lcl_to_rmt_adjs_by_lcl_idx, src_map_index); + if (!rmts_stored_idxp) + { + pool_get (lcm->lcl_to_rmt_adjacencies, rmts); + memset (rmts, 0, sizeof (*rmts)); + rmts_idx = rmts - lcm->lcl_to_rmt_adjacencies; + hash_set (lcm->lcl_to_rmt_adjs_by_lcl_idx, src_map_index, rmts_idx); + } + else + { + rmts_idx = (u32) (*rmts_stored_idxp); + rmts = pool_elt_at_index (lcm->lcl_to_rmt_adjacencies, rmts_idx); + } + vec_add1 (rmts[0], dst_map_index); } typedef struct @@ -707,6 +724,8 @@ vnet_lisp_map_cache_add_del (vnet_lisp_add_del_mapping_args_t * a, { lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); u32 mi, *map_indexp, map_index, i; + u32 **rmts = 0, *remote_idxp, rmts_itr, remote_idx; + uword *rmts_idxp; mapping_t *m, *old_map; u32 **eid_indexes; @@ -794,6 +813,21 @@ vnet_lisp_map_cache_add_del (vnet_lisp_add_del_mapping_args_t * a, m = pool_elt_at_index (lcm->mapping_pool, mi); if (m->local) { + /* Remove adjacencies associated with the local mapping */ + rmts_idxp = hash_get (lcm->lcl_to_rmt_adjs_by_lcl_idx, mi); + if (rmts_idxp) + { + rmts = + pool_elt_at_index (lcm->lcl_to_rmt_adjacencies, rmts_idxp[0]); + vec_foreach (remote_idxp, rmts[0]) + { + dp_del_fwd_entry (lcm, remote_idxp[0]); + } + vec_free (rmts[0]); + pool_put (lcm->lcl_to_rmt_adjacencies, rmts); + hash_unset (lcm->lcl_to_rmt_adjs_by_lcl_idx, mi); + } + u32 k, *lm_indexp; for (k = 0; k < vec_len (lcm->local_mappings_indexes); k++) { @@ -803,6 +837,26 @@ vnet_lisp_map_cache_add_del (vnet_lisp_add_del_mapping_args_t * a, } vec_del1 (lcm->local_mappings_indexes, k); } + else + { + /* Remove remote (if present) from the vectors of lcl-to-rmts + * TODO: Address this in a more efficient way. + */ + /* *INDENT-OFF* */ + pool_foreach (rmts, lcm->lcl_to_rmt_adjacencies, + ({ + vec_foreach_index (rmts_itr, rmts[0]) + { + remote_idx = vec_elt (rmts[0], rmts_itr); + if (mi == remote_idx) + { + vec_del1 (rmts[0], rmts_itr); + break; + } + } + })); + /* *INDENT-ON* */ + } /* remove mapping from dictionary */ gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->eid, 0, 0); @@ -1318,7 +1372,7 @@ vnet_lisp_clear_all_remote_adjacencies (void) mapping_t *map = pool_elt_at_index (lcm->mapping_pool, map_indexp[0]); if (!map->local) { - dp_del_fwd_entry (lcm, 0, map_indexp[0]); + dp_del_fwd_entry (lcm, map_indexp[0]); dm_args->is_add = 0; gid_address_copy (&dm_args->eid, &map->eid); @@ -1404,7 +1458,7 @@ vnet_lisp_add_del_adjacency (vnet_lisp_add_del_adjacency_args_t * a) dp_add_fwd_entry (lcm, local_mi, remote_mi); } else - dp_del_fwd_entry (lcm, 0, remote_mi); + dp_del_fwd_entry (lcm, remote_mi); return 0; } @@ -2029,7 +2083,7 @@ vnet_lisp_map_register_enable_disable (u8 is_enable) clib_error_t * vnet_lisp_enable_disable (u8 is_enable) { - u32 vni, dp_table; + u32 vni, dp_table, **rmts; clib_error_t *error = 0; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a; @@ -2060,6 +2114,15 @@ vnet_lisp_enable_disable (u8 is_enable) /* clear interface table */ hash_free (lcm->fwd_entry_by_mapping_index); pool_free (lcm->fwd_entry_pool); + /* Clear state tracking rmt-lcl fwd entries */ + /* *INDENT-OFF* */ + pool_foreach(rmts, lcm->lcl_to_rmt_adjacencies, + { + vec_free(rmts[0]); + }); + /* *INDENT-ON* */ + hash_free (lcm->lcl_to_rmt_adjs_by_lcl_idx); + pool_free (lcm->lcl_to_rmt_adjacencies); } /* update global flag */ diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index a3e2fc25..12bfcb51 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -180,6 +180,12 @@ typedef struct /* hash map of forwarding entries by mapping index */ u32 *fwd_entry_by_mapping_index; + /* pool of vectors of rmts per lcl mapping in adjacencies */ + u32 **lcl_to_rmt_adjacencies; + + /* hash of pool positions of vectors of rmts by lcl mapping index */ + u32 *lcl_to_rmt_adjs_by_lcl_idx; + /* forwarding entries pool */ fwd_entry_t *fwd_entry_pool; -- cgit 1.2.3-korg From 058799951d062bbbe4df8df101b4db5bc7797b8f Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Tue, 5 Sep 2017 15:46:09 +0200 Subject: LISP: support for neighbor discovery Change-Id: I0f1a051dd3b5786dc7c457bc6fc7ce4fcd0f530c Signed-off-by: Filip Tehlar --- src/vat/api_format.c | 233 +++++++++++++++++++++++++++++++++++++ src/vnet/lisp-cp/control.c | 236 +++++++++++++++++++++++++++++--------- src/vnet/lisp-cp/control.h | 8 ++ src/vnet/lisp-cp/gid_dictionary.c | 82 +++++++------ src/vnet/lisp-cp/gid_dictionary.h | 24 ++-- src/vnet/lisp-cp/lisp_types.c | 5 +- src/vnet/lisp-cp/lisp_types.h | 26 +++-- src/vnet/lisp-cp/one_api.c | 77 ++++++++++++- src/vnet/lisp-cp/one_cli.c | 36 ++++++ 9 files changed, 617 insertions(+), 110 deletions(-) (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/vat/api_format.c b/src/vat/api_format.c index ff3354c9..520ae4f6 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -3392,6 +3392,71 @@ end: vam->result_ready = 1; } +static void + vl_api_one_ndp_entries_get_reply_t_handler + (vl_api_one_ndp_entries_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + + for (i = 0; i < n; i++) + print (vam->ofp, "%U -> %U", format_ip6_address, &mp->entries[i].ip6, + format_ethernet_address, mp->entries[i].mac); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_ndp_entries_get_reply_t_handler_json + (vl_api_one_ndp_entries_get_reply_t * mp) +{ + u8 *s = 0; + vat_main_t *vam = &vat_main; + vat_json_node_t *e = 0, root; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + vl_api_one_ndp_entry_t *arp_entry; + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + vat_json_init_array (&root); + + for (i = 0; i < n; i++) + { + e = vat_json_array_add (&root); + arp_entry = &mp->entries[i]; + + vat_json_init_object (e); + s = format (0, "%U", format_ethernet_address, arp_entry->mac); + vec_add1 (s, 0); + + vat_json_object_add_string_copy (e, "mac", s); + vec_free (s); + + s = format (0, "%U", format_ip6_address, &arp_entry->ip6); + vec_add1 (s, 0); + vat_json_object_add_string_copy (e, "ip6", s); + vec_free (s); + } + + vat_json_print (vam->ofp, &root); + vat_json_free (&root); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + static void vl_api_one_l2_arp_entries_get_reply_t_handler (vl_api_one_l2_arp_entries_get_reply_t * mp) @@ -3457,6 +3522,57 @@ end: vam->result_ready = 1; } +static void +vl_api_one_ndp_bd_get_reply_t_handler (vl_api_one_ndp_bd_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + + for (i = 0; i < n; i++) + { + print (vam->ofp, "%d", clib_net_to_host_u32 (mp->bridge_domains[i])); + } + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_ndp_bd_get_reply_t_handler_json + (vl_api_one_ndp_bd_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t root; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + vat_json_init_array (&root); + + for (i = 0; i < n; i++) + { + vat_json_array_add_uint (&root, + clib_net_to_host_u32 (mp->bridge_domains[i])); + } + + vat_json_print (vam->ofp, &root); + vat_json_free (&root); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + static void vl_api_one_l2_arp_bd_get_reply_t_handler (vl_api_one_l2_arp_bd_get_reply_t * mp) @@ -4590,6 +4706,10 @@ static void vl_api_flow_classify_details_t_handler_json #define vl_api_one_l2_arp_entries_get_reply_t_endian vl_noop_handler #define vl_api_one_l2_arp_entries_get_reply_t_print vl_noop_handler #define vl_api_one_l2_arp_bd_get_reply_t_endian vl_noop_handler +#define vl_api_one_ndp_bd_get_reply_t_endian vl_noop_handler +#define vl_api_one_ndp_bd_get_reply_t_print vl_noop_handler +#define vl_api_one_ndp_entries_get_reply_t_print vl_noop_handler +#define vl_api_one_ndp_entries_get_reply_t_endian vl_noop_handler /* * Generate boilerplate reply handlers, which @@ -4706,6 +4826,7 @@ _(one_eid_table_add_del_map_reply) \ _(one_use_petr_reply) \ _(one_stats_enable_disable_reply) \ _(one_add_del_l2_arp_entry_reply) \ +_(one_add_del_ndp_entry_reply) \ _(one_stats_flush_reply) \ _(gpe_enable_disable_reply) \ _(gpe_set_encap_mode_reply) \ @@ -4950,6 +5071,9 @@ _(ONE_STATS_FLUSH_REPLY, one_stats_flush_reply) \ _(ONE_STATS_ENABLE_DISABLE_REPLY, one_stats_enable_disable_reply) \ _(SHOW_ONE_STATS_ENABLE_DISABLE_REPLY, \ show_one_stats_enable_disable_reply) \ +_(ONE_ADD_DEL_NDP_ENTRY_REPLY, one_add_del_ndp_entry_reply) \ +_(ONE_NDP_BD_GET_REPLY, one_ndp_bd_get_reply) \ +_(ONE_NDP_ENTRIES_GET_REPLY, one_ndp_entries_get_reply) \ _(ONE_ADD_DEL_L2_ARP_ENTRY_REPLY, one_add_del_l2_arp_entry_reply) \ _(ONE_L2_ARP_BD_GET_REPLY, one_l2_arp_bd_get_reply) \ _(ONE_L2_ARP_ENTRIES_GET_REPLY, one_l2_arp_entries_get_reply) \ @@ -15413,6 +15537,58 @@ api_show_one_rloc_probe_state (vat_main_t * vam) #define api_show_lisp_rloc_probe_state api_show_one_rloc_probe_state +static int +api_one_add_del_ndp_entry (vat_main_t * vam) +{ + vl_api_one_add_del_ndp_entry_t *mp; + unformat_input_t *input = vam->input; + u8 is_add = 1; + u8 mac_set = 0; + u8 bd_set = 0; + u8 ip_set = 0; + u8 mac[6] = { 0, }; + u8 ip6[16] = { 0, }; + u32 bd = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + is_add = 0; + else if (unformat (input, "mac %U", unformat_ethernet_address, mac)) + mac_set = 1; + else if (unformat (input, "ip %U", unformat_ip6_address, ip6)) + ip_set = 1; + else if (unformat (input, "bd %d", &bd)) + bd_set = 1; + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!bd_set || !ip_set || (!mac_set && is_add)) + { + errmsg ("Missing BD, IP or MAC!"); + return -99; + } + + M (ONE_ADD_DEL_NDP_ENTRY, mp); + mp->is_add = is_add; + clib_memcpy (mp->mac, mac, 6); + mp->bd = clib_host_to_net_u32 (bd); + clib_memcpy (mp->ip6, ip6, sizeof (mp->ip6)); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + static int api_one_add_del_l2_arp_entry (vat_main_t * vam) { @@ -15464,6 +15640,60 @@ api_one_add_del_l2_arp_entry (vat_main_t * vam) return ret; } +static int +api_one_ndp_bd_get (vat_main_t * vam) +{ + vl_api_one_ndp_bd_get_t *mp; + int ret; + + M (ONE_NDP_BD_GET, mp); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +static int +api_one_ndp_entries_get (vat_main_t * vam) +{ + vl_api_one_ndp_entries_get_t *mp; + unformat_input_t *input = vam->input; + u8 bd_set = 0; + u32 bd = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "bd %d", &bd)) + bd_set = 1; + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!bd_set) + { + errmsg ("Expected bridge domain!"); + return -99; + } + + M (ONE_NDP_ENTRIES_GET, mp); + mp->bd = clib_host_to_net_u32 (bd); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + static int api_one_l2_arp_bd_get (vat_main_t * vam) { @@ -20411,6 +20641,9 @@ _(one_locator_set_dump, "[local | remote]") \ _(one_locator_dump, "ls_index | ls_name ") \ _(one_eid_table_dump, "[eid / | ] [vni] " \ "[local] | [remote]") \ +_(one_add_del_ndp_entry, "[del] mac bd ip6 ") \ +_(one_ndp_bd_get, "") \ +_(one_ndp_entries_get, "bd ") \ _(one_add_del_l2_arp_entry, "[del] mac bd ip4 ") \ _(one_l2_arp_bd_get, "") \ _(one_l2_arp_entries_get, "bd ") \ diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index 74597a6b..7aa3b419 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -908,7 +908,11 @@ static void add_l2_arp_bd (BVT (clib_bihash_kv) * kvp, void *arg) { u32 **ht = arg; - u32 bd = (u32) kvp->key[0]; + u32 version = (u32) kvp->key[0]; + if (IP6 == version) + return; + + u32 bd = (u32) (kvp->key[0] >> 32); hash_set (ht[0], bd, 0); } @@ -918,8 +922,31 @@ vnet_lisp_l2_arp_bds_get (void) lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); u32 *bds = 0; - gid_dict_foreach_l2_arp_entry (&lcm->mapping_index_by_gid, - add_l2_arp_bd, &bds); + gid_dict_foreach_l2_arp_ndp_entry (&lcm->mapping_index_by_gid, + add_l2_arp_bd, &bds); + return bds; +} + +static void +add_ndp_bd (BVT (clib_bihash_kv) * kvp, void *arg) +{ + u32 **ht = arg; + u32 version = (u32) kvp->key[0]; + if (IP4 == version) + return; + + u32 bd = (u32) (kvp->key[0] >> 32); + hash_set (ht[0], bd, 0); +} + +u32 * +vnet_lisp_ndp_bds_get (void) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + u32 *bds = 0; + + gid_dict_foreach_l2_arp_ndp_entry (&lcm->mapping_index_by_gid, + add_ndp_bd, &bds); return bds; } @@ -927,15 +954,21 @@ typedef struct { void *vector; u32 bd; -} lisp_add_l2_arp_args_t; +} lisp_add_l2_arp_ndp_args_t; static void add_l2_arp_entry (BVT (clib_bihash_kv) * kvp, void *arg) { - lisp_add_l2_arp_args_t *a = arg; + lisp_add_l2_arp_ndp_args_t *a = arg; lisp_api_l2_arp_entry_t **vector = a->vector, e; - if ((u32) kvp->key[0] == a->bd) + u32 version = (u32) kvp->key[0]; + if (IP6 == version) + return; + + u32 bd = (u32) (kvp->key[0] >> 32); + + if (bd == a->bd) { mac_copy (e.mac, (void *) &kvp->value); e.ip4 = (u32) kvp->key[1]; @@ -948,13 +981,48 @@ vnet_lisp_l2_arp_entries_get_by_bd (u32 bd) { lisp_api_l2_arp_entry_t *entries = 0; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - lisp_add_l2_arp_args_t a; + lisp_add_l2_arp_ndp_args_t a; + + a.vector = &entries; + a.bd = bd; + + gid_dict_foreach_l2_arp_ndp_entry (&lcm->mapping_index_by_gid, + add_l2_arp_entry, &a); + return entries; +} + +static void +add_ndp_entry (BVT (clib_bihash_kv) * kvp, void *arg) +{ + lisp_add_l2_arp_ndp_args_t *a = arg; + lisp_api_ndp_entry_t **vector = a->vector, e; + + u32 version = (u32) kvp->key[0]; + if (IP4 == version) + return; + + u32 bd = (u32) (kvp->key[0] >> 32); + + if (bd == a->bd) + { + mac_copy (e.mac, (void *) &kvp->value); + clib_memcpy (e.ip6, &kvp->key[1], 16); + vec_add1 (vector[0], e); + } +} + +lisp_api_ndp_entry_t * +vnet_lisp_ndp_entries_get_by_bd (u32 bd) +{ + lisp_api_ndp_entry_t *entries = 0; + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + lisp_add_l2_arp_ndp_args_t a; a.vector = &entries; a.bd = bd; - gid_dict_foreach_l2_arp_entry (&lcm->mapping_index_by_gid, - add_l2_arp_entry, &a); + gid_dict_foreach_l2_arp_ndp_entry (&lcm->mapping_index_by_gid, + add_ndp_entry, &a); return entries; } @@ -2236,7 +2304,9 @@ vnet_lisp_add_del_mreq_itr_rlocs (vnet_lisp_add_del_mreq_itr_rloc_args_t * a) #define foreach_lisp_cp_lookup_error \ _(DROP, "drop") \ _(MAP_REQUESTS_SENT, "map-request sent") \ -_(ARP_REPLY_TX, "ARP replies sent") +_(ARP_REPLY_TX, "ARP replies sent") \ +_(NDP_NEIGHBOR_ADVERTISEMENT_TX, \ + "neighbor advertisement sent") static char *lisp_cp_lookup_error_strings[] = { #define _(sym,string) string, @@ -2255,7 +2325,7 @@ typedef enum typedef enum { LISP_CP_LOOKUP_NEXT_DROP, - LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX, + LISP_CP_LOOKUP_NEXT_ARP_NDP_REPLY_TX, LISP_CP_LOOKUP_N_NEXT, } lisp_cp_lookup_next_t; @@ -3069,6 +3139,7 @@ get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b, { ethernet_header_t *eh; u32 vni = 0; + icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *opt; memset (src, 0, sizeof (*src)); memset (dst, 0, sizeof (*dst)); @@ -3116,6 +3187,33 @@ get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b, } else { + if (clib_net_to_host_u16 (eh->type) == ETHERNET_TYPE_IP6) + { + ip6_header_t *ip; + ip = (ip6_header_t *) (eh + 1); + + if (IP_PROTOCOL_ICMP6 == ip->protocol) + { + icmp6_neighbor_solicitation_or_advertisement_header_t *ndh; + ndh = ip6_next_header (ip); + if (ndh->icmp.type == ICMP6_neighbor_solicitation) + { + opt = (void *) (ndh + 1); + if ((opt->header.type != + ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address) + || (opt->header.n_data_u64s != 1)) + return; /* source link layer address option not present */ + + gid_address_type (dst) = GID_ADDR_NDP; + gid_address_ndp_bd (dst) = + lisp_get_bd_from_buffer_eth (b); + ip_address_set (&gid_address_arp_ndp_ip (dst), + &ndh->target_address, IP6); + return; + } + } + } + gid_address_type (src) = GID_ADDR_MAC; gid_address_type (dst) = GID_ADDR_MAC; mac_copy (&gid_address_mac (src), eh->src_address); @@ -3151,6 +3249,7 @@ lisp_cp_lookup_inline (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame, int overlay) { + icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *opt; u32 *from, *to_next, di, si; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); u32 pkts_mapped = 0, next_index; @@ -3174,6 +3273,9 @@ lisp_cp_lookup_inline (vlib_main_t * vm, ethernet_arp_header_t *arp0; ethernet_header_t *eth0; vnet_hw_interface_t *hw_if0; + ethernet_header_t *eh0; + icmp6_neighbor_solicitation_or_advertisement_header_t *ndh; + ip6_header_t *ip0; pi0 = from[0]; from += 1; @@ -3190,41 +3292,70 @@ lisp_cp_lookup_inline (vlib_main_t * vm, if (gid_address_type (&dst) == GID_ADDR_ARP) { mac0 = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &dst); - if (GID_LOOKUP_MISS_L2 != mac0) - { - /* send ARP reply */ - - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0; - - hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0); - - eth0 = vlib_buffer_get_current (b0); - arp0 = (ethernet_arp_header_t *) (((u8 *) eth0) - + sizeof (*eth0)); - arp0->opcode = - clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply); - arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0]; - clib_memcpy (arp0->ip4_over_ethernet[0].ethernet, - (u8 *) & mac0, 6); - clib_memcpy (&arp0->ip4_over_ethernet[0].ip4, - &gid_address_arp_ip4 (&dst), 4); - - /* Hardware must be ethernet-like. */ - ASSERT (vec_len (hw_if0->hw_address) == 6); - - clib_memcpy (eth0->dst_address, eth0->src_address, 6); - clib_memcpy (eth0->src_address, hw_if0->hw_address, 6); - - b0->error = node->errors[LISP_CP_LOOKUP_ERROR_ARP_REPLY_TX]; - next0 = LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX; - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, - n_left_to_next, pi0, - next0); - continue; - } - goto done; + if (GID_LOOKUP_MISS_L2 == mac0) + goto drop; + + /* send ARP reply */ + sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0; + + hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0); + + eth0 = vlib_buffer_get_current (b0); + arp0 = (ethernet_arp_header_t *) (((u8 *) eth0) + + sizeof (*eth0)); + arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply); + arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0]; + clib_memcpy (arp0->ip4_over_ethernet[0].ethernet, + (u8 *) & mac0, 6); + clib_memcpy (&arp0->ip4_over_ethernet[0].ip4, + &gid_address_arp_ip4 (&dst), 4); + + /* Hardware must be ethernet-like. */ + ASSERT (vec_len (hw_if0->hw_address) == 6); + + clib_memcpy (eth0->dst_address, eth0->src_address, 6); + clib_memcpy (eth0->src_address, hw_if0->hw_address, 6); + + b0->error = node->errors[LISP_CP_LOOKUP_ERROR_ARP_REPLY_TX]; + next0 = LISP_CP_LOOKUP_NEXT_ARP_NDP_REPLY_TX; + goto enqueue; + } + else if (gid_address_type (&dst) == GID_ADDR_NDP) + { + mac0 = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &dst); + if (GID_LOOKUP_MISS_L2 == mac0) + goto drop; + + sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0; + + eh0 = vlib_buffer_get_current (b0); + ip0 = (ip6_header_t *) (eh0 + 1); + ndh = ip6_next_header (ip0); + int bogus_length; + ip0->dst_address = ip0->src_address; + ip0->src_address = ndh->target_address; + ip0->hop_limit = 255; + opt = (void *) (ndh + 1); + opt->header.type = + ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address; + clib_memcpy (opt->ethernet_address, (u8 *) & mac0, 6); + ndh->icmp.type = ICMP6_neighbor_advertisement; + ndh->advertisement_flags = clib_host_to_net_u32 + (ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED | + ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_OVERRIDE); + ndh->icmp.checksum = 0; + ndh->icmp.checksum = + ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip0, + &bogus_length); + clib_memcpy (eh0->dst_address, eh0->src_address, 6); + clib_memcpy (eh0->src_address, (u8 *) & mac0, 6); + b0->error = + node->errors + [LISP_CP_LOOKUP_ERROR_NDP_NEIGHBOR_ADVERTISEMENT_TX]; + next0 = LISP_CP_LOOKUP_NEXT_ARP_NDP_REPLY_TX; + goto enqueue; } /* if we have remote mapping for destination already in map-chache @@ -3267,8 +3398,10 @@ lisp_cp_lookup_inline (vlib_main_t * vm, pkts_mapped++; } - done: + drop: b0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP]; + next0 = LISP_CP_LOOKUP_NEXT_DROP; + enqueue: if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { lisp_cp_lookup_trace_t *tr = vlib_add_trace (vm, node, b0, @@ -3281,7 +3414,6 @@ lisp_cp_lookup_inline (vlib_main_t * vm, } gid_address_free (&dst); gid_address_free (&src); - next0 = LISP_CP_LOOKUP_NEXT_DROP; vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, pi0, next0); @@ -3339,7 +3471,7 @@ VLIB_REGISTER_NODE (lisp_cp_lookup_ip4_node) = { .next_nodes = { [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop", - [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output", + [LISP_CP_LOOKUP_NEXT_ARP_NDP_REPLY_TX] = "interface-output", }, }; /* *INDENT-ON* */ @@ -3359,7 +3491,7 @@ VLIB_REGISTER_NODE (lisp_cp_lookup_ip6_node) = { .next_nodes = { [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop", - [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output", + [LISP_CP_LOOKUP_NEXT_ARP_NDP_REPLY_TX] = "interface-output", }, }; /* *INDENT-ON* */ @@ -3379,7 +3511,7 @@ VLIB_REGISTER_NODE (lisp_cp_lookup_l2_node) = { .next_nodes = { [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop", - [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output", + [LISP_CP_LOOKUP_NEXT_ARP_NDP_REPLY_TX] = "interface-output", }, }; /* *INDENT-ON* */ @@ -3399,7 +3531,7 @@ VLIB_REGISTER_NODE (lisp_cp_lookup_nsh_node) = { .next_nodes = { [LISP_CP_LOOKUP_NEXT_DROP] = "error-drop", - [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output", + [LISP_CP_LOOKUP_NEXT_ARP_NDP_REPLY_TX] = "interface-output", }, }; /* *INDENT-ON* */ diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index 12bfcb51..d40f6f53 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -103,6 +103,12 @@ typedef struct u32 ip4; } lisp_api_l2_arp_entry_t; +typedef struct +{ + u8 mac[6]; + u8 ip6[16]; +} lisp_api_ndp_entry_t; + typedef enum { MR_MODE_DST_ONLY = 0, @@ -395,6 +401,8 @@ int vnet_lisp_map_register_set_ttl (u32 ttl); u32 vnet_lisp_map_register_get_ttl (void); int vnet_lisp_map_register_fallback_threshold_set (u32 value); u32 vnet_lisp_map_register_fallback_threshold_get (void); +u32 *vnet_lisp_ndp_bds_get (void); +lisp_api_ndp_entry_t *vnet_lisp_ndp_entries_get_by_bd (u32 bd); map_records_arg_t *parse_map_reply (vlib_buffer_t * b); diff --git a/src/vnet/lisp-cp/gid_dictionary.c b/src/vnet/lisp-cp/gid_dictionary.c index cf9a741a..c3b93301 100644 --- a/src/vnet/lisp-cp/gid_dictionary.c +++ b/src/vnet/lisp-cp/gid_dictionary.c @@ -139,12 +139,13 @@ gid_dict_foreach_subprefix (gid_dictionary_t * db, gid_address_t * eid, } void -gid_dict_foreach_l2_arp_entry (gid_dictionary_t * db, void (*cb) - (BVT (clib_bihash_kv) * kvp, void *arg), - void *ht) +gid_dict_foreach_l2_arp_ndp_entry (gid_dictionary_t * db, void (*cb) + (BVT (clib_bihash_kv) * kvp, void *arg), + void *ht) { - gid_l2_arp_table_t *tab = &db->arp_table; - BV (clib_bihash_foreach_key_value_pair) (&tab->arp_lookup_table, cb, ht); + gid_l2_arp_ndp_table_t *tab = &db->arp_ndp_table; + BV (clib_bihash_foreach_key_value_pair) (&tab->arp_ndp_lookup_table, cb, + ht); } static void @@ -338,11 +339,19 @@ ip_sd_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t * dst, } static void -make_arp_key (BVT (clib_bihash_kv) * kv, u32 bd, ip4_address_t * addr) +make_arp_ndp_key (BVT (clib_bihash_kv) * kv, u32 bd, ip_address_t * addr) { - kv->key[0] = (u64) bd; - kv->key[1] = (u64) addr->as_u32; - kv->key[2] = (u64) 0; + kv->key[0] = ((u64) bd << 32) | (u32) ip_addr_version (addr); + if (ip_addr_version (addr) == IP4) + { + kv->key[1] = (u64) addr->ip.v4.as_u32; + kv->key[2] = (u64) 0; + } + else + { + kv->key[1] = (u64) addr->ip.v6.as_u64[0]; + kv->key[2] = (u64) addr->ip.v6.as_u64[1]; + } } static void @@ -354,13 +363,14 @@ make_nsh_key (BVT (clib_bihash_kv) * kv, u32 vni, u32 spi, u8 si) } static u64 -arp_lookup (gid_l2_arp_table_t * db, u32 bd, ip4_address_t * key) +arp_ndp_lookup (gid_l2_arp_ndp_table_t * db, u32 bd, ip_address_t * key) { int rv; BVT (clib_bihash_kv) kv, value; - make_arp_key (&kv, bd, key); - rv = BV (clib_bihash_search_inline_2) (&db->arp_lookup_table, &kv, &value); + make_arp_ndp_key (&kv, bd, key); + rv = BV (clib_bihash_search_inline_2) (&db->arp_ndp_lookup_table, &kv, + &value); if (rv == 0) return value.value; @@ -414,8 +424,9 @@ gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key) } break; case GID_ADDR_ARP: - return arp_lookup (&db->arp_table, gid_address_arp_bd (key), - &gid_address_arp_ip4 (key)); + case GID_ADDR_NDP: + return arp_ndp_lookup (&db->arp_ndp_table, gid_address_arp_ndp_bd (key), + &gid_address_arp_ndp_ip (key)); case GID_ADDR_NSH: return nsh_lookup (&db->nsh_table, gid_address_vni (key), gid_address_nsh_spi (key), gid_address_nsh_si (key)); @@ -890,25 +901,27 @@ add_del_sd (gid_dictionary_t * db, u32 vni, source_dest_t * key, u32 value, } static u64 -add_del_arp (gid_l2_arp_table_t * db, u32 bd, ip4_address_t * key, u64 value, - u8 is_add) +add_del_arp_ndp (gid_l2_arp_ndp_table_t * db, u32 bd, ip_address_t * key, + u64 value, u8 is_add) { BVT (clib_bihash_kv) kv, result; u32 old_val = ~0; - make_arp_key (&kv, bd, key); - if (BV (clib_bihash_search) (&db->arp_lookup_table, &kv, &result) == 0) + make_arp_ndp_key (&kv, bd, key); + if (BV (clib_bihash_search) (&db->arp_ndp_lookup_table, &kv, &result) == 0) old_val = result.value; if (is_add) { kv.value = value; - BV (clib_bihash_add_del) (&db->arp_lookup_table, &kv, 1 /* is_add */ ); + BV (clib_bihash_add_del) (&db->arp_ndp_lookup_table, &kv, + 1 /* is_add */ ); db->count++; } else { - BV (clib_bihash_add_del) (&db->arp_lookup_table, &kv, 0 /* is_add */ ); + BV (clib_bihash_add_del) (&db->arp_ndp_lookup_table, &kv, + 0 /* is_add */ ); db->count--; } return old_val; @@ -955,8 +968,10 @@ gid_dictionary_add_del (gid_dictionary_t * db, gid_address_t * key, u64 value, return add_del_sd (db, gid_address_vni (key), &gid_address_sd (key), (u32) value, is_add); case GID_ADDR_ARP: - return add_del_arp (&db->arp_table, gid_address_arp_bd (key), - &gid_address_arp_ip4 (key), value, is_add); + case GID_ADDR_NDP: + return add_del_arp_ndp (&db->arp_ndp_table, + gid_address_arp_ndp_bd (key), + &gid_address_arp_ndp_ip (key), value, is_add); case GID_ADDR_NSH: return add_del_nsh (&db->nsh_table, gid_address_vni (key), gid_address_nsh_spi (key), gid_address_nsh_si (key), @@ -987,20 +1002,21 @@ mac_lookup_init (gid_mac_table_t * db) } static void -arp_lookup_init (gid_l2_arp_table_t * db) +arp_ndp_lookup_init (gid_l2_arp_ndp_table_t * db) { - if (db->arp_lookup_table_nbuckets == 0) - db->arp_lookup_table_nbuckets = ARP_LOOKUP_DEFAULT_HASH_NUM_BUCKETS; + if (db->arp_ndp_lookup_table_nbuckets == 0) + db->arp_ndp_lookup_table_nbuckets = + ARP_NDP_LOOKUP_DEFAULT_HASH_NUM_BUCKETS; - db->arp_lookup_table_nbuckets = - 1 << max_log2 (db->arp_lookup_table_nbuckets); + db->arp_ndp_lookup_table_nbuckets = + 1 << max_log2 (db->arp_ndp_lookup_table_nbuckets); - if (db->arp_lookup_table_size == 0) - db->arp_lookup_table_size = ARP_LOOKUP_DEFAULT_HASH_MEMORY_SIZE; + if (db->arp_ndp_lookup_table_size == 0) + db->arp_ndp_lookup_table_size = ARP_NDP_LOOKUP_DEFAULT_HASH_MEMORY_SIZE; - BV (clib_bihash_init) (&db->arp_lookup_table, "arp lookup table", - db->arp_lookup_table_nbuckets, - db->arp_lookup_table_size); + BV (clib_bihash_init) (&db->arp_ndp_lookup_table, "arp ndp lookup table", + db->arp_ndp_lookup_table_nbuckets, + db->arp_ndp_lookup_table_size); } static void @@ -1026,7 +1042,7 @@ gid_dictionary_init (gid_dictionary_t * db) ip4_lookup_init (&db->dst_ip4_table); ip6_lookup_init (&db->dst_ip6_table); mac_lookup_init (&db->sd_mac_table); - arp_lookup_init (&db->arp_table); + arp_ndp_lookup_init (&db->arp_ndp_table); nsh_lookup_init (&db->nsh_table); } diff --git a/src/vnet/lisp-cp/gid_dictionary.h b/src/vnet/lisp-cp/gid_dictionary.h index 51806bd6..3f8500e5 100644 --- a/src/vnet/lisp-cp/gid_dictionary.h +++ b/src/vnet/lisp-cp/gid_dictionary.h @@ -36,9 +36,9 @@ #define MAC_LOOKUP_DEFAULT_HASH_NUM_BUCKETS (64 * 1024) #define MAC_LOOKUP_DEFAULT_HASH_MEMORY_SIZE (32<<20) -/* Default size of the ARP hash table */ -#define ARP_LOOKUP_DEFAULT_HASH_NUM_BUCKETS (64 * 1024) -#define ARP_LOOKUP_DEFAULT_HASH_MEMORY_SIZE (32<<20) +/* Default size of the ARP/NDP hash table */ +#define ARP_NDP_LOOKUP_DEFAULT_HASH_NUM_BUCKETS (64 * 1024) +#define ARP_NDP_LOOKUP_DEFAULT_HASH_MEMORY_SIZE (32<<20) /* Default size of the NSH hash table */ #define NSH_LOOKUP_DEFAULT_HASH_NUM_BUCKETS (64 * 1024) @@ -100,16 +100,16 @@ typedef struct gid_nsh_table typedef struct { - BVT (clib_bihash) arp_lookup_table; - u32 arp_lookup_table_nbuckets; - uword arp_lookup_table_size; + BVT (clib_bihash) arp_ndp_lookup_table; + u32 arp_ndp_lookup_table_nbuckets; + uword arp_ndp_lookup_table_size; u64 count; -} gid_l2_arp_table_t; +} gid_l2_arp_ndp_table_t; typedef struct { - /** L2 ARP table */ - gid_l2_arp_table_t arp_table; + /** L2 ARP/NDP table */ + gid_l2_arp_ndp_table_t arp_ndp_table; /** NSH lookup table */ gid_nsh_table_t nsh_table; @@ -146,9 +146,9 @@ gid_dict_foreach_subprefix (gid_dictionary_t * db, gid_address_t * eid, foreach_subprefix_match_cb_t cb, void *arg); void -gid_dict_foreach_l2_arp_entry (gid_dictionary_t * db, void (*cb) - (BVT (clib_bihash_kv) * kvp, void *arg), - void *ht); +gid_dict_foreach_l2_arp_ndp_entry (gid_dictionary_t * db, void (*cb) + (BVT (clib_bihash_kv) * kvp, void *arg), + void *ht); #endif /* VNET_LISP_GPE_GID_DICTIONARY_H_ */ diff --git a/src/vnet/lisp-cp/lisp_types.c b/src/vnet/lisp-cp/lisp_types.c index 622f39af..05f046fa 100644 --- a/src/vnet/lisp-cp/lisp_types.c +++ b/src/vnet/lisp-cp/lisp_types.c @@ -279,8 +279,9 @@ format_gid_address (u8 * s, va_list * args) return format (s, "[%d] %U", gid_address_vni (a), format_mac_address, &gid_address_mac (a)); case GID_ADDR_ARP: - return format (s, "[%d, %U]", gid_address_arp_bd (a), - format_ip4_address, &gid_address_arp_ip4 (a)); + case GID_ADDR_NDP: + return format (s, "[%d, %U]", gid_address_arp_ndp_bd (a), + format_ip_address, &gid_address_arp_ndp_ip (a)); case GID_ADDR_NSH: return format (s, "%U", format_nsh_address, &gid_address_nsh (a)); diff --git a/src/vnet/lisp-cp/lisp_types.h b/src/vnet/lisp-cp/lisp_types.h index b17110f6..4a919e79 100644 --- a/src/vnet/lisp-cp/lisp_types.h +++ b/src/vnet/lisp-cp/lisp_types.h @@ -91,6 +91,7 @@ typedef enum GID_ADDR_SRC_DST, GID_ADDR_NSH, GID_ADDR_ARP, + GID_ADDR_NDP, GID_ADDR_NO_ADDRESS, GID_ADDR_TYPES } gid_address_type_t; @@ -172,12 +173,15 @@ typedef struct typedef struct { - ip4_address_t addr; + ip_address_t addr; u32 bd; -} lcaf_arp_t; +} lcaf_arp_ndp_t; -#define lcaf_arp_ip4(_a) (_a)->addr -#define lcaf_arp_bd(_a) (_a)->bd +#define lcaf_arp_ndp_ip(_a) (_a)->addr +#define lcaf_arp_ndp_ip_ver(_a) ip_addr_version(&lcaf_arp_ndp_ip(_a)) +#define lcaf_arp_ndp_ip4(_a) ip_addr_v4(&lcaf_arp_ndp_ip(_a)) +#define lcaf_arp_ndp_ip6(_a) ip_addr_v6(&lcaf_arp_ndp_ip(_a)) +#define lcaf_arp_ndp_bd(_a) (_a)->bd typedef struct { @@ -185,7 +189,7 @@ typedef struct union { source_dest_t sd; - lcaf_arp_t arp; + lcaf_arp_ndp_t arp_ndp; vni_t uni; }; u8 type; @@ -204,7 +208,7 @@ typedef struct _gid_address_t lcaf_t lcaf; u8 mac[6]; source_dest_t sd; - lcaf_arp_t arp; + lcaf_arp_ndp_t arp_ndp; nsh_t nsh; }; u8 type; @@ -275,9 +279,13 @@ void gid_address_ip_set (gid_address_t * dst, void *src, u8 version); #define gid_address_sd_dst(_a) sd_dst(&gid_address_sd(_a)) #define gid_address_sd_src_type(_a) sd_src_type(&gid_address_sd(_a)) #define gid_address_sd_dst_type(_a) sd_dst_type(&gid_address_sd(_a)) -#define gid_address_arp(_a) (_a)->arp -#define gid_address_arp_ip4(_a) lcaf_arp_ip4(&gid_address_arp (_a)) -#define gid_address_arp_bd(_a) lcaf_arp_bd(&gid_address_arp (_a)) +#define gid_address_arp_ndp(_a) (_a)->arp_ndp +#define gid_address_arp_ndp_bd(_a) lcaf_arp_ndp_bd(&gid_address_arp_ndp(_a)) +#define gid_address_arp_ndp_ip(_a) lcaf_arp_ndp_ip(&gid_address_arp_ndp(_a)) +#define gid_address_arp_ip4(_a) lcaf_arp_ndp_ip4(&gid_address_arp_ndp(_a)) +#define gid_address_ndp_ip6(_a) lcaf_arp_ndp_ip6(&gid_address_arp_ndp(_a)) +#define gid_address_ndp_bd gid_address_arp_ndp_bd +#define gid_address_arp_bd gid_address_arp_ndp_bd /* 'sub'address functions */ #define foreach_gid_address_type_fcns \ diff --git a/src/vnet/lisp-cp/one_api.c b/src/vnet/lisp-cp/one_api.c index 7c8ba63f..96b3d2c0 100644 --- a/src/vnet/lisp-cp/one_api.c +++ b/src/vnet/lisp-cp/one_api.c @@ -130,7 +130,9 @@ _(ONE_STATS_FLUSH, one_stats_flush) \ _(ONE_L2_ARP_BD_GET, one_l2_arp_bd_get) \ _(ONE_L2_ARP_ENTRIES_GET, one_l2_arp_entries_get) \ _(ONE_ADD_DEL_L2_ARP_ENTRY, one_add_del_l2_arp_entry) \ - +_(ONE_ADD_DEL_NDP_ENTRY, one_add_del_ndp_entry) \ +_(ONE_NDP_BD_GET, one_ndp_bd_get) \ +_(ONE_NDP_ENTRIES_GET, one_ndp_entries_get) \ static locator_t * unformat_one_locs (vl_api_one_remote_locator_t * rmt_locs, u32 rloc_num) @@ -1563,13 +1565,55 @@ static void gid_address_arp_bd (arp) = clib_net_to_host_u32 (mp->bd); /* vpp keeps ip4 addresses in network byte order */ - clib_memcpy (&gid_address_arp_ip4 (arp), &mp->ip4, 4); + ip_address_set (&gid_address_arp_ndp_ip (arp), &mp->ip4, IP4); rv = vnet_lisp_add_del_l2_arp_entry (arp, mp->mac, mp->is_add); REPLY_MACRO (VL_API_ONE_ADD_DEL_L2_ARP_ENTRY_REPLY); } +static void +vl_api_one_add_del_ndp_entry_t_handler (vl_api_one_add_del_ndp_entry_t * mp) +{ + vl_api_one_add_del_ndp_entry_reply_t *rmp; + int rv = 0; + gid_address_t _g, *g = &_g; + memset (g, 0, sizeof (*g)); + + gid_address_type (g) = GID_ADDR_NDP; + gid_address_ndp_bd (g) = clib_net_to_host_u32 (mp->bd); + ip_address_set (&gid_address_arp_ndp_ip (g), mp->ip6, IP6); + + rv = vnet_lisp_add_del_l2_arp_entry (g, mp->mac, mp->is_add); + + REPLY_MACRO (VL_API_ONE_ADD_DEL_NDP_ENTRY_REPLY); +} + +static void +vl_api_one_ndp_bd_get_t_handler (vl_api_one_ndp_bd_get_t * mp) +{ + vl_api_one_ndp_bd_get_reply_t *rmp; + int rv = 0; + u32 i = 0; + hash_pair_t *p; + + u32 *bds = vnet_lisp_ndp_bds_get (); + u32 size = hash_elts (bds) * sizeof (u32); + + /* *INDENT-OFF* */ + REPLY_MACRO4 (VL_API_ONE_NDP_BD_GET_REPLY, size, + { + rmp->count = clib_host_to_net_u32 (hash_elts (bds)); + hash_foreach_pair (p, bds, + ({ + rmp->bridge_domains[i++] = clib_host_to_net_u32 (p->key); + })); + }); + /* *INDENT-ON* */ + + hash_free (bds); +} + static void vl_api_one_l2_arp_bd_get_t_handler (vl_api_one_l2_arp_bd_get_t * mp) { @@ -1653,6 +1697,35 @@ static void /* *INDENT-ON* */ } +static void +vl_api_one_ndp_entries_get_t_handler (vl_api_one_ndp_entries_get_t * mp) +{ + vl_api_one_ndp_entries_get_reply_t *rmp = 0; + lisp_api_ndp_entry_t *entries = 0, *e; + u32 i = 0; + int rv = 0; + + u32 bd = clib_net_to_host_u32 (mp->bd); + + entries = vnet_lisp_ndp_entries_get_by_bd (bd); + u32 size = vec_len (entries) * sizeof (vl_api_one_ndp_entry_t); + + /* *INDENT-OFF* */ + REPLY_MACRO4 (VL_API_ONE_NDP_ENTRIES_GET_REPLY, size, + { + rmp->count = clib_host_to_net_u32 (vec_len (entries)); + vec_foreach (e, entries) + { + mac_copy (rmp->entries[i].mac, e->mac); + clib_memcpy (rmp->entries[i].ip6, e->ip6, 16); + i++; + } + }); + /* *INDENT-ON* */ + + vec_free (entries); +} + /* * one_api_hookup * Add vpe's API message handlers to the table. diff --git a/src/vnet/lisp-cp/one_cli.c b/src/vnet/lisp-cp/one_cli.c index 3e0c4c0a..1e52c9af 100644 --- a/src/vnet/lisp-cp/one_cli.c +++ b/src/vnet/lisp-cp/one_cli.c @@ -376,6 +376,42 @@ VLIB_CLI_COMMAND (one_show_l2_arp_entries_command) = { }; /* *INDENT-ON* */ +static clib_error_t * +lisp_show_ndp_entries_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + u32 *ht = vnet_lisp_ndp_bds_get (); + lisp_api_ndp_entry_t *entries, *e; + hash_pair_t *p; + + /* *INDENT-OFF* */ + hash_foreach_pair (p, ht, + ({ + entries = vnet_lisp_ndp_entries_get_by_bd (p->key); + vlib_cli_output (vm, "Table: %d", p->key); + + vec_foreach (e, entries) + { + vlib_cli_output (vm, "\t%U -> %U", format_ip6_address, &e->ip6, + format_mac_address, e->mac); + } + vec_free (entries); + })); + /* *INDENT-ON* */ + + hash_free (ht); + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (one_show_ndp_entries_command) = { + .path = "show one ndp entries", + .short_help = "Show ONE NDP entries", + .function = lisp_show_ndp_entries_command_fn, +}; +/* *INDENT-ON* */ + /** * Handler for add/del remote mapping CLI. * -- cgit 1.2.3-korg From 649296428b669b67b55ef2e701830fb8e676c6b6 Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Wed, 20 Sep 2017 08:41:23 +0200 Subject: LISP: add debug cli for neighbor discovery Change-Id: Ib5d335d6130617d6135615c6c8fa8deaac971331 Signed-off-by: Filip Tehlar --- src/vnet/lisp-cp/control.c | 4 +-- src/vnet/lisp-cp/control.h | 3 ++- src/vnet/lisp-cp/one_api.c | 4 +-- src/vnet/lisp-cp/one_cli.c | 66 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 71 insertions(+), 6 deletions(-) (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index 7aa3b419..42b5b8b0 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -1027,7 +1027,7 @@ vnet_lisp_ndp_entries_get_by_bd (u32 bd) } int -vnet_lisp_add_del_l2_arp_entry (gid_address_t * key, u8 * mac, u8 is_add) +vnet_lisp_add_del_l2_arp_ndp_entry (gid_address_t * key, u8 * mac, u8 is_add) { if (vnet_lisp_enable_disable_status () == 0) { @@ -1054,7 +1054,7 @@ vnet_lisp_add_del_l2_arp_entry (gid_address_t * key, u8 * mac, u8 is_add) { if (res == GID_LOOKUP_MISS_L2) { - clib_warning ("ONE ARP entry %U not found - cannot delete!", + clib_warning ("ONE entry %U not found - cannot delete!", format_gid_address, key); return -1; } diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index d40f6f53..0df18f42 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -393,7 +393,8 @@ int vnet_lisp_rloc_probe_enable_disable (u8 is_enable); int vnet_lisp_map_register_enable_disable (u8 is_enable); u8 vnet_lisp_map_register_state_get (void); u8 vnet_lisp_rloc_probe_state_get (void); -int vnet_lisp_add_del_l2_arp_entry (gid_address_t * key, u8 * mac, u8 is_add); +int vnet_lisp_add_del_l2_arp_ndp_entry (gid_address_t * key, u8 * mac, + u8 is_add); u32 *vnet_lisp_l2_arp_bds_get (void); lisp_api_l2_arp_entry_t *vnet_lisp_l2_arp_entries_get_by_bd (u32 bd); int vnet_lisp_nsh_set_locator_set (u8 * locator_set_name, u8 is_add); diff --git a/src/vnet/lisp-cp/one_api.c b/src/vnet/lisp-cp/one_api.c index 96b3d2c0..ae52381b 100644 --- a/src/vnet/lisp-cp/one_api.c +++ b/src/vnet/lisp-cp/one_api.c @@ -1567,7 +1567,7 @@ static void /* vpp keeps ip4 addresses in network byte order */ ip_address_set (&gid_address_arp_ndp_ip (arp), &mp->ip4, IP4); - rv = vnet_lisp_add_del_l2_arp_entry (arp, mp->mac, mp->is_add); + rv = vnet_lisp_add_del_l2_arp_ndp_entry (arp, mp->mac, mp->is_add); REPLY_MACRO (VL_API_ONE_ADD_DEL_L2_ARP_ENTRY_REPLY); } @@ -1584,7 +1584,7 @@ vl_api_one_add_del_ndp_entry_t_handler (vl_api_one_add_del_ndp_entry_t * mp) gid_address_ndp_bd (g) = clib_net_to_host_u32 (mp->bd); ip_address_set (&gid_address_arp_ndp_ip (g), mp->ip6, IP6); - rv = vnet_lisp_add_del_l2_arp_entry (g, mp->mac, mp->is_add); + rv = vnet_lisp_add_del_l2_arp_ndp_entry (g, mp->mac, mp->is_add); REPLY_MACRO (VL_API_ONE_ADD_DEL_NDP_ENTRY_REPLY); } diff --git a/src/vnet/lisp-cp/one_cli.c b/src/vnet/lisp-cp/one_cli.c index 1e52c9af..700bfd66 100644 --- a/src/vnet/lisp-cp/one_cli.c +++ b/src/vnet/lisp-cp/one_cli.c @@ -276,6 +276,70 @@ VLIB_CLI_COMMAND (one_eid_table_map_command) = { }; /* *INDENT-ON* */ +static clib_error_t * +lisp_add_del_ndp_entry_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + clib_error_t *error = NULL; + int rc = 0; + u8 hw_addr[6], bd = 0; + ip6_address_t ip6; + u32 hw_addr_set = 0, ip_set = 0, is_add = 1; + gid_address_t _g, *g = &_g; + + memset (&ip6, 0, sizeof (ip6)); + memset (hw_addr, 0, sizeof (hw_addr)); + memset (g, 0, sizeof (*g)); + + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "mac %U", unformat_mac_address, hw_addr)) + hw_addr_set = 1; + else if (unformat (line_input, "ip %U", unformat_ip6_address, &ip6)) + ip_set = 1; + else if (unformat (line_input, "del")) + is_add = 0; + else if (unformat (line_input, "bd %d", &bd)) + ; + else + { + error = clib_error_return (0, "parse error"); + goto done; + } + } + + if (!ip_set || (!hw_addr_set && is_add)) + { + vlib_cli_output (vm, "expected IP and MAC addresses!"); + return 0; + } + + /* build GID address */ + ip_address_set (&gid_address_arp_ndp_ip (g), &ip6, IP6); + gid_address_ndp_bd (g) = bd; + gid_address_type (g) = GID_ADDR_NDP; + rc = vnet_lisp_add_del_l2_arp_ndp_entry (g, hw_addr, is_add); + if (rc) + clib_warning ("Failed to %s ndp entry!", is_add ? "add" : "delete"); + +done: + unformat_free (line_input); + return error; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (one_add_del_ndp_entry_command) = { + .path = "one ndp", + .short_help = "one ndp [del] bd mac ip ", + .function = lisp_add_del_ndp_entry_command_fn, +}; +/* *INDENT-ON* */ + static clib_error_t * lisp_add_del_l2_arp_entry_command_fn (vlib_main_t * vm, unformat_input_t * input, @@ -323,7 +387,7 @@ lisp_add_del_l2_arp_entry_command_fn (vlib_main_t * vm, gid_address_arp_ip4 (arp) = ip4; gid_address_arp_bd (arp) = bd; gid_address_type (arp) = GID_ADDR_ARP; - rc = vnet_lisp_add_del_l2_arp_entry (arp, hw_addr, is_add); + rc = vnet_lisp_add_del_l2_arp_ndp_entry (arp, hw_addr, is_add); if (rc) clib_warning ("Failed to %s l2 arp entry!", is_add ? "add" : "delete"); -- cgit 1.2.3-korg From a4980b8f3e53bd0917c75910938fbb077105821f Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Wed, 27 Sep 2017 14:32:02 +0200 Subject: LISP: add API handlers for set/get transport protocol Change-Id: Ib675164c475edcdbe3013df7b847adf5e050c53f Signed-off-by: Filip Tehlar --- src/vat/api_format.c | 132 +++++++++++++++++++++++++++++++++++++++++++++ src/vnet/lisp-cp/control.c | 21 ++++++++ src/vnet/lisp-cp/control.h | 11 ++++ src/vnet/lisp-cp/one_api.c | 30 +++++++++++ 4 files changed, 194 insertions(+) (limited to 'src/vnet/lisp-cp/control.h') diff --git a/src/vat/api_format.c b/src/vat/api_format.c index 520ae4f6..02300216 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -1752,6 +1752,64 @@ static void vl_api_gpe_add_del_fwd_entry_reply_t_handler_json vam->result_ready = 1; } +u8 * +format_lisp_transport_protocol (u8 * s, va_list * args) +{ + u32 proto = va_arg (*args, u32); + + switch (proto) + { + case 1: + return format (s, "udp"); + case 2: + return format (s, "api"); + default: + return 0; + } + return 0; +} + +static void vl_api_one_get_transport_protocol_reply_t_handler + (vl_api_one_get_transport_protocol_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + u32 proto = mp->protocol; + print (vam->ofp, "Transport protocol: %U", + format_lisp_transport_protocol, proto); + vam->retval = retval; + vam->result_ready = 1; + } +} + +static void vl_api_one_get_transport_protocol_reply_t_handler_json + (vl_api_one_get_transport_protocol_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + u8 *s; + + s = format (0, "%U", format_lisp_transport_protocol, mp->protocol); + vec_add1 (s, 0); + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_string_copy (&node, "transport-protocol", s); + + vec_free (s); + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + static void vl_api_one_add_del_locator_set_reply_t_handler (vl_api_one_add_del_locator_set_reply_t * mp) { @@ -4818,6 +4876,7 @@ _(one_enable_disable_reply) \ _(one_rloc_probe_enable_disable_reply) \ _(one_map_register_enable_disable_reply) \ _(one_map_register_set_ttl_reply) \ +_(one_set_transport_protocol_reply) \ _(one_map_register_fallback_threshold_reply) \ _(one_pitr_set_locator_set_reply) \ _(one_map_request_mode_reply) \ @@ -5050,6 +5109,8 @@ _(ONE_ENABLE_DISABLE_REPLY, one_enable_disable_reply) \ _(ONE_MAP_REGISTER_ENABLE_DISABLE_REPLY, \ one_map_register_enable_disable_reply) \ _(ONE_MAP_REGISTER_SET_TTL_REPLY, one_map_register_set_ttl_reply) \ +_(ONE_SET_TRANSPORT_PROTOCOL_REPLY, one_set_transport_protocol_reply) \ +_(ONE_GET_TRANSPORT_PROTOCOL_REPLY, one_get_transport_protocol_reply) \ _(ONE_MAP_REGISTER_FALLBACK_THRESHOLD_REPLY, \ one_map_register_fallback_threshold_reply) \ _(ONE_RLOC_PROBE_ENABLE_DISABLE_REPLY, \ @@ -16598,6 +16659,75 @@ api_show_one_map_register_fallback_threshold (vat_main_t * vam) return ret; } +uword +unformat_lisp_transport_protocol (unformat_input_t * input, va_list * args) +{ + u32 *proto = va_arg (*args, u32 *); + + if (unformat (input, "udp")) + *proto = 1; + else if (unformat (input, "api")) + *proto = 2; + else + return 0; + + return 1; +} + +static int +api_one_set_transport_protocol (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_set_transport_protocol_t *mp; + u8 is_set = 0; + u32 protocol = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%U", unformat_lisp_transport_protocol, &protocol)) + is_set = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!is_set) + { + errmsg ("Transport protocol missing!"); + return -99; + } + + M (ONE_SET_TRANSPORT_PROTOCOL, mp); + mp->protocol = (u8) protocol; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_one_get_transport_protocol (vat_main_t * vam) +{ + vl_api_one_get_transport_protocol_t *mp; + int ret; + + M (ONE_GET_TRANSPORT_PROTOCOL, mp); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + static int api_one_map_register_set_ttl (vat_main_t * vam) { @@ -20662,6 +20792,8 @@ _(one_stats_dump, "") \ _(one_stats_flush, "") \ _(one_get_map_request_itr_rlocs, "") \ _(one_map_register_set_ttl, "") \ +_(one_set_transport_protocol, "udp|api") \ +_(one_get_transport_protocol, "") \ _(show_one_nsh_mapping, "") \ _(show_one_pitr, "") \ _(show_one_use_petr, "") \ diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index 42b5b8b0..0d6d453d 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -4351,6 +4351,7 @@ lisp_cp_init (vlib_main_t * vm) lcm->map_register_ttl = MAP_REGISTER_DEFAULT_TTL; lcm->max_expired_map_registers = MAX_EXPIRED_MAP_REGISTERS_DEFAULT; lcm->expired_map_registers = 0; + lcm->transport_protocol = LISP_TRANSPORT_PROTOCOL_UDP; return 0; } @@ -4720,6 +4721,26 @@ VLIB_REGISTER_NODE (lisp_retry_service_node,static) = { }; /* *INDENT-ON* */ +u32 +vnet_lisp_set_transport_protocol (u8 protocol) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + + if (protocol < LISP_TRANSPORT_PROTOCOL_UDP || + protocol > LISP_TRANSPORT_PROTOCOL_API) + return VNET_API_ERROR_INVALID_ARGUMENT; + + lcm->transport_protocol = protocol; + return 0; +} + +lisp_transport_protocol_t +vnet_lisp_get_transport_protocol (void) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + return lcm->transport_protocol; +} + VLIB_INIT_FUNCTION (lisp_cp_init); /* diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h index 0df18f42..a6da8188 100644 --- a/src/vnet/lisp-cp/control.h +++ b/src/vnet/lisp-cp/control.h @@ -140,6 +140,12 @@ typedef struct u32 bd; } lisp_l2_arp_key_t; +typedef enum +{ + LISP_TRANSPORT_PROTOCOL_UDP = 1, + LISP_TRANSPORT_PROTOCOL_API +} lisp_transport_protocol_t; + typedef struct { u64 nonce; @@ -271,6 +277,9 @@ typedef struct u32 max_expired_map_registers; u32 expired_map_registers; + /** either UDP based or binary API. Default is UDP */ + lisp_transport_protocol_t transport_protocol; + /* commodity */ ip4_main_t *im4; ip6_main_t *im6; @@ -404,6 +413,8 @@ int vnet_lisp_map_register_fallback_threshold_set (u32 value); u32 vnet_lisp_map_register_fallback_threshold_get (void); u32 *vnet_lisp_ndp_bds_get (void); lisp_api_ndp_entry_t *vnet_lisp_ndp_entries_get_by_bd (u32 bd); +u32 vnet_lisp_set_transport_protocol (u8 protocol); +lisp_transport_protocol_t vnet_lisp_get_transport_protocol (void); map_records_arg_t *parse_map_reply (vlib_buffer_t * b); diff --git a/src/vnet/lisp-cp/one_api.c b/src/vnet/lisp-cp/one_api.c index ae52381b..e3a2afe7 100644 --- a/src/vnet/lisp-cp/one_api.c +++ b/src/vnet/lisp-cp/one_api.c @@ -133,6 +133,8 @@ _(ONE_ADD_DEL_L2_ARP_ENTRY, one_add_del_l2_arp_entry) \ _(ONE_ADD_DEL_NDP_ENTRY, one_add_del_ndp_entry) \ _(ONE_NDP_BD_GET, one_ndp_bd_get) \ _(ONE_NDP_ENTRIES_GET, one_ndp_entries_get) \ +_(ONE_SET_TRANSPORT_PROTOCOL, one_set_transport_protocol) \ +_(ONE_GET_TRANSPORT_PROTOCOL, one_get_transport_protocol) static locator_t * unformat_one_locs (vl_api_one_remote_locator_t * rmt_locs, u32 rloc_num) @@ -1697,6 +1699,34 @@ static void /* *INDENT-ON* */ } +static void + vl_api_one_set_transport_protocol_t_handler + (vl_api_one_set_transport_protocol_t * mp) +{ + vl_api_one_set_transport_protocol_reply_t *rmp; + int rv = 0; + + rv = vnet_lisp_set_transport_protocol (mp->protocol); + + REPLY_MACRO (VL_API_ONE_SET_TRANSPORT_PROTOCOL_REPLY); +} + +static void + vl_api_one_get_transport_protocol_t_handler + (vl_api_one_get_transport_protocol_t * mp) +{ + vl_api_one_get_transport_protocol_reply_t *rmp; + int rv = 0; + u8 proto = (u8) vnet_lisp_get_transport_protocol (); + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_ONE_GET_TRANSPORT_PROTOCOL_REPLY, + ({ + rmp->protocol = proto; + })); + /* *INDENT-ON* */ +} + static void vl_api_one_ndp_entries_get_t_handler (vl_api_one_ndp_entries_get_t * mp) { -- cgit 1.2.3-korg