#include <vnet/vnet.h>
#include <vnet/ip/ip.h>
#include <vnet/ip/ip_frag.h>
-#include <vnet/ip/ip6_neighbor.h>
+#include <vnet/ip/ip6_link.h>
#include <vnet/ethernet/ethernet.h> /* for ethernet_header_t */
#include <vnet/srp/srp.h> /* for srp_hw_interface_class */
#include <vppinfra/cache.h>
#include <vnet/mfib/ip6_mfib.h>
#include <vnet/dpo/load_balance_map.h>
#include <vnet/dpo/classify_dpo.h>
+#include <vnet/classify/vnet_classify.h>
#ifndef CLIB_MARCH_VARIANT
#include <vppinfra/bihash_template.c>
#endif
#include <vnet/ip/ip6_forward.h>
+#include <vnet/ipsec/ipsec_tun.h>
#include <vnet/interface_output.h>
/* Flag used by IOAM code. Classifier sets it pop-hop-by-hop checks it */
ip6_sw_interface_enable_disable (u32 sw_if_index, u32 is_enable)
{
ip6_main_t *im = &ip6_main;
+ vnet_main_t *vnm = vnet_get_main ();
+ vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
vec_validate_init_empty (im->ip_enabled_by_sw_if_index, sw_if_index, 0);
vnet_feature_enable_disable ("ip6-multicast", "ip6-not-enabled",
sw_if_index, !is_enable, 0, 0);
+
+ if (is_enable)
+ hi->l3_if_count++;
+ else if (hi->l3_if_count)
+ hi->l3_if_count--;
}
/* get first interface address */
vnet_main_t *vnm = vnet_get_main ();
ip6_main_t *im = &ip6_main;
ip_lookup_main_t *lm = &im->lookup_main;
- clib_error_t *error;
+ clib_error_t *error = NULL;
u32 if_address_index;
ip6_address_fib_t ip6_af, *addr_fib = 0;
- ip6_address_t ll_addr;
+ const ip6_address_t *ll_addr;
/* local0 interface doesn't support IP addressing */
if (sw_if_index == 0)
}
if (!is_del)
{
- return ip6_neighbor_set_link_local_address (vm, sw_if_index,
- address);
+ int rv;
+
+ rv = ip6_link_set_local_address (sw_if_index, address);
+
+ if (rv)
+ {
+ vnm->api_errno = rv;
+ return clib_error_create ("address not assignable");
+ }
}
else
{
- ll_addr = ip6_neighbor_get_link_local_address (sw_if_index);
- if (ip6_address_is_equal (&ll_addr, address))
+ ll_addr = ip6_get_link_local_address (sw_if_index);
+ if (ip6_address_is_equal (ll_addr, address))
{
vnm->api_errno = VNET_API_ERROR_ADDRESS_NOT_DELETABLE;
return clib_error_create ("address not deletable");
return clib_error_create ("address not found");
}
}
+
+ return (NULL);
}
vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
ip_interface_address_t *ia;
vnet_sw_interface_t *sif;
- pool_foreach(sif, vnm->interface_main.sw_interfaces,
- ({
+ pool_foreach (sif, vnm->interface_main.sw_interfaces)
+ {
if (im->fib_index_by_sw_if_index[sw_if_index] ==
im->fib_index_by_sw_if_index[sif->sw_if_index])
{
ip6_address_t * x =
ip_interface_address_get_address
(&im->lookup_main, ia);
+
if (ip6_destination_matches_route
(im, address, x, ia->address_length) ||
ip6_destination_matches_route (im,
!ip6_address_is_equal (x, address))
continue;
+ if (ia->flags & IP_INTERFACE_ADDRESS_FLAG_STALE)
+ /* if the address we're comparing against is stale
+ * then the CP has not added this one back yet, maybe
+ * it never will, so we have to assume it won't and
+ * ignore it. if it does add it back, then it will fail
+ * because this one is now present */
+ continue;
+
/* error if the length or intf was different */
vnm->api_errno = VNET_API_ERROR_DUPLICATE_IF_ADDRESS;
- return
- clib_error_create
+ error = clib_error_create
("failed to add %U which conflicts with %U for interface %U",
format_ip6_address_and_length, address,
address_length,
ia->address_length,
format_vnet_sw_if_index_name, vnm,
sif->sw_if_index);
+ goto done;
}
}));
}
- }));
+ }
}
/* *INDENT-ON* */
- {
- uword elts_before = pool_elts (lm->if_address_pool);
+ if_address_index = ip_interface_address_find (lm, addr_fib, address_length);
- error = ip_interface_address_add_del
- (lm, sw_if_index, addr_fib, address_length, is_del, &if_address_index);
- if (error)
- goto done;
+ if (is_del)
+ {
+ if (~0 == if_address_index)
+ {
+ vnm->api_errno = VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE;
+ error = clib_error_create ("%U not found for interface %U",
+ lm->format_address_and_length,
+ addr_fib, address_length,
+ format_vnet_sw_if_index_name, vnm,
+ sw_if_index);
+ goto done;
+ }
- /* Pool did not grow: add duplicate address. */
- if (elts_before == pool_elts (lm->if_address_pool))
- goto done;
- }
+ error = ip_interface_address_del (lm, vnm, if_address_index, addr_fib,
+ address_length, sw_if_index);
+ if (error)
+ goto done;
+ }
+ else
+ {
+ if (~0 != if_address_index)
+ {
+ ip_interface_address_t *ia;
+
+ ia = pool_elt_at_index (lm->if_address_pool, if_address_index);
+
+ if (ia->flags & IP_INTERFACE_ADDRESS_FLAG_STALE)
+ {
+ if (ia->sw_if_index == sw_if_index)
+ {
+ /* re-adding an address during the replace action.
+ * consdier this the update. clear the flag and
+ * we're done */
+ ia->flags &= ~IP_INTERFACE_ADDRESS_FLAG_STALE;
+ goto done;
+ }
+ else
+ {
+ /* The prefix is moving from one interface to another.
+ * delete the stale and add the new */
+ ip6_add_del_interface_address (vm,
+ ia->sw_if_index,
+ address, address_length, 1);
+ ia = NULL;
+ error = ip_interface_address_add (lm, sw_if_index,
+ addr_fib, address_length,
+ &if_address_index);
+ }
+ }
+ else
+ {
+ vnm->api_errno = VNET_API_ERROR_DUPLICATE_IF_ADDRESS;
+ error = clib_error_create
+ ("Prefix %U already found on interface %U",
+ lm->format_address_and_length, addr_fib, address_length,
+ format_vnet_sw_if_index_name, vnm, ia->sw_if_index);
+ }
+ }
+ else
+ error = ip_interface_address_add (lm, sw_if_index,
+ addr_fib, address_length,
+ &if_address_index);
+ }
+
+ if (error)
+ goto done;
ip6_sw_interface_enable_disable (sw_if_index, !is_del);
+ if (!is_del)
+ ip6_link_enable (sw_if_index, NULL);
/* intf addr routes are added/deleted on admin up/down */
if (vnet_sw_interface_is_admin_up (vnm, sw_if_index))
pool_elt_at_index (lm->if_address_pool,
if_address_index));
}
- {
- ip6_add_del_interface_address_callback_t *cb;
- vec_foreach (cb, im->add_del_interface_address_callbacks)
- cb->function (im, cb->function_opaque, sw_if_index,
- address, address_length, if_address_index, is_del);
- }
+
+ ip6_add_del_interface_address_callback_t *cb;
+ vec_foreach (cb, im->add_del_interface_address_callbacks)
+ cb->function (im, cb->function_opaque, sw_if_index,
+ address, address_length, if_address_index, is_del);
+
+ if (is_del)
+ ip6_link_disable (sw_if_index);
done:
vec_free (addr_fib);
ip6_address_t *address;
vlib_main_t *vm = vlib_get_main ();
- ip6_neighbor_sw_interface_add_del (vnm, sw_if_index, 0 /* is_add */ );
vnet_sw_interface_update_unnumbered (sw_if_index, ~0, 0);
/* *INDENT-OFF* */
foreach_ip_interface_address (lm6, ia, sw_if_index, 0,
ip6_forward_next_trace_t *t = va_arg (*args, ip6_forward_next_trace_t *);
u32 indent = format_get_indent (s);
- s = format (s, "%U%U",
+ s = format (s, "%Ufib:%d adj:%d flow:%d",
+ format_white_space, indent,
+ t->fib_index, t->adj_index, t->flow_hash);
+ s = format (s, "\n%U%U",
format_white_space, indent,
format_ip6_header, t->packet_data, sizeof (t->packet_data));
return s;
ip6_tcp_udp_icmp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
ip6_header_t * ip0, int *bogus_lengthp)
{
- ip_csum_t sum0;
- u16 payload_length_host_byte_order;
+ ip_csum_t sum0 = 0;
+ u16 payload_length, payload_length_host_byte_order;
u32 i;
u32 headers_size = sizeof (ip0[0]);
u8 *data_this_buffer;
+ u8 next_hdr = ip0->protocol;
ASSERT (bogus_lengthp);
*bogus_lengthp = 0;
- /* Initialize checksum with ip header. */
- sum0 = ip0->payload_length + clib_host_to_net_u16 (ip0->protocol);
payload_length_host_byte_order = clib_net_to_host_u16 (ip0->payload_length);
data_this_buffer = (u8 *) (ip0 + 1);
-
- for (i = 0; i < ARRAY_LEN (ip0->src_address.as_uword); i++)
- {
- sum0 = ip_csum_with_carry
- (sum0, clib_mem_unaligned (&ip0->src_address.as_uword[i], uword));
- sum0 = ip_csum_with_carry
- (sum0, clib_mem_unaligned (&ip0->dst_address.as_uword[i], uword));
- }
+ payload_length = ip0->payload_length;
/* some icmp packets may come with a "router alert" hop-by-hop extension header (e.g., mldv2 packets)
* or UDP-Ping packets */
- if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS))
+ if (PREDICT_FALSE (next_hdr == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS))
{
u32 skip_bytes;
ip6_hop_by_hop_ext_t *ext_hdr =
payload_length_host_byte_order -= skip_bytes;
headers_size += skip_bytes;
+
+ /* pseudo-header adjustments:
+ * exclude ext header bytes from payload length
+ * use payload IP proto rather than ext header IP proto
+ */
+ payload_length = clib_host_to_net_u16 (payload_length_host_byte_order);
+ next_hdr = ext_hdr->next_hdr;
+ }
+
+ /* Initialize checksum with ip pseudo-header. */
+ sum0 = payload_length + clib_host_to_net_u16 (next_hdr);
+
+ for (i = 0; i < ARRAY_LEN (ip0->src_address.as_uword); i++)
+ {
+ sum0 = ip_csum_with_carry
+ (sum0, clib_mem_unaligned (&ip0->src_address.as_uword[i], uword));
+ sum0 = ip_csum_with_carry
+ (sum0, clib_mem_unaligned (&ip0->dst_address.as_uword[i], uword));
}
if (p0)
payload_length_host_byte_order = clib_net_to_host_u16 (ip0->payload_length);
n_bytes_left = n_this_buffer = payload_length_host_byte_order;
- if (p0)
+
+ u32 n_ip_bytes_this_buffer =
+ p0->current_length - (((u8 *) ip0 - p0->data) - p0->current_data);
+ if (n_this_buffer + headers_size > n_ip_bytes_this_buffer)
{
- u32 n_ip_bytes_this_buffer =
- p0->current_length - (((u8 *) ip0 - p0->data) - p0->current_data);
- if (n_this_buffer + headers_size > n_ip_bytes_this_buffer)
- {
- n_this_buffer = p0->current_length > headers_size ?
- n_ip_bytes_this_buffer - headers_size : 0;
- }
+ n_this_buffer = p0->current_length > headers_size ?
+ n_ip_bytes_this_buffer - headers_size : 0;
}
n_bytes_left -= n_this_buffer;
vlib_prefetch_buffer_data (b[3], LOAD);
}
- u8 error[2];
+ ip6_error_t error[2];
error[0] = IP6_ERROR_UNKNOWN_PROTOCOL;
error[1] = IP6_ERROR_UNKNOWN_PROTOCOL;
next[1] =
error[1] != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next[1];
- b[0]->error = error_node->errors[0];
- b[1]->error = error_node->errors[1];
+ b[0]->error = error_node->errors[error[0]];
+ b[1]->error = error_node->errors[error[1]];
if (head_of_feature_arc)
{
next[0] =
error != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next[0];
- b[0]->error = error_node->errors[0];
+ b[0]->error = error_node->errors[error];
if (head_of_feature_arc)
{
#ifdef CLIB_MARCH_VARIANT
extern vlib_node_registration_t ip6_local_node;
-
#else
-
void
ip6_register_protocol (u32 protocol, u32 node_index)
{
ASSERT (protocol < ARRAY_LEN (lm->local_next_by_ip_protocol));
lm->local_next_by_ip_protocol[protocol] = IP_LOCAL_NEXT_PUNT;
}
-
-clib_error_t *
-ip6_probe_neighbor (vlib_main_t * vm, ip6_address_t * dst, u32 sw_if_index,
- u8 refresh)
-{
- vnet_main_t *vnm = vnet_get_main ();
- ip6_main_t *im = &ip6_main;
- icmp6_neighbor_solicitation_header_t *h;
- ip6_address_t *src;
- ip_interface_address_t *ia;
- ip_adjacency_t *adj;
- vnet_hw_interface_t *hi;
- vnet_sw_interface_t *si;
- vlib_buffer_t *b;
- adj_index_t ai;
- u32 bi = 0;
- int bogus_length;
-
- si = vnet_get_sw_interface (vnm, sw_if_index);
-
- if (!(si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
- {
- return clib_error_return (0, "%U: interface %U down",
- format_ip6_address, dst,
- format_vnet_sw_if_index_name, vnm,
- sw_if_index);
- }
-
- src =
- ip6_interface_address_matching_destination (im, dst, sw_if_index, &ia);
- if (!src)
- {
- vnm->api_errno = VNET_API_ERROR_NO_MATCHING_INTERFACE;
- return clib_error_return
- (0, "no matching interface address for destination %U (interface %U)",
- format_ip6_address, dst,
- format_vnet_sw_if_index_name, vnm, sw_if_index);
- }
-
- h =
- vlib_packet_template_get_packet (vm,
- &im->discover_neighbor_packet_template,
- &bi);
- if (!h)
- return clib_error_return (0, "ICMP6 NS packet allocation failed");
-
- hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
-
- /* Destination address is a solicited node multicast address. We need to fill in
- the low 24 bits with low 24 bits of target's address. */
- h->ip.dst_address.as_u8[13] = dst->as_u8[13];
- h->ip.dst_address.as_u8[14] = dst->as_u8[14];
- h->ip.dst_address.as_u8[15] = dst->as_u8[15];
-
- h->ip.src_address = src[0];
- h->neighbor.target_address = dst[0];
-
- if (PREDICT_FALSE (!hi->hw_address))
- {
- return clib_error_return (0, "%U: interface %U do not support ip probe",
- format_ip6_address, dst,
- format_vnet_sw_if_index_name, vnm,
- sw_if_index);
- }
-
- clib_memcpy_fast (h->link_layer_option.ethernet_address, hi->hw_address,
- vec_len (hi->hw_address));
-
- h->neighbor.icmp.checksum =
- ip6_tcp_udp_icmp_compute_checksum (vm, 0, &h->ip, &bogus_length);
- ASSERT (bogus_length == 0);
-
- b = vlib_get_buffer (vm, bi);
- vnet_buffer (b)->sw_if_index[VLIB_RX] =
- vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index;
-
- /* Add encapsulation string for software interface (e.g. ethernet header). */
- ip46_address_t nh = {
- .ip6 = *dst,
- };
-
- ai = adj_nbr_add_or_lock (FIB_PROTOCOL_IP6,
- VNET_LINK_IP6, &nh, sw_if_index);
- adj = adj_get (ai);
-
- /* Peer has been previously resolved, retrieve glean adj instead */
- if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE && refresh == 0)
- {
- adj_unlock (ai);
- ai = adj_glean_add_or_lock (FIB_PROTOCOL_IP6,
- VNET_LINK_IP6, sw_if_index, &nh);
- adj = adj_get (ai);
- }
-
- vnet_rewrite_one_header (adj[0], h, sizeof (ethernet_header_t));
- vlib_buffer_advance (b, -adj->rewrite_header.data_bytes);
-
- {
- vlib_frame_t *f = vlib_get_frame_to_node (vm, hi->output_node_index);
- u32 *to_next = vlib_frame_vector_args (f);
- to_next[0] = bi;
- f->n_vectors = 1;
- vlib_put_frame_to_node (vm, hi->output_node_index, f);
- }
-
- adj_unlock (ai);
- return /* no error */ 0;
-}
#endif
typedef enum
0);
}
}
- else
- {
- p0->flags &= ~VNET_BUFFER_F_LOCALLY_ORIGINATED;
- }
+
is_locally_originated1 =
p1->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED;
if (PREDICT_TRUE (!is_locally_originated1))
0);
}
}
- else
- {
- p1->flags &= ~VNET_BUFFER_F_LOCALLY_ORIGINATED;
- }
+
adj0 = adj_get (adj_index0);
adj1 = adj_get (adj_index1);
if (PREDICT_FALSE
(adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
- vnet_feature_arc_start (lm->output_feature_arc_index,
- tx_sw_if_index0, &next0, p0);
+ vnet_feature_arc_start_w_cfg_index
+ (lm->output_feature_arc_index, tx_sw_if_index0, &next0, p0,
+ adj0->ia_cfg_index);
}
else
{
if (PREDICT_FALSE
(adj1[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
- vnet_feature_arc_start (lm->output_feature_arc_index,
- tx_sw_if_index1, &next1, p1);
+ vnet_feature_arc_start_w_cfg_index
+ (lm->output_feature_arc_index, tx_sw_if_index1, &next1, p1,
+ adj1->ia_cfg_index);
}
else
{
{
/* before we paint on the next header, update the L4
* checksums if required, since there's no offload on a tunnel */
- calc_checksums (vm, p0);
- calc_checksums (vm, p1);
+ vnet_calc_checksums_inline (vm, p0, 0 /* is_ip4 */ ,
+ 1 /* is_ip6 */ );
+ vnet_calc_checksums_inline (vm, p1, 0 /* is_ip4 */ ,
+ 1 /* is_ip6 */ );
+
+ /* 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 simple Ethernet header. */
- vnet_rewrite_two_headers (adj0[0], adj1[0],
- ip0, ip1, sizeof (ethernet_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 (is_midchain)
{
0);
}
}
- else
- {
- p0->flags &= ~VNET_BUFFER_F_LOCALLY_ORIGINATED;
- }
if (is_midchain)
{
- calc_checksums (vm, p0);
- }
+ vnet_calc_checksums_inline (vm, p0, 0 /* is_ip4 */ ,
+ 1 /* is_ip6 */ );
- /* Guess we are only writing on simple Ethernet header. */
- vnet_rewrite_one_header (adj0[0], ip0, sizeof (ethernet_header_t));
+ /* 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;
if (PREDICT_FALSE
(adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
- vnet_feature_arc_start (lm->output_feature_arc_index,
- tx_sw_if_index0, &next0, p0);
+ vnet_feature_arc_start_w_cfg_index
+ (lm->output_feature_arc_index, tx_sw_if_index0, &next0, p0,
+ adj0->ia_cfg_index);
}
else
{
ip_lookup_init (&im->lookup_main, /* is_ip6 */ 1);
- if (im->lookup_table_nbuckets == 0)
- im->lookup_table_nbuckets = IP6_FIB_DEFAULT_HASH_NUM_BUCKETS;
-
- im->lookup_table_nbuckets = 1 << max_log2 (im->lookup_table_nbuckets);
-
- if (im->lookup_table_size == 0)
- im->lookup_table_size = IP6_FIB_DEFAULT_HASH_MEMORY_SIZE;
-
- clib_bihash_init_24_8 (&(im->ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash),
- "ip6 FIB fwding table",
- im->lookup_table_nbuckets, im->lookup_table_size);
- clib_bihash_init_24_8 (&im->ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash,
- "ip6 FIB non-fwding table",
- im->lookup_table_nbuckets, im->lookup_table_size);
- clib_bihash_init_40_8 (&im->ip6_mtable.ip6_mhash,
- "ip6 mFIB table",
- im->lookup_table_nbuckets, im->lookup_table_size);
-
/* Create FIB with index 0 and table id of 0. */
fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0,
FIB_SOURCE_DEFAULT_ROUTE);
/* Unless explicitly configured, don't process HBH options */
im->hbh_enabled = 0;
- {
- icmp6_neighbor_solicitation_header_t p;
-
- clib_memset (&p, 0, sizeof (p));
-
- p.ip.ip_version_traffic_class_and_flow_label =
- clib_host_to_net_u32 (0x6 << 28);
- p.ip.payload_length =
- clib_host_to_net_u16 (sizeof (p) -
- STRUCT_OFFSET_OF
- (icmp6_neighbor_solicitation_header_t, neighbor));
- p.ip.protocol = IP_PROTOCOL_ICMP6;
- p.ip.hop_limit = 255;
- ip6_set_solicited_node_multicast_address (&p.ip.dst_address, 0);
-
- p.neighbor.icmp.type = ICMP6_neighbor_solicitation;
-
- p.link_layer_option.header.type =
- ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address;
- p.link_layer_option.header.n_data_u64s =
- sizeof (p.link_layer_option) / sizeof (u64);
-
- vlib_packet_template_init (vm,
- &im->discover_neighbor_packet_template,
- &p, sizeof (p),
- /* alloc chunk size */ 8,
- "ip6 neighbor discovery");
- }
-
return error;
}
VLIB_INIT_FUNCTION (ip6_lookup_init);
-static clib_error_t *
-test_ip6_link_command_fn (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- u8 mac[6];
- ip6_address_t _a, *a = &_a;
-
- if (unformat (input, "%U", unformat_ethernet_address, mac))
- {
- ip6_link_local_address_from_ethernet_mac_address (a, mac);
- vlib_cli_output (vm, "Link local address: %U", format_ip6_address, a);
- ip6_ethernet_mac_address_from_link_local_address (mac, a);
- vlib_cli_output (vm, "Original MAC address: %U",
- format_ethernet_address, mac);
- }
-
- return 0;
-}
-
-/*?
- * This command converts the given MAC Address into an IPv6 link-local
- * address.
- *
- * @cliexpar
- * Example of how to create an IPv6 link-local address:
- * @cliexstart{test ip6 link 16:d9:e0:91:79:86}
- * Link local address: fe80::14d9:e0ff:fe91:7986
- * Original MAC address: 16:d9:e0:91:79:86
- * @cliexend
-?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (test_link_command, static) =
-{
- .path = "test ip6 link",
- .function = test_ip6_link_command_fn,
- .short_help = "test ip6 link <mac-address>",
-};
-/* *INDENT-ON* */
-
#ifndef CLIB_MARCH_VARIANT
int
vnet_set_ip6_flow_hash (u32 table_id, u32 flow_hash_config)
};
/* *INDENT-ON* */
-static clib_error_t *
-ip6_config (vlib_main_t * vm, unformat_input_t * input)
-{
- ip6_main_t *im = &ip6_main;
- uword heapsize = 0;
- u32 tmp;
- u32 nbuckets = 0;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "hash-buckets %d", &tmp))
- nbuckets = tmp;
- else if (unformat (input, "heap-size %U",
- unformat_memory_size, &heapsize))
- ;
- else
- return clib_error_return (0, "unknown input '%U'",
- format_unformat_error, input);
- }
-
- im->lookup_table_nbuckets = nbuckets;
- im->lookup_table_size = heapsize;
-
- return 0;
-}
-
-VLIB_EARLY_CONFIG_FUNCTION (ip6_config, "ip6");
-
/*
* fd.io coding-style-patch-verification: ON
*