X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Flisp-gpe%2Flisp_gpe_adjacency.c;h=8efb97248aa73f296c22c3b5d040602e6804a15f;hb=282872127bbeee6ae59ab3f885c09bad601ee0cc;hp=1dbf8677f715692ff1f237f9301fae3543c60a73;hpb=ce1b4c7f05ce28d7b73eb7ed0a8ea4bd483f09e9;p=vpp.git diff --git a/src/vnet/lisp-gpe/lisp_gpe_adjacency.c b/src/vnet/lisp-gpe/lisp_gpe_adjacency.c index 1dbf8677f71..8efb97248aa 100644 --- a/src/vnet/lisp-gpe/lisp_gpe_adjacency.c +++ b/src/vnet/lisp-gpe/lisp_gpe_adjacency.c @@ -19,12 +19,15 @@ */ #include +#include #include #include #include #include #include #include +#include +#include /** * Memory pool of all adjacencies @@ -96,9 +99,9 @@ lisp_gpe_adj_get_fib_chain_type (const lisp_gpe_adjacency_t * ladj) { switch (ip_addr_version (&ladj->remote_rloc)) { - case IP4: + case AF_IP4: return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4); - case IP6: + case AF_IP6: return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6); default: ASSERT (0); @@ -112,12 +115,12 @@ ip46_address_to_ip_address (const ip46_address_t * a, ip_address_t * b) { if (ip46_address_is_ip4 (a)) { - memset (b, 0, sizeof (*b)); - ip_address_set (b, &a->ip4, IP4); + clib_memset (b, 0, sizeof (*b)); + ip_address_set (b, &a->ip4, AF_IP4); } else { - ip_address_set (b, &a->ip6, IP6); + ip_address_set (b, &a->ip6, AF_IP6); } } @@ -128,48 +131,13 @@ static void lisp_gpe_adj_stack_one (lisp_gpe_adjacency_t * ladj, adj_index_t ai) { const lisp_gpe_tunnel_t *lgt; - dpo_id_t tmp = DPO_INVALID; lgt = lisp_gpe_tunnel_get (ladj->tunnel_index); - fib_entry_contribute_forwarding (lgt->fib_entry_index, - lisp_gpe_adj_get_fib_chain_type (ladj), - &tmp); - if (DPO_LOAD_BALANCE == tmp.dpoi_type) - { - /* - * post LISP rewrite we will load-balance. However, the LISP encap - * is always the same for this adjacency/tunnel and hence the IP/UDP src,dst - * hash is always the same result too. So we do that hash now and - * stack on the choice. - * If the choice is an incomplete adj then we will need a poke when - * it becomes complete. This happens since the adj update walk propagates - * as far a recursive paths. - */ - const dpo_id_t *choice; - load_balance_t *lb; - int hash; - - lb = load_balance_get (tmp.dpoi_index); - - if (IP4 == ip_addr_version (&ladj->remote_rloc)) - { - hash = ip4_compute_flow_hash ((ip4_header_t *) adj_get_rewrite (ai), - lb->lb_hash_config); - } - else - { - hash = ip6_compute_flow_hash ((ip6_header_t *) adj_get_rewrite (ai), - lb->lb_hash_config); - } - - choice = - load_balance_get_bucket_i (lb, hash & lb->lb_n_buckets_minus_1); - dpo_copy (&tmp, choice); - } - - adj_nbr_midchain_stack (ai, &tmp); - dpo_reset (&tmp); + adj_nbr_midchain_stack_on_fib_entry (ai, + lgt->fib_entry_index, + lisp_gpe_adj_get_fib_chain_type + (ladj)); } /** @@ -191,7 +159,7 @@ lisp_gpe_adj_stack (lisp_gpe_adjacency_t * ladj) fib_protocol_t nh_proto; ip46_address_t nh; - ip_address_to_46 (&ladj->remote_rloc, &nh, &nh_proto); + nh_proto = ip_address_to_46 (&ladj->remote_rloc, &nh); /* * walk all the adjacencies on th lisp interface and restack them @@ -221,9 +189,99 @@ 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, + const 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; + 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; + clib_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); + ALWAYS_ASSERT (p); + + /* compute payload length starting after GPE */ + u32 bytes = b->current_length - (lisp_data - b->data - b->current_data); + vlib_increment_combined_counter (&lgm->counters, vlib_get_thread_index (), + p[0], 1, bytes); +} + static void -lisp_gpe_fixup (vlib_main_t * vm, ip_adjacency_t * adj, vlib_buffer_t * b) +lisp_gpe_fixup (vlib_main_t * vm, + const ip_adjacency_t * adj, + vlib_buffer_t * b, const void *data) { + 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))); @@ -241,6 +299,7 @@ lisp_gpe_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai) ip_adjacency_t *adj; ip_address_t rloc; vnet_link_t linkt; + adj_flags_t af; index_t lai; adj = adj_get (ai); @@ -256,11 +315,12 @@ lisp_gpe_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai) ladj = pool_elt_at_index (lisp_adj_pool, lai); lgt = lisp_gpe_tunnel_get (ladj->tunnel_index); linkt = adj_get_link_type (ai); + af = ADJ_FLAG_MIDCHAIN_IP_STACK; + if (VNET_LINK_ETHERNET == linkt) + af |= ADJ_FLAG_MIDCHAIN_NO_COUNT; + adj_nbr_midchain_update_rewrite - (ai, lisp_gpe_fixup, - (VNET_LINK_ETHERNET == linkt ? - ADJ_MIDCHAIN_FLAG_NO_COUNT : - ADJ_MIDCHAIN_FLAG_NONE), + (ai, lisp_gpe_fixup, NULL, af, lisp_gpe_tunnel_build_rewrite (lgt, ladj, lisp_gpe_adj_proto_from_vnet_link_type (linkt))); @@ -303,7 +363,7 @@ lisp_gpe_adjacency_find_or_create_and_lock (const locator_pair_t * pair, { pool_get (lisp_adj_pool, ladj); - memset (ladj, 0, sizeof (*ladj)); + clib_memset (ladj, 0, sizeof (*ladj)); lai = (ladj - lisp_adj_pool); ip_address_copy (&ladj->remote_rloc, &pair->rmt_loc); @@ -514,7 +574,7 @@ lisp_gpe_adjacency_show (vlib_main_t * vm, /* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_lisp_gpe_tunnel_command, static) = { - .path = "show lisp gpe adjacency", + .path = "show gpe adjacency", .function = lisp_gpe_adjacency_show, }; /* *INDENT-ON* */ @@ -534,7 +594,7 @@ lisp_gpe_adj_module_init (vlib_main_t * vm) return (NULL); } -VLIB_INIT_FUNCTION (lisp_gpe_adj_module_init) +VLIB_INIT_FUNCTION (lisp_gpe_adj_module_init); /* * fd.io coding-style-patch-verification: ON *