aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/ip
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/ip')
-rw-r--r--src/vnet/ip/icmp6.c2
-rw-r--r--src/vnet/ip/ip.api17
-rw-r--r--src/vnet/ip/ip.h2
-rw-r--r--src/vnet/ip/ip6.h5
-rw-r--r--src/vnet/ip/ip6_forward.c147
-rw-r--r--src/vnet/ip/ip6_input.h66
-rw-r--r--src/vnet/ip/ip6_ll_table.c78
-rw-r--r--src/vnet/ip/ip_api.c67
-rw-r--r--src/vnet/ip/ip_sas.c2
-rw-r--r--src/vnet/ip/ip_test.c54
-rw-r--r--src/vnet/ip/lookup.c11
11 files changed, 248 insertions, 203 deletions
diff --git a/src/vnet/ip/icmp6.c b/src/vnet/ip/icmp6.c
index b095f679cc8..f93ebce4bf1 100644
--- a/src/vnet/ip/icmp6.c
+++ b/src/vnet/ip/icmp6.c
@@ -338,7 +338,7 @@ ip6_icmp_error (vlib_main_t * vm,
if (throttle_check (&icmp_throttle, thread_index, r0, seed))
{
- vlib_error_count (vm, node->node_index, ICMP4_ERROR_DROP, 1);
+ vlib_error_count (vm, node->node_index, ICMP6_ERROR_DROP, 1);
from += 1;
n_left_from -= 1;
continue;
diff --git a/src/vnet/ip/ip.api b/src/vnet/ip/ip.api
index 967f56cf917..fc7d7582dec 100644
--- a/src/vnet/ip/ip.api
+++ b/src/vnet/ip/ip.api
@@ -57,6 +57,23 @@ autoreply define ip_table_add_del
vl_api_ip_table_t table;
};
+/** \brief Add / del table request - version 2
+ A table can be added multiple times, but need be deleted only once.
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param table - the FIB table to add or del
+ @param create_mfib - whether to create mfib or not
+ @param is_add - add or del
+*/
+autoreply define ip_table_add_del_v2
+{
+ u32 client_index;
+ u32 context;
+ vl_api_ip_table_t table;
+ bool create_mfib [default=true];
+ bool is_add [default=true];
+};
+
/** \brief Allocate an unused table
A table can be added multiple times.
If a large number of tables are in use (millions), this API might
diff --git a/src/vnet/ip/ip.h b/src/vnet/ip/ip.h
index 9ebefa0cf5d..084243dccfa 100644
--- a/src/vnet/ip/ip.h
+++ b/src/vnet/ip/ip.h
@@ -262,7 +262,7 @@ extern vlib_node_registration_t ip4_inacl_node;
extern vlib_node_registration_t ip6_inacl_node;
void ip_table_create (fib_protocol_t fproto, u32 table_id, u8 is_api,
- const u8 * name);
+ u8 create_mfib, const u8 *name);
void ip_table_delete (fib_protocol_t fproto, u32 table_id, u8 is_api);
diff --git a/src/vnet/ip/ip6.h b/src/vnet/ip/ip6.h
index 56eec523d5b..f8462a5cbff 100644
--- a/src/vnet/ip/ip6.h
+++ b/src/vnet/ip/ip6.h
@@ -68,6 +68,11 @@ typedef struct
/* Index into FIB vector. */
u32 index;
+
+ /**
+ * The hash table DB
+ */
+ uword *fib_entry_by_dst_address;
} ip6_fib_t;
typedef struct ip6_mfib_t
diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c
index 48fb633fd32..31adc90ecab 100644
--- a/src/vnet/ip/ip6_forward.c
+++ b/src/vnet/ip/ip6_forward.c
@@ -51,6 +51,7 @@
#include <vnet/dpo/receive_dpo.h>
#include <vnet/dpo/classify_dpo.h>
#include <vnet/classify/vnet_classify.h>
+#include <vnet/adj/adj_dp.h>
#include <vnet/pg/pg.h>
#ifndef CLIB_MARCH_VARIANT
@@ -1897,18 +1898,6 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm,
vnet_buffer (p0)->ip.save_rewrite_length = rw_len0;
vnet_buffer (p1)->ip.save_rewrite_length = rw_len1;
- if (do_counters)
- {
- vlib_increment_combined_counter
- (&adjacency_counters,
- thread_index, adj_index0, 1,
- vlib_buffer_length_in_chain (vm, p0) + rw_len0);
- vlib_increment_combined_counter
- (&adjacency_counters,
- thread_index, adj_index1, 1,
- vlib_buffer_length_in_chain (vm, p1) + rw_len1);
- }
-
/* Check MTU of outgoing interface. */
u16 ip0_len =
clib_net_to_host_u16 (ip0->payload_length) +
@@ -1933,16 +1922,15 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm,
* wants to see the IP header */
if (PREDICT_TRUE (error0 == IP6_ERROR_NONE))
{
- p0->current_data -= rw_len0;
- p0->current_length += rw_len0;
+ vlib_buffer_advance (p0, -(word) rw_len0);
tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index;
vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
next0 = adj0[0].rewrite_header.next_index;
if (PREDICT_FALSE
(adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
- vnet_feature_arc_start_w_cfg_index
- (lm->output_feature_arc_index, tx_sw_if_index0, &next0, p0,
- adj0->ia_cfg_index);
+ vnet_feature_arc_start_w_cfg_index (
+ lm->output_feature_arc_index, tx_sw_if_index0, &next0, p0,
+ adj0->ia_cfg_index);
}
else
{
@@ -1950,18 +1938,16 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm,
}
if (PREDICT_TRUE (error1 == IP6_ERROR_NONE))
{
- p1->current_data -= rw_len1;
- p1->current_length += rw_len1;
-
+ vlib_buffer_advance (p1, -(word) rw_len1);
tx_sw_if_index1 = adj1[0].rewrite_header.sw_if_index;
vnet_buffer (p1)->sw_if_index[VLIB_TX] = tx_sw_if_index1;
next1 = adj1[0].rewrite_header.next_index;
if (PREDICT_FALSE
(adj1[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
- vnet_feature_arc_start_w_cfg_index
- (lm->output_feature_arc_index, tx_sw_if_index1, &next1, p1,
- adj1->ia_cfg_index);
+ vnet_feature_arc_start_w_cfg_index (
+ lm->output_feature_arc_index, tx_sw_if_index1, &next1, p1,
+ adj1->ia_cfg_index);
}
else
{
@@ -1969,40 +1955,46 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm,
}
if (is_midchain)
- {
- /* Guess we are only writing on ipv6 header. */
- vnet_rewrite_two_headers (adj0[0], adj1[0],
- ip0, ip1, sizeof (ip6_header_t));
- }
+ /* Guess we are only writing on ipv6 header. */
+ vnet_rewrite_two_headers (adj0[0], adj1[0], ip0, ip1,
+ sizeof (ip6_header_t));
else
/* Guess we are only writing on simple Ethernet header. */
vnet_rewrite_two_headers (adj0[0], adj1[0],
ip0, ip1, sizeof (ethernet_header_t));
+ if (do_counters)
+ {
+ if (error0 == IP6_ERROR_NONE)
+ vlib_increment_combined_counter (
+ &adjacency_counters, thread_index, adj_index0, 1,
+ vlib_buffer_length_in_chain (vm, p0) + rw_len0);
+ if (error1 == IP6_ERROR_NONE)
+ vlib_increment_combined_counter (
+ &adjacency_counters, thread_index, adj_index1, 1,
+ vlib_buffer_length_in_chain (vm, p1) + rw_len1);
+ }
+
if (is_midchain)
{
- if (adj0->sub_type.midchain.fixup_func)
- adj0->sub_type.midchain.fixup_func
- (vm, adj0, p0, adj0->sub_type.midchain.fixup_data);
- if (adj1->sub_type.midchain.fixup_func)
- adj1->sub_type.midchain.fixup_func
- (vm, adj1, p1, adj1->sub_type.midchain.fixup_data);
+ if (error0 == IP6_ERROR_NONE)
+ adj_midchain_fixup (vm, adj0, p0, VNET_LINK_IP6);
+ if (error1 == IP6_ERROR_NONE)
+ adj_midchain_fixup (vm, adj1, p1, VNET_LINK_IP6);
}
if (is_mcast)
{
/*
* copy bytes from the IP address into the MAC rewrite
*/
- vnet_ip_mcast_fixup_header (IP6_MCAST_ADDR_MASK,
- adj0->
- rewrite_header.dst_mcast_offset,
- &ip0->dst_address.as_u32[3],
- (u8 *) ip0);
- vnet_ip_mcast_fixup_header (IP6_MCAST_ADDR_MASK,
- adj1->
- rewrite_header.dst_mcast_offset,
- &ip1->dst_address.as_u32[3],
- (u8 *) ip1);
+ if (error0 == IP6_ERROR_NONE)
+ vnet_ip_mcast_fixup_header (
+ IP6_MCAST_ADDR_MASK, adj0->rewrite_header.dst_mcast_offset,
+ &ip0->dst_address.as_u32[3], (u8 *) ip0);
+ if (error1 == IP6_ERROR_NONE)
+ vnet_ip_mcast_fixup_header (
+ IP6_MCAST_ADDR_MASK, adj1->rewrite_header.dst_mcast_offset,
+ &ip1->dst_address.as_u32[3], (u8 *) ip1);
}
vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
@@ -2061,28 +2053,10 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm,
}
}
- if (is_midchain)
- {
- /* Guess we are only writing on ip6 header. */
- vnet_rewrite_one_header (adj0[0], ip0, sizeof (ip6_header_t));
- }
- else
- /* Guess we are only writing on simple Ethernet header. */
- vnet_rewrite_one_header (adj0[0], ip0,
- sizeof (ethernet_header_t));
-
/* Update packet buffer attributes/set output interface. */
rw_len0 = adj0[0].rewrite_header.data_bytes;
vnet_buffer (p0)->ip.save_rewrite_length = rw_len0;
- if (do_counters)
- {
- vlib_increment_combined_counter
- (&adjacency_counters,
- thread_index, adj_index0, 1,
- vlib_buffer_length_in_chain (vm, p0) + rw_len0);
- }
-
/* Check MTU of outgoing interface. */
u16 ip0_len =
clib_net_to_host_u16 (ip0->payload_length) +
@@ -2098,9 +2072,7 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm,
* wants to see the IP header */
if (PREDICT_TRUE (error0 == IP6_ERROR_NONE))
{
- p0->current_data -= rw_len0;
- p0->current_length += rw_len0;
-
+ vlib_buffer_advance (p0, -(word) rw_len0);
tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index;
vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
@@ -2108,30 +2080,37 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm,
if (PREDICT_FALSE
(adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
- vnet_feature_arc_start_w_cfg_index
- (lm->output_feature_arc_index, tx_sw_if_index0, &next0, p0,
- adj0->ia_cfg_index);
+ vnet_feature_arc_start_w_cfg_index (
+ lm->output_feature_arc_index, tx_sw_if_index0, &next0, p0,
+ adj0->ia_cfg_index);
+
+ if (is_midchain)
+ /* Guess we are only writing on ip6 header. */
+ vnet_rewrite_one_header (adj0[0], ip0, sizeof (ip6_header_t));
+ else
+ /* Guess we are only writing on simple Ethernet header. */
+ vnet_rewrite_one_header (adj0[0], ip0,
+ sizeof (ethernet_header_t));
+
+ if (do_counters)
+ {
+ vlib_increment_combined_counter (
+ &adjacency_counters, thread_index, adj_index0, 1,
+ vlib_buffer_length_in_chain (vm, p0) + rw_len0);
+ }
+
+ if (is_midchain && adj0->sub_type.midchain.fixup_func)
+ adj_midchain_fixup (vm, adj0, p0, VNET_LINK_IP6);
+ if (is_mcast)
+ vnet_ip_mcast_fixup_header (
+ IP6_MCAST_ADDR_MASK, adj0->rewrite_header.dst_mcast_offset,
+ &ip0->dst_address.as_u32[3], (u8 *) ip0);
}
else
{
p0->error = error_node->errors[error0];
}
- if (is_midchain)
- {
- if (adj0->sub_type.midchain.fixup_func)
- adj0->sub_type.midchain.fixup_func
- (vm, adj0, p0, adj0->sub_type.midchain.fixup_data);
- }
- if (is_mcast)
- {
- vnet_ip_mcast_fixup_header (IP6_MCAST_ADDR_MASK,
- adj0->
- rewrite_header.dst_mcast_offset,
- &ip0->dst_address.as_u32[3],
- (u8 *) ip0);
- }
-
from += 1;
n_left_from -= 1;
to_next += 1;
@@ -2215,7 +2194,7 @@ VLIB_NODE_FN (ip6_mcast_midchain_node) (vlib_main_t * vm,
VLIB_REGISTER_NODE (ip6_midchain_node) = {
.name = "ip6-midchain",
.vector_size = sizeof (u32),
- .format_trace = format_ip6_forward_next_trace,
+ .format_trace = format_ip6_rewrite_trace,
.sibling_of = "ip6-rewrite",
};
diff --git a/src/vnet/ip/ip6_input.h b/src/vnet/ip/ip6_input.h
index 49e37ec1808..25eae62723d 100644
--- a/src/vnet/ip/ip6_input.h
+++ b/src/vnet/ip/ip6_input.h
@@ -53,11 +53,9 @@ typedef enum
} ip6_input_next_t;
always_inline void
-ip6_input_check_x2 (vlib_main_t * vm,
- vlib_node_runtime_t * error_node,
- vlib_buffer_t * p0, vlib_buffer_t * p1,
- ip6_header_t * ip0, ip6_header_t * ip1,
- u32 * next0, u32 * next1)
+ip6_input_check_x2 (vlib_main_t *vm, vlib_node_runtime_t *error_node,
+ vlib_buffer_t *p0, vlib_buffer_t *p1, ip6_header_t *ip0,
+ ip6_header_t *ip1, u32 *next0, u32 *next1)
{
u8 error0, error1;
@@ -65,13 +63,15 @@ ip6_input_check_x2 (vlib_main_t * vm,
/* Version != 6? Drop it. */
error0 =
- (clib_net_to_host_u32
- (ip0->ip_version_traffic_class_and_flow_label) >> 28) !=
- 6 ? IP6_ERROR_VERSION : error0;
+ (clib_net_to_host_u32 (ip0->ip_version_traffic_class_and_flow_label) >>
+ 28) != 6 ?
+ IP6_ERROR_VERSION :
+ error0;
error1 =
- (clib_net_to_host_u32
- (ip1->ip_version_traffic_class_and_flow_label) >> 28) !=
- 6 ? IP6_ERROR_VERSION : error1;
+ (clib_net_to_host_u32 (ip1->ip_version_traffic_class_and_flow_label) >>
+ 28) != 6 ?
+ IP6_ERROR_VERSION :
+ error1;
/* hop limit < 1? Drop it. for link-local broadcast packets,
* like dhcpv6 packets from client has hop-limit 1, which should not
@@ -81,18 +81,18 @@ ip6_input_check_x2 (vlib_main_t * vm,
error1 = ip1->hop_limit < 1 ? IP6_ERROR_TIME_EXPIRED : error1;
/* L2 length must be at least minimal IP header. */
- error0 =
- p0->current_length < sizeof (ip0[0]) ? IP6_ERROR_TOO_SHORT : error0;
- error1 =
- p1->current_length < sizeof (ip1[0]) ? IP6_ERROR_TOO_SHORT : error1;
+ error0 = p0->current_length < sizeof (ip0[0]) ? IP6_ERROR_TOO_SHORT : error0;
+ error1 = p1->current_length < sizeof (ip1[0]) ? IP6_ERROR_TOO_SHORT : error1;
if (PREDICT_FALSE (error0 != IP6_ERROR_NONE))
{
+ p0->error = error_node->errors[error0];
+
if (error0 == IP6_ERROR_TIME_EXPIRED)
{
- icmp6_error_set_vnet_buffer (p0, ICMP6_time_exceeded,
- ICMP6_time_exceeded_ttl_exceeded_in_transit,
- 0);
+ icmp6_error_set_vnet_buffer (
+ p0, ICMP6_time_exceeded,
+ ICMP6_time_exceeded_ttl_exceeded_in_transit, 0);
*next0 = IP6_INPUT_NEXT_ICMP_ERROR;
}
else
@@ -102,11 +102,13 @@ ip6_input_check_x2 (vlib_main_t * vm,
}
if (PREDICT_FALSE (error1 != IP6_ERROR_NONE))
{
+ p1->error = error_node->errors[error1];
+
if (error1 == IP6_ERROR_TIME_EXPIRED)
{
- icmp6_error_set_vnet_buffer (p1, ICMP6_time_exceeded,
- ICMP6_time_exceeded_ttl_exceeded_in_transit,
- 0);
+ icmp6_error_set_vnet_buffer (
+ p1, ICMP6_time_exceeded,
+ ICMP6_time_exceeded_ttl_exceeded_in_transit, 0);
*next1 = IP6_INPUT_NEXT_ICMP_ERROR;
}
else
@@ -117,9 +119,8 @@ ip6_input_check_x2 (vlib_main_t * vm,
}
always_inline void
-ip6_input_check_x1 (vlib_main_t * vm,
- vlib_node_runtime_t * error_node,
- vlib_buffer_t * p0, ip6_header_t * ip0, u32 * next0)
+ip6_input_check_x1 (vlib_main_t *vm, vlib_node_runtime_t *error_node,
+ vlib_buffer_t *p0, ip6_header_t *ip0, u32 *next0)
{
u8 error0;
@@ -127,9 +128,10 @@ ip6_input_check_x1 (vlib_main_t * vm,
/* Version != 6? Drop it. */
error0 =
- (clib_net_to_host_u32
- (ip0->ip_version_traffic_class_and_flow_label) >> 28) !=
- 6 ? IP6_ERROR_VERSION : error0;
+ (clib_net_to_host_u32 (ip0->ip_version_traffic_class_and_flow_label) >>
+ 28) != 6 ?
+ IP6_ERROR_VERSION :
+ error0;
/* hop limit < 1? Drop it. for link-local broadcast packets,
* like dhcpv6 packets from client has hop-limit 1, which should not
@@ -138,16 +140,16 @@ ip6_input_check_x1 (vlib_main_t * vm,
error0 = ip0->hop_limit < 1 ? IP6_ERROR_TIME_EXPIRED : error0;
/* L2 length must be at least minimal IP header. */
- error0 =
- p0->current_length < sizeof (ip0[0]) ? IP6_ERROR_TOO_SHORT : error0;
+ error0 = p0->current_length < sizeof (ip0[0]) ? IP6_ERROR_TOO_SHORT : error0;
if (PREDICT_FALSE (error0 != IP6_ERROR_NONE))
{
+ p0->error = error_node->errors[error0];
if (error0 == IP6_ERROR_TIME_EXPIRED)
{
- icmp6_error_set_vnet_buffer (p0, ICMP6_time_exceeded,
- ICMP6_time_exceeded_ttl_exceeded_in_transit,
- 0);
+ icmp6_error_set_vnet_buffer (
+ p0, ICMP6_time_exceeded,
+ ICMP6_time_exceeded_ttl_exceeded_in_transit, 0);
*next0 = IP6_INPUT_NEXT_ICMP_ERROR;
}
else
diff --git a/src/vnet/ip/ip6_ll_table.c b/src/vnet/ip/ip6_ll_table.c
index f9172f6c50c..2234ea9df37 100644
--- a/src/vnet/ip/ip6_ll_table.c
+++ b/src/vnet/ip/ip6_ll_table.c
@@ -144,17 +144,20 @@ ip6_ll_table_entry_delete (const ip6_ll_prefix_t * ilp)
fib_node_index_t ip6_ll_entry_index;
u32 fib_index;
+ fib_index = ip6_ll_fib_get (ilp->ilp_sw_if_index);
+ if (~0 == fib_index)
+ return;
+
ip6_ll_entry_index = ip6_ll_table_lookup_exact_match (ilp);
+ if (FIB_NODE_INDEX_INVALID == ip6_ll_entry_index)
+ return;
- if (FIB_NODE_INDEX_INVALID != ip6_ll_entry_index)
- fib_table_entry_delete_index (ip6_ll_entry_index, FIB_SOURCE_IP6_ND);
+ fib_table_entry_delete_index (ip6_ll_entry_index, FIB_SOURCE_IP6_ND);
/*
* if there are no ND sourced prefixes left, then we can clean up this FIB
*/
- fib_index = ip6_ll_fib_get (ilp->ilp_sw_if_index);
- if (~0 != fib_index &&
- 0 == fib_table_get_num_entries (fib_index, FIB_PROTOCOL_IP6,
+ if (0 == fib_table_get_num_entries (fib_index, FIB_PROTOCOL_IP6,
FIB_SOURCE_IP6_ND))
{
fib_table_unlock (fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_IP6_ND);
@@ -208,33 +211,10 @@ ip6_ll_table_show_all (vlib_main_t * vm, u32 fib_index)
vec_free (ctx.entries);
}
-typedef struct
-{
- u32 fib_index;
- u64 count_by_prefix_length[129];
-} count_routes_in_fib_at_prefix_length_arg_t;
-
-static int
-count_routes_in_fib_at_prefix_length (clib_bihash_kv_24_8_t * kvp, void *arg)
-{
- count_routes_in_fib_at_prefix_length_arg_t *ap = arg;
- int mask_width;
-
- if ((kvp->key[2] >> 32) != ap->fib_index)
- return (BIHASH_WALK_CONTINUE);
-
- mask_width = kvp->key[2] & 0xFF;
-
- ap->count_by_prefix_length[mask_width]++;
-
- return (BIHASH_WALK_CONTINUE);
-}
-
static clib_error_t *
ip6_ll_show_fib (vlib_main_t * vm,
unformat_input_t * input, vlib_cli_command_t * cmd)
{
- count_routes_in_fib_at_prefix_length_arg_t _ca, *ca = &_ca;
fib_table_t *fib_table;
int verbose, matching;
ip6_address_t matching_address;
@@ -272,9 +252,6 @@ ip6_ll_show_fib (vlib_main_t * vm,
vec_foreach_index (sw_if_index, ip6_ll_table.ilt_fibs)
{
- fib_source_t source;
- u8 *s = NULL;
-
fib_index = ip6_ll_table.ilt_fibs[sw_if_index];
if (~0 == fib_index)
continue;
@@ -284,44 +261,9 @@ ip6_ll_show_fib (vlib_main_t * vm,
if (!(fib_table->ft_flags & FIB_TABLE_FLAG_IP6_LL))
continue;
- s = format (s, "%U, fib_index:%d, locks:[",
- format_fib_table_name, fib_index,
- FIB_PROTOCOL_IP6, fib_index);
- vec_foreach_index (source, fib_table->ft_locks)
- {
- if (0 != fib_table->ft_locks[source])
- {
- s = format (s, "%U:%d, ",
- format_fib_source, source, fib_table->ft_locks[source]);
- }
- }
- s = format (s, "]");
- vlib_cli_output (vm, "%v", s);
- vec_free (s);
-
- /* Show summary? */
+ ip6_fib_table_show (vm, fib_table, !verbose);
if (!verbose)
- {
- clib_bihash_24_8_t *h =
- &ip6_fib_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash;
- int len;
-
- vlib_cli_output (vm, "%=20s%=16s", "Prefix length", "Count");
-
- clib_memset (ca, 0, sizeof (*ca));
- ca->fib_index = fib_index;
-
- clib_bihash_foreach_key_value_pair_24_8
- (h, count_routes_in_fib_at_prefix_length, ca);
-
- for (len = 128; len >= 0; len--)
- {
- if (ca->count_by_prefix_length[len])
- vlib_cli_output (vm, "%=20d%=16lld",
- len, ca->count_by_prefix_length[len]);
- }
- continue;
- }
+ continue;
if (!matching)
{
diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c
index 644b4988abc..5ced88fec2e 100644
--- a/src/vnet/ip/ip_api.c
+++ b/src/vnet/ip/ip_api.c
@@ -636,7 +636,8 @@ vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp)
if (mp->is_add)
{
- ip_table_create (fproto, table_id, 1, mp->table.name);
+ ip_table_create (fproto, table_id, 1 /* is_api */, 1 /* create_mfib */,
+ mp->table.name);
}
else
{
@@ -647,6 +648,28 @@ vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp)
}
void
+vl_api_ip_table_add_del_v2_t_handler (vl_api_ip_table_add_del_v2_t *mp)
+{
+ vl_api_ip_table_add_del_v2_reply_t *rmp;
+ fib_protocol_t fproto =
+ (mp->table.is_ip6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
+ u32 table_id = ntohl (mp->table.table_id);
+ int rv = 0;
+
+ if (mp->is_add)
+ {
+ ip_table_create (fproto, table_id, 1 /* is_api */, mp->create_mfib,
+ mp->table.name);
+ }
+ else
+ {
+ ip_table_delete (fproto, table_id, 1);
+ }
+
+ REPLY_MACRO (VL_API_IP_TABLE_ADD_DEL_V2_REPLY);
+}
+
+void
vl_api_ip_table_allocate_t_handler (vl_api_ip_table_allocate_t *mp)
{
vl_api_ip_table_allocate_reply_t *rmp;
@@ -661,7 +684,8 @@ vl_api_ip_table_allocate_t_handler (vl_api_ip_table_allocate_t *mp)
if (~0 == table_id)
rv = VNET_API_ERROR_EAGAIN;
else
- ip_table_create (fproto, table_id, 1, mp->table.name);
+ ip_table_create (fproto, table_id, 1 /* is_api */, 1 /* create_mfib */,
+ mp->table.name);
REPLY_MACRO2 (VL_API_IP_TABLE_ALLOCATE_REPLY, {
clib_memcpy_fast (&rmp->table, &mp->table, sizeof (mp->table));
@@ -915,8 +939,8 @@ vl_api_ip_route_lookup_v2_t_handler (vl_api_ip_route_lookup_v2_t *mp)
}
void
-ip_table_create (fib_protocol_t fproto,
- u32 table_id, u8 is_api, const u8 * name)
+ip_table_create (fib_protocol_t fproto, u32 table_id, u8 is_api,
+ u8 create_mfib, const u8 *name)
{
u32 fib_index, mfib_index;
vnet_main_t *vnm = vnet_get_main ();
@@ -936,16 +960,23 @@ ip_table_create (fib_protocol_t fproto,
* their own unicast tables.
*/
fib_index = fib_table_find (fproto, table_id);
- mfib_index = mfib_table_find (fproto, table_id);
-
/*
* Always try to re-lock in case the fib was deleted by an API call
* but was not yet freed because some other locks were held
*/
fib_table_find_or_create_and_lock_w_name (
fproto, table_id, (is_api ? FIB_SOURCE_API : FIB_SOURCE_CLI), name);
- mfib_table_find_or_create_and_lock_w_name (
- fproto, table_id, (is_api ? MFIB_SOURCE_API : MFIB_SOURCE_CLI), name);
+
+ if (create_mfib)
+ {
+ /* same for mfib, if needs be */
+ mfib_index = mfib_table_find (fproto, table_id);
+ mfib_table_find_or_create_and_lock_w_name (
+ fproto, table_id, (is_api ? MFIB_SOURCE_API : MFIB_SOURCE_CLI),
+ name);
+ }
+ else
+ mfib_index = 0;
if ((~0 == fib_index) || (~0 == mfib_index))
call_elf_section_ip_table_callbacks (vnm, table_id, 1 /* is_add */ ,
@@ -1655,9 +1686,10 @@ vl_api_ip_table_replace_begin_t_handler (vl_api_ip_table_replace_begin_t * mp)
rv = VNET_API_ERROR_NO_SUCH_FIB;
else
{
+ u32 mfib_index = mfib_table_find (fproto, ntohl (mp->table.table_id));
fib_table_mark (fib_index, fproto, FIB_SOURCE_API);
- mfib_table_mark (mfib_table_find (fproto, ntohl (mp->table.table_id)),
- fproto, MFIB_SOURCE_API);
+ if (mfib_index != INDEX_INVALID)
+ mfib_table_mark (mfib_index, fproto, MFIB_SOURCE_API);
}
REPLY_MACRO (VL_API_IP_TABLE_REPLACE_BEGIN_REPLY);
}
@@ -1677,10 +1709,10 @@ vl_api_ip_table_replace_end_t_handler (vl_api_ip_table_replace_end_t * mp)
rv = VNET_API_ERROR_NO_SUCH_FIB;
else
{
+ u32 mfib_index = mfib_table_find (fproto, ntohl (mp->table.table_id));
fib_table_sweep (fib_index, fproto, FIB_SOURCE_API);
- mfib_table_sweep (mfib_table_find
- (fproto, ntohl (mp->table.table_id)), fproto,
- MFIB_SOURCE_API);
+ if (mfib_index != INDEX_INVALID)
+ mfib_table_sweep (mfib_index, fproto, MFIB_SOURCE_API);
}
REPLY_MACRO (VL_API_IP_TABLE_REPLACE_END_REPLY);
}
@@ -1703,6 +1735,7 @@ vl_api_ip_table_flush_t_handler (vl_api_ip_table_flush_t * mp)
vnet_main_t *vnm = vnet_get_main ();
vnet_interface_main_t *im = &vnm->interface_main;
vnet_sw_interface_t *si;
+ u32 mfib_index;
/* Shut down interfaces in this FIB / clean out intfc routes */
pool_foreach (si, im->sw_interfaces)
@@ -1717,8 +1750,10 @@ vl_api_ip_table_flush_t_handler (vl_api_ip_table_flush_t * mp)
}
fib_table_flush (fib_index, fproto, FIB_SOURCE_API);
- mfib_table_flush (mfib_table_find (fproto, ntohl (mp->table.table_id)),
- fproto, MFIB_SOURCE_API);
+
+ mfib_index = mfib_table_find (fproto, ntohl (mp->table.table_id));
+ if (mfib_index != INDEX_INVALID)
+ mfib_table_flush (mfib_index, fproto, MFIB_SOURCE_API);
}
REPLY_MACRO (VL_API_IP_TABLE_FLUSH_REPLY);
@@ -2128,6 +2163,8 @@ ip_api_hookup (vlib_main_t * vm)
am, REPLY_MSG_ID_BASE + VL_API_IP_ROUTE_ADD_DEL_V2, 1);
vl_api_set_msg_thread_safe (
am, REPLY_MSG_ID_BASE + VL_API_IP_ROUTE_ADD_DEL_V2_REPLY, 1);
+ vl_api_set_msg_thread_safe (am, REPLY_MSG_ID_BASE + VL_API_IP_ADDRESS_DUMP,
+ 1);
return 0;
}
diff --git a/src/vnet/ip/ip_sas.c b/src/vnet/ip/ip_sas.c
index 0fc261724f1..01f6c90baf8 100644
--- a/src/vnet/ip/ip_sas.c
+++ b/src/vnet/ip/ip_sas.c
@@ -54,6 +54,8 @@ ip6_sas_commonlen (const ip6_address_t *a1, const ip6_address_t *a2)
static int
ip4_sas_commonlen (const ip4_address_t *a1, const ip4_address_t *a2)
{
+ if (!a1 || !a2)
+ return 0;
u64 a =
clib_net_to_host_u32 (a1->as_u32) ^ clib_net_to_host_u32 (a2->as_u32);
if (a == 0)
diff --git a/src/vnet/ip/ip_test.c b/src/vnet/ip/ip_test.c
index 727afba67f4..0d1c71063ae 100644
--- a/src/vnet/ip/ip_test.c
+++ b/src/vnet/ip/ip_test.c
@@ -464,6 +464,60 @@ api_ip_table_add_del (vat_main_t *vam)
}
static int
+api_ip_table_add_del_v2 (vat_main_t *vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_ip_table_add_del_v2_t *mp;
+ u8 create_mfib = 1;
+ u32 table_id = ~0;
+ u8 is_ipv6 = 0;
+ u8 is_add = 1;
+ int ret = 0;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "ipv6"))
+ is_ipv6 = 1;
+ else if (unformat (i, "del"))
+ is_add = 0;
+ else if (unformat (i, "add"))
+ is_add = 1;
+ else if (unformat (i, "table %d", &table_id))
+ ;
+ else if (unformat (i, "no-mfib"))
+ create_mfib = 0;
+ else
+ {
+ clib_warning ("parse error '%U'", format_unformat_error, i);
+ return -99;
+ }
+ }
+
+ if (~0 == table_id)
+ {
+ errmsg ("missing table-ID");
+ return -99;
+ }
+
+ /* Construct the API message */
+ M (IP_TABLE_ADD_DEL_V2, mp);
+
+ mp->table.table_id = ntohl (table_id);
+ mp->table.is_ip6 = is_ipv6;
+ mp->is_add = is_add;
+ mp->create_mfib = create_mfib;
+
+ /* send it... */
+ S (mp);
+
+ /* Wait for a reply... */
+ W (ret);
+
+ return ret;
+}
+
+static int
api_ip_table_replace_begin (vat_main_t *vam)
{
unformat_input_t *i = vam->input;
diff --git a/src/vnet/ip/lookup.c b/src/vnet/ip/lookup.c
index c225c222a38..b978bd79742 100644
--- a/src/vnet/ip/lookup.c
+++ b/src/vnet/ip/lookup.c
@@ -419,10 +419,12 @@ vnet_ip_table_cmd (vlib_main_t * vm,
unformat_input_t _line_input, *line_input = &_line_input;
clib_error_t *error = NULL;
u32 table_id, is_add;
+ u8 create_mfib;
u8 *name = NULL;
is_add = 1;
table_id = ~0;
+ create_mfib = 1;
/* Get a line of input. */
if (!unformat_user (main_input, unformat_line_input, line_input))
@@ -438,6 +440,8 @@ vnet_ip_table_cmd (vlib_main_t * vm,
is_add = 1;
else if (unformat (line_input, "name %s", &name))
;
+ else if (unformat (line_input, "no-mfib"))
+ create_mfib = 0;
else
{
error = unformat_parse_error (line_input);
@@ -459,7 +463,8 @@ vnet_ip_table_cmd (vlib_main_t * vm,
table_id = ip_table_get_unused_id (fproto);
vlib_cli_output (vm, "%u\n", table_id);
}
- ip_table_create (fproto, table_id, 0, name);
+ ip_table_create (fproto, table_id, 0 /* is_api */, create_mfib,
+ name);
}
else
{
@@ -603,6 +608,8 @@ VLIB_CLI_COMMAND (vlib_cli_show_ip6_command, static) = {
* @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0 weight 3}
* To add a route to a particular FIB table (VRF), use:
* @cliexcmd{ip route add 172.16.24.0/24 table 7 via GigabitEthernet2/0/0}
+ * To add a route to drop the traffic:
+ * @cliexcmd{ip route add 172.16.24.0/24 table 100 via 127.0.0.1 drop}
?*/
VLIB_CLI_COMMAND (ip_route_command, static) = {
.path = "ip route",
@@ -612,7 +619,7 @@ VLIB_CLI_COMMAND (ip_route_command, static) = {
"<value>] [udp-encap <value>] [ip4-lookup-in-table <value>] "
"[ip6-lookup-in-table <value>] [mpls-lookup-in-table <value>] "
"[resolve-via-host] [resolve-via-connected] [rx-ip4|rx-ip6 "
- "<interface>] [out-labels <value value value>]",
+ "<interface>] [out-labels <value value value>] [drop]",
.function = vnet_ip_route_cmd,
.is_mp_safe = 1,
};