X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Flisp-cp%2Fcontrol.c;h=c1edc3a9315d557126196880dd947f33110e1981;hb=0a62e5a3d817c3400be122c58d0311c298047580;hp=0d6d453de009b69698cffe49548cddd00032ede9;hpb=a4980b8f3e53bd0917c75910938fbb077105821f;p=vpp.git diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c index 0d6d453de00..c1edc3a9315 100644 --- a/src/vnet/lisp-cp/control.c +++ b/src/vnet/lisp-cp/control.c @@ -221,7 +221,8 @@ ip_fib_get_first_egress_ip_for_dst (lisp_cp_main_t * lcm, ip_address_t * dst, } static int -dp_add_del_iface (lisp_cp_main_t * lcm, u32 vni, u8 is_l2, u8 is_add) +dp_add_del_iface (lisp_cp_main_t * lcm, u32 vni, u8 is_l2, u8 is_add, + u8 with_default_route) { uword *dp_table; @@ -251,7 +252,8 @@ dp_add_del_iface (lisp_cp_main_t * lcm, u32 vni, u8 is_l2, u8 is_add) if (is_l2) lisp_gpe_tenant_l2_iface_add_or_lock (vni, dp_table[0]); else - lisp_gpe_tenant_l3_iface_add_or_lock (vni, dp_table[0]); + lisp_gpe_tenant_l3_iface_add_or_lock (vni, dp_table[0], + with_default_route); } else { @@ -454,8 +456,16 @@ dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index) /* * Determine local mapping and eid */ - if (lcm->lisp_pitr) - lcl_map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index); + if (lcm->flags & LISP_FLAG_PITR_MODE) + { + if (lcm->pitr_map_index != ~0) + lcl_map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index); + else + { + clib_warning ("no PITR mapping configured!"); + return; + } + } else lcl_map = pool_elt_at_index (lcm->mapping_pool, src_map_index); lcl_eid = &lcl_map->eid; @@ -1101,7 +1111,8 @@ vnet_lisp_eid_table_map (u32 vni, u32 dp_id, u8 is_l2, u8 is_add) hash_set (vni_by_dp_table[0], dp_id, vni); /* create dp iface */ - dp_add_del_iface (lcm, vni, is_l2, 1); + dp_add_del_iface (lcm, vni, is_l2, 1 /* is_add */ , + 1 /* with_default_route */ ); } else { @@ -1112,7 +1123,7 @@ vnet_lisp_eid_table_map (u32 vni, u32 dp_id, u8 is_l2, u8 is_add) return -1; } /* remove dp iface */ - dp_add_del_iface (lcm, vni, is_l2, 0); + dp_add_del_iface (lcm, vni, is_l2, 0 /* is_add */ , 0 /* unused */ ); hash_unset (dp_table_by_vni[0], vni); hash_unset (vni_by_dp_table[0], dp_id); @@ -1344,6 +1355,8 @@ vnet_lisp_add_mapping (vnet_lisp_add_del_mapping_args_t * a, /* new mapping */ else { + if (is_updated) + is_updated[0] = 1; remove_overlapping_sub_prefixes (lcm, &a->eid, 0 == ls_args->locators); ls_args->is_add = 1; @@ -1380,6 +1393,7 @@ vnet_lisp_del_mapping (gid_address_t * eid, u32 * res_map_index) mapping_t *old_map; u32 mi; + memset (ls_args, 0, sizeof (ls_args[0])); memset (m_args, 0, sizeof (m_args[0])); if (res_map_index) res_map_index[0] = ~0; @@ -1496,8 +1510,18 @@ 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 */ - if (lcm->lisp_pitr) - local_mi = lcm->pitr_map_index; + if (lcm->flags & LISP_FLAG_PITR_MODE) + { + if (lcm->pitr_map_index != ~0) + { + local_mi = lcm->pitr_map_index; + } + else + { + /* PITR mode is on, but no mapping is configured */ + return -1; + } + } else { if (gid_address_type (&a->reid) == GID_ADDR_NSH) @@ -1632,17 +1656,12 @@ vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add) m->local = 1; m->pitr_set = 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; + lcm->pitr_map_index = ~0; } return 0; } @@ -1728,6 +1747,7 @@ vnet_lisp_use_petr (ip_address_t * ip, u8 is_add) /* Disable use-petr */ lcm->flags &= ~LISP_FLAG_USE_PETR; + lcm->petr_map_index = ~0; } return 0; } @@ -1784,6 +1804,7 @@ get_locator_set_index (vnet_lisp_add_del_locator_set_args_t * a, uword * p) /* find locator-set */ if (a->local) { + ASSERT (a->name); p = hash_get_mem (lcm->locator_set_index_by_name, a->name); } else @@ -1819,39 +1840,70 @@ is_locator_in_locator_set (lisp_cp_main_t * lcm, locator_set_t * ls, } static void -update_adjacencies_by_map_index (lisp_cp_main_t * lcm, u8 is_local, +update_adjacencies_by_map_index (lisp_cp_main_t * lcm, u32 mapping_index, u8 remove_only) { fwd_entry_t *fwd; mapping_t *map; + uword *fei = 0, *rmts_idxp = 0; + u32 **rmts = 0, *remote_idxp = 0, *rmts_copy = 0; vnet_lisp_add_del_adjacency_args_t _a, *a = &_a; + memset (a, 0, sizeof (*a)); map = pool_elt_at_index (lcm->mapping_pool, mapping_index); - /* *INDENT-OFF* */ - pool_foreach(fwd, lcm->fwd_entry_pool, - ({ - if ((is_local && 0 == gid_address_cmp (&map->eid, &fwd->leid)) || - (!is_local && 0 == gid_address_cmp (&map->eid, &fwd->reid))) - { - a->is_add = 0; - gid_address_copy (&a->leid, &fwd->leid); - gid_address_copy (&a->reid, &fwd->reid); + if (map->local) + { + rmts_idxp = hash_get (lcm->lcl_to_rmt_adjs_by_lcl_idx, mapping_index); + if (rmts_idxp) + { + rmts = + pool_elt_at_index (lcm->lcl_to_rmt_adjacencies, rmts_idxp[0]); + rmts_copy = vec_dup (rmts[0]); - vnet_lisp_add_del_adjacency (a); + vec_foreach (remote_idxp, rmts_copy) + { + fei = hash_get (lcm->fwd_entry_by_mapping_index, remote_idxp[0]); + if (!fei) + continue; - if (!remove_only) - { - a->is_add = 1; - vnet_lisp_add_del_adjacency (a); - } - } - })); - /* *INDENT-ON* */ + fwd = pool_elt_at_index (lcm->fwd_entry_pool, fei[0]); + a->is_add = 0; + gid_address_copy (&a->leid, &fwd->leid); + gid_address_copy (&a->reid, &fwd->reid); + vnet_lisp_add_del_adjacency (a); + + if (!remove_only) + { + a->is_add = 1; + vnet_lisp_add_del_adjacency (a); + } + } + vec_free (rmts_copy); + } + } + else + { + fei = hash_get (lcm->fwd_entry_by_mapping_index, mapping_index); + if (!fei) + return; + + fwd = pool_elt_at_index (lcm->fwd_entry_pool, fei[0]); + a->is_add = 0; + gid_address_copy (&a->leid, &fwd->leid); + gid_address_copy (&a->reid, &fwd->reid); + vnet_lisp_add_del_adjacency (a); + + if (!remove_only) + { + a->is_add = 1; + vnet_lisp_add_del_adjacency (a); + } + } } static void -update_fwd_entries_by_locator_set (lisp_cp_main_t * lcm, u8 is_local, +update_fwd_entries_by_locator_set (lisp_cp_main_t * lcm, u32 ls_index, u8 remove_only) { u32 i, *map_indexp; @@ -1865,8 +1917,7 @@ update_fwd_entries_by_locator_set (lisp_cp_main_t * lcm, u8 is_local, for (i = 0; i < vec_len (eid_indexes[0]); i++) { map_indexp = vec_elt_at_index (eid_indexes[0], i); - update_adjacencies_by_map_index (lcm, is_local, map_indexp[0], - remove_only); + update_adjacencies_by_map_index (lcm, map_indexp[0], remove_only); } } @@ -1977,7 +2028,7 @@ vnet_lisp_add_del_locator (vnet_lisp_add_del_locator_set_args_t * a, if (removed) { /* update fwd entries using this locator in DP */ - update_fwd_entries_by_locator_set (lcm, loc->local, ls_index, + update_fwd_entries_by_locator_set (lcm, ls_index, vec_len (ls->locator_indices) == 0); } @@ -2148,10 +2199,66 @@ vnet_lisp_map_register_enable_disable (u8 is_enable) return 0; } +static void +lisp_cp_register_dst_port (vlib_main_t * vm) +{ + udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp, + lisp_cp_input_node.index, 1 /* is_ip4 */ ); + udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp6, + lisp_cp_input_node.index, 0 /* is_ip4 */ ); +} + +static void +lisp_cp_unregister_dst_port (vlib_main_t * vm) +{ + udp_unregister_dst_port (vm, UDP_DST_PORT_lisp_cp, 0 /* is_ip4 */ ); + udp_unregister_dst_port (vm, UDP_DST_PORT_lisp_cp6, 1 /* is_ip4 */ ); +} + +/** + * lisp_cp_enable_l2_l3_ifaces + * + * Enable all l2 and l3 ifaces + */ +static void +lisp_cp_enable_l2_l3_ifaces (lisp_cp_main_t * lcm, u8 with_default_route) +{ + u32 vni, dp_table; + + /* *INDENT-OFF* */ + hash_foreach(vni, dp_table, lcm->table_id_by_vni, ({ + dp_add_del_iface(lcm, vni, /* is_l2 */ 0, /* is_add */1, + with_default_route); + })); + hash_foreach(vni, dp_table, lcm->bd_id_by_vni, ({ + dp_add_del_iface(lcm, vni, /* is_l2 */ 1, 1, + with_default_route); + })); + /* *INDENT-ON* */ +} + +static void +lisp_cp_disable_l2_l3_ifaces (lisp_cp_main_t * lcm) +{ + u32 **rmts; + + /* 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); +} + clib_error_t * vnet_lisp_enable_disable (u8 is_enable) { - 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; @@ -2164,33 +2271,45 @@ vnet_lisp_enable_disable (u8 is_enable) a->is_en ? "enable" : "disable"); } - if (is_enable) + /* decide what to do based on mode */ + + if (lcm->flags & LISP_FLAG_XTR_MODE) { - /* enable all l2 and l3 ifaces */ + if (is_enable) + { + lisp_cp_register_dst_port (lcm->vlib_main); + lisp_cp_enable_l2_l3_ifaces (lcm, 1 /* with_default_route */ ); + } + else + { + lisp_cp_unregister_dst_port (lcm->vlib_main); + lisp_cp_disable_l2_l3_ifaces (lcm); + } + } - /* *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 (lcm->flags & LISP_FLAG_PETR_MODE) + { + /* if in xTR mode, the LISP ports were already (un)registered above */ + if (!(lcm->flags & LISP_FLAG_XTR_MODE)) + { + if (is_enable) + lisp_cp_register_dst_port (lcm->vlib_main); + else + lisp_cp_unregister_dst_port (lcm->vlib_main); + } } - else + + if (lcm->flags & LISP_FLAG_PITR_MODE) { - /* 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); + if (is_enable) + { + /* install interfaces, but no default routes */ + lisp_cp_enable_l2_l3_ifaces (lcm, 0 /* with_default_route */ ); + } + else + { + lisp_cp_disable_l2_l3_ifaces (lcm); + } } /* update global flag */ @@ -2700,6 +2819,7 @@ foreach_msmr /* CP output statistics */ #define foreach_lisp_cp_output_error \ _(MAP_REGISTERS_SENT, "map-registers sent") \ +_(MAP_REQUESTS_SENT, "map-requests sent") \ _(RLOC_PROBES_SENT, "rloc-probes sent") static char *lisp_cp_output_error_strings[] = { #define _(sym,string) string, @@ -2945,8 +3065,10 @@ _send_encapsulated_map_request (lisp_cp_main_t * lcm, return 0; } + u8 pitr_mode = lcm->flags & LISP_FLAG_PITR_MODE; + /* get locator-set for seid */ - if (!lcm->lisp_pitr && gid_address_type (deid) != GID_ADDR_NSH) + if (!pitr_mode && gid_address_type (deid) != GID_ADDR_NSH) { map_index = gid_dictionary_lookup (&lcm->mapping_index_by_gid, seid); if (map_index == ~0) @@ -2969,10 +3091,18 @@ _send_encapsulated_map_request (lisp_cp_main_t * lcm, } else { - if (lcm->lisp_pitr) + if (pitr_mode) { - map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index); - ls_index = map->locator_set_index; + if (lcm->pitr_map_index != ~0) + { + map = + pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index); + ls_index = map->locator_set_index; + } + else + { + return -1; + } } else { @@ -3025,6 +3155,9 @@ _send_encapsulated_map_request (lisp_cp_main_t * lcm, f->n_vectors = 1; vlib_put_frame_to_node (lcm->vlib_main, next_index, f); + vlib_node_increment_counter (vlib_get_main (), lisp_cp_output_node.index, + LISP_CP_OUTPUT_ERROR_MAP_REQUESTS_SENT, 1); + if (duplicate_pmr) /* if there is a pending request already update it */ { @@ -3240,6 +3373,7 @@ get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b, gid_address_nsh_si (dst) = si; gid_address_type (dst) = GID_ADDR_NSH; + gid_address_type (src) = GID_ADDR_NSH; } } } @@ -3252,7 +3386,7 @@ lisp_cp_lookup_inline (vlib_main_t * vm, 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; + u32 next_index; uword n_left_from, n_left_to_next; vnet_main_t *vnm = vnet_get_main (); @@ -3372,7 +3506,6 @@ lisp_cp_lookup_inline (vlib_main_t * vm, /* send map-request */ queue_map_request (&src, &dst, 0 /* smr_invoked */ , 0 /* is_resend */ ); - pkts_mapped++; } else { @@ -3395,7 +3528,6 @@ lisp_cp_lookup_inline (vlib_main_t * vm, /* send map-request */ queue_map_request (&src, &dst, 0 /* smr_invoked */ , 0 /* is_resend */ ); - pkts_mapped++; } drop: @@ -3421,9 +3553,6 @@ lisp_cp_lookup_inline (vlib_main_t * vm, 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, - pkts_mapped); return from_frame->n_vectors; } @@ -3743,7 +3872,8 @@ process_map_reply (map_records_arg_t * a) } if ((u32) ~ 0 != m->ttl) - mapping_start_expiration_timer (lcm, dst_map_index, MAPPING_TIMEOUT); + mapping_start_expiration_timer (lcm, dst_map_index, + (m->ttl == 0) ? 0 : MAPPING_TIMEOUT); } /* remove pending map request entry */ @@ -4323,8 +4453,9 @@ lisp_cp_init (vlib_main_t * vm) lcm->vlib_main = vm; lcm->vnet_main = vnet_get_main (); lcm->mreq_itr_rlocs = ~0; - lcm->lisp_pitr = 0; lcm->flags = 0; + lcm->pitr_map_index = ~0; + lcm->petr_map_index = ~0; memset (&lcm->active_map_resolver, 0, sizeof (lcm->active_map_resolver)); memset (&lcm->active_map_server, 0, sizeof (lcm->active_map_server)); @@ -4340,10 +4471,7 @@ lisp_cp_init (vlib_main_t * vm) hash_set (lcm->table_id_by_vni, 0, 0); hash_set (lcm->vni_by_table_id, 0, 0); - udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp, - lisp_cp_input_node.index, 1 /* is_ip4 */ ); - udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp6, - lisp_cp_input_node.index, 0 /* is_ip4 */ ); + lisp_cp_register_dst_port (vm); u64 now = clib_cpu_time_now (); timing_wheel_init (&lcm->wheel, now, vm->clib_time.clocks_per_second); @@ -4352,6 +4480,7 @@ lisp_cp_init (vlib_main_t * vm) lcm->max_expired_map_registers = MAX_EXPIRED_MAP_REGISTERS_DEFAULT; lcm->expired_map_registers = 0; lcm->transport_protocol = LISP_TRANSPORT_PROTOCOL_UDP; + lcm->flags |= LISP_FLAG_XTR_MODE; return 0; } @@ -4741,6 +4870,124 @@ vnet_lisp_get_transport_protocol (void) return lcm->transport_protocol; } +int +vnet_lisp_enable_disable_xtr_mode (u8 is_enabled) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + u8 pitr_mode = lcm->flags & LISP_FLAG_PITR_MODE; + u8 xtr_mode = lcm->flags & LISP_FLAG_XTR_MODE; + u8 petr_mode = lcm->flags & LISP_FLAG_PETR_MODE; + + if (pitr_mode && is_enabled) + return VNET_API_ERROR_INVALID_ARGUMENT; + + if (is_enabled && xtr_mode) + return 0; + if (!is_enabled && !xtr_mode) + return 0; + + if (is_enabled) + { + if (!petr_mode) + { + lisp_cp_register_dst_port (lcm->vlib_main); + } + lisp_cp_enable_l2_l3_ifaces (lcm, 1 /* with_default_route */ ); + lcm->flags |= LISP_FLAG_XTR_MODE; + } + else + { + if (!petr_mode) + { + lisp_cp_unregister_dst_port (lcm->vlib_main); + } + lisp_cp_disable_l2_l3_ifaces (lcm); + lcm->flags &= ~LISP_FLAG_XTR_MODE; + } + return 0; +} + +int +vnet_lisp_enable_disable_pitr_mode (u8 is_enabled) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + u8 xtr_mode = lcm->flags & LISP_FLAG_XTR_MODE; + u8 pitr_mode = lcm->flags & LISP_FLAG_PITR_MODE; + + if (xtr_mode && is_enabled) + return VNET_API_ERROR_INVALID_VALUE; + + if (is_enabled && pitr_mode) + return 0; + if (!is_enabled && !pitr_mode) + return 0; + + if (is_enabled) + { + /* create iface, no default route */ + lisp_cp_enable_l2_l3_ifaces (lcm, 0 /* with_default_route */ ); + lcm->flags |= LISP_FLAG_PITR_MODE; + } + else + { + lisp_cp_disable_l2_l3_ifaces (lcm); + lcm->flags &= ~LISP_FLAG_PITR_MODE; + } + return 0; +} + +int +vnet_lisp_enable_disable_petr_mode (u8 is_enabled) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + u8 xtr_mode = lcm->flags & LISP_FLAG_XTR_MODE; + u8 petr_mode = lcm->flags & LISP_FLAG_PETR_MODE; + + if (is_enabled && petr_mode) + return 0; + if (!is_enabled && !petr_mode) + return 0; + + if (is_enabled) + { + if (!xtr_mode) + { + lisp_cp_register_dst_port (lcm->vlib_main); + } + lcm->flags |= LISP_FLAG_PETR_MODE; + } + else + { + if (!xtr_mode) + { + lisp_cp_unregister_dst_port (lcm->vlib_main); + } + lcm->flags &= ~LISP_FLAG_PETR_MODE; + } + return 0; +} + +u8 +vnet_lisp_get_xtr_mode (void) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + return (lcm->flags & LISP_FLAG_XTR_MODE); +} + +u8 +vnet_lisp_get_pitr_mode (void) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + return (lcm->flags & LISP_FLAG_PITR_MODE); +} + +u8 +vnet_lisp_get_petr_mode (void) +{ + lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); + return (lcm->flags & LISP_FLAG_PETR_MODE); +} + VLIB_INIT_FUNCTION (lisp_cp_init); /*