#include <vnet/vnet.h>
#include <vnet/ip/ip.h>
+#include <vnet/ip/ip_frag.h>
#include <vnet/ip/ip6_neighbor.h>
#include <vnet/ethernet/ethernet.h> /* for ethernet_header_t */
#include <vnet/srp/srp.h> /* for srp_hw_interface_class */
clib_error_t *error;
u32 if_address_index;
ip6_address_fib_t ip6_af, *addr_fib = 0;
+ ip6_address_t ll_addr;
/* local0 interface doesn't support IP addressing */
if (sw_if_index == 0)
clib_error_create ("local0 interface doesn't support IP addressing");
}
+ if (ip6_address_is_link_local_unicast (address))
+ {
+ if (address_length != 128)
+ {
+ vnm->api_errno = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
+ return
+ clib_error_create
+ ("prefix length of link-local address must be 128");
+ }
+ if (!is_del)
+ {
+ return ip6_neighbor_set_link_local_address (vm, sw_if_index,
+ address);
+ }
+ else
+ {
+ ll_addr = ip6_neighbor_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");
+ }
+ else
+ {
+ vnm->api_errno = VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE;
+ return clib_error_create ("address not found");
+ }
+ }
+ }
+
vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
vec_validate (im->mfib_index_by_sw_if_index, sw_if_index);
{
.arc_name = "ip6-unicast",
.node_name = "ip6-policer-classify",
- .runs_before = VNET_FEATURES ("ipsec-input-ip6"),
+ .runs_before = VNET_FEATURES ("ipsec6-input"),
};
VNET_FEATURE_INIT (ip6_ipsec, static) =
{
.arc_name = "ip6-unicast",
- .node_name = "ipsec-input-ip6",
+ .node_name = "ipsec6-input",
.runs_before = VNET_FEATURES ("l2tp-decap"),
};
VNET_FEATURE_INIT (ip6_outacl, static) = {
.arc_name = "ip6-output",
.node_name = "ip6-outacl",
- .runs_before = VNET_FEATURES ("ipsec-output-ip6"),
+ .runs_before = VNET_FEATURES ("ipsec6-output"),
};
VNET_FEATURE_INIT (ip6_ipsec_output, static) = {
.arc_name = "ip6-output",
- .node_name = "ipsec-output-ip6",
+ .node_name = "ipsec6-output",
.runs_before = VNET_FEATURES ("interface-output"),
};
VLIB_NODE_FUNCTION_MULTIARCH (ip6_lookup_node, ip6_lookup);
-always_inline uword
+static uword
ip6_load_balance (vlib_main_t * vm,
vlib_node_runtime_t * node, vlib_frame_t * frame)
{
vlib_combined_counter_main_t *cm = &load_balance_main.lbm_via_counters;
u32 n_left_from, n_left_to_next, *from, *to_next;
ip_lookup_next_t next;
- u32 thread_index = vlib_get_thread_index ();
+ u32 thread_index = vm->thread_index;
ip6_main_t *im = &ip6_main;
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
next = node->cached_next_index;
- if (node->flags & VLIB_NODE_FLAG_TRACE)
- ip6_forward_next_trace (vm, node, frame, VLIB_TX);
-
while (n_left_from > 0)
{
vlib_get_next_frame (vm, node, next, to_next, n_left_to_next);
vlib_put_next_frame (vm, node, next, n_left_to_next);
}
+ if (node->flags & VLIB_NODE_FLAG_TRACE)
+ ip6_forward_next_trace (vm, node, frame, VLIB_TX);
+
return frame->n_vectors;
}
? IP6_ERROR_SRC_LOOKUP_MISS : error1);
}
- /* TODO maybe move to lookup? */
- vnet_buffer (p0)->ip.fib_index =
- vec_elt (im->fib_index_by_sw_if_index,
- vnet_buffer (p0)->sw_if_index[VLIB_RX]);
vnet_buffer (p0)->ip.fib_index =
- (vnet_buffer (p0)->sw_if_index[VLIB_TX] ==
- (u32) ~ 0) ? vnet_buffer (p0)->ip.
- fib_index : vnet_buffer (p0)->sw_if_index[VLIB_TX];
+ vnet_buffer (p0)->sw_if_index[VLIB_TX] != ~0 ?
+ vnet_buffer (p0)->sw_if_index[VLIB_TX] :
+ vnet_buffer (p0)->ip.fib_index;
vnet_buffer (p1)->ip.fib_index =
- vec_elt (im->fib_index_by_sw_if_index,
- vnet_buffer (p1)->sw_if_index[VLIB_RX]);
- vnet_buffer (p1)->ip.fib_index =
- (vnet_buffer (p1)->sw_if_index[VLIB_TX] ==
- (u32) ~ 0) ? vnet_buffer (p1)->ip.
- fib_index : vnet_buffer (p1)->sw_if_index[VLIB_TX];
-
+ vnet_buffer (p1)->sw_if_index[VLIB_TX] != ~0 ?
+ vnet_buffer (p1)->sw_if_index[VLIB_TX] :
+ vnet_buffer (p1)->ip.fib_index;
skip_checks:
}
vnet_buffer (p0)->ip.fib_index =
- vec_elt (im->fib_index_by_sw_if_index,
- vnet_buffer (p0)->sw_if_index[VLIB_RX]);
- vnet_buffer (p0)->ip.fib_index =
- (vnet_buffer (p0)->sw_if_index[VLIB_TX] ==
- (u32) ~ 0) ? vnet_buffer (p0)->ip.
- fib_index : vnet_buffer (p0)->sw_if_index[VLIB_TX];
+ vnet_buffer (p0)->sw_if_index[VLIB_TX] != ~0 ?
+ vnet_buffer (p0)->sw_if_index[VLIB_TX] :
+ vnet_buffer (p0)->ip.fib_index;
skip_check:
[IP_LOCAL_NEXT_PUNT] = "ip6-punt",
[IP_LOCAL_NEXT_UDP_LOOKUP] = "ip6-udp-lookup",
[IP_LOCAL_NEXT_ICMP] = "ip6-icmp-input",
+ [IP_LOCAL_NEXT_REASSEMBLY] = "ip6-reassembly",
},
};
/* *INDENT-ON* */
}
clib_error_t *
-ip6_probe_neighbor (vlib_main_t * vm, ip6_address_t * dst, u32 sw_if_index)
+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;
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);
adj = adj_get (ai);
/* Peer has been previously resolved, retrieve glean adj instead */
- if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE)
+ if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE && refresh == 0)
{
adj_unlock (ai);
ai = adj_glean_add_or_lock (FIB_PROTOCOL_IP6,
{
IP6_REWRITE_NEXT_DROP,
IP6_REWRITE_NEXT_ICMP_ERROR,
+ IP6_REWRITE_NEXT_FRAGMENT,
+ IP6_REWRITE_N_NEXT /* Last */
} ip6_rewrite_next_t;
/**
*/
#define IP6_MCAST_ADDR_MASK 0xffffffff
+always_inline void
+ip6_mtu_check (vlib_buffer_t * b, u16 packet_bytes,
+ u16 adj_packet_bytes, bool is_locally_generated,
+ u32 * next, u32 * error)
+{
+ if (adj_packet_bytes >= 1280 && packet_bytes > adj_packet_bytes)
+ {
+ if (is_locally_generated)
+ {
+ /* IP fragmentation */
+ ip_frag_set_vnet_buffer (b, adj_packet_bytes,
+ IP6_FRAG_NEXT_IP6_REWRITE, 0);
+ *next = IP6_REWRITE_NEXT_FRAGMENT;
+ *error = IP6_ERROR_MTU_EXCEEDED;
+ }
+ else
+ {
+ *error = IP6_ERROR_MTU_EXCEEDED;
+ icmp6_error_set_vnet_buffer (b, ICMP6_packet_too_big, 0,
+ adj_packet_bytes);
+ *next = IP6_REWRITE_NEXT_ICMP_ERROR;
+ }
+ }
+}
+
always_inline uword
ip6_rewrite_inline (vlib_main_t * vm,
vlib_node_runtime_t * node,
n_left_from = frame->n_vectors;
next_index = node->cached_next_index;
- u32 thread_index = vlib_get_thread_index ();
+ u32 thread_index = vm->thread_index;
while (n_left_from > 0)
{
u32 pi0, rw_len0, next0, error0, adj_index0;
u32 pi1, rw_len1, next1, error1, adj_index1;
u32 tx_sw_if_index0, tx_sw_if_index1;
+ bool is_locally_originated0, is_locally_originated1;
/* Prefetch next iteration. */
{
error0 = error1 = IP6_ERROR_NONE;
next0 = next1 = IP6_REWRITE_NEXT_DROP;
- if (PREDICT_TRUE (!(p0->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED)))
+ is_locally_originated0 =
+ p0->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED;
+ if (PREDICT_TRUE (!is_locally_originated0))
{
i32 hop_limit0 = ip0->hop_limit;
{
p0->flags &= ~VNET_BUFFER_F_LOCALLY_ORIGINATED;
}
- if (PREDICT_TRUE (!(p1->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED)))
+ is_locally_originated1 =
+ p1->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED;
+ if (PREDICT_TRUE (!is_locally_originated1))
{
i32 hop_limit1 = ip1->hop_limit;
}
/* Check MTU of outgoing interface. */
- error0 =
- (vlib_buffer_length_in_chain (vm, p0) >
- adj0[0].
- rewrite_header.max_l3_packet_bytes ? IP6_ERROR_MTU_EXCEEDED :
- error0);
- error1 =
- (vlib_buffer_length_in_chain (vm, p1) >
- adj1[0].
- rewrite_header.max_l3_packet_bytes ? IP6_ERROR_MTU_EXCEEDED :
- error1);
+ ip6_mtu_check (p0, clib_net_to_host_u16 (ip0->payload_length) +
+ sizeof (ip6_header_t),
+ adj0[0].rewrite_header.max_l3_packet_bytes,
+ is_locally_originated0, &next0, &error0);
+ ip6_mtu_check (p1, clib_net_to_host_u16 (ip1->payload_length) +
+ sizeof (ip6_header_t),
+ adj1[0].rewrite_header.max_l3_packet_bytes,
+ is_locally_originated1, &next1, &error1);
/* Don't adjust the buffer for hop count issue; icmp-error node
* wants to see the IP headerr */
u32 pi0, rw_len0;
u32 adj_index0, next0, error0;
u32 tx_sw_if_index0;
+ bool is_locally_originated0;
pi0 = to_next[0] = from[0];
next0 = IP6_REWRITE_NEXT_DROP;
/* Check hop limit */
- if (PREDICT_TRUE (!(p0->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED)))
+ is_locally_originated0 =
+ p0->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED;
+ if (PREDICT_TRUE (!is_locally_originated0))
{
i32 hop_limit0 = ip0->hop_limit;
}
/* Check MTU of outgoing interface. */
- error0 =
- (vlib_buffer_length_in_chain (vm, p0) >
- adj0[0].
- rewrite_header.max_l3_packet_bytes ? IP6_ERROR_MTU_EXCEEDED :
- error0);
+ ip6_mtu_check (p0, clib_net_to_host_u16 (ip0->payload_length) +
+ sizeof (ip6_header_t),
+ adj0[0].rewrite_header.max_l3_packet_bytes,
+ is_locally_originated0, &next0, &error0);
/* Don't adjust the buffer for hop count issue; icmp-error node
- * wants to see the IP headerr */
+ * wants to see the IP header */
if (PREDICT_TRUE (error0 == IP6_ERROR_NONE))
{
p0->current_data -= rw_len0;
return ip6_rewrite_inline (vm, node, frame, 0, 0, 0);
}
+static uword
+ip6_rewrite_bcast (vlib_main_t * vm,
+ vlib_node_runtime_t * node, vlib_frame_t * frame)
+{
+ if (adj_are_counters_enabled ())
+ return ip6_rewrite_inline (vm, node, frame, 1, 0, 0);
+ else
+ return ip6_rewrite_inline (vm, node, frame, 0, 0, 0);
+}
+
static uword
ip6_rewrite_mcast (vlib_main_t * vm,
vlib_node_runtime_t * node, vlib_frame_t * frame)
.format_trace = format_ip6_forward_next_trace,
.sibling_of = "ip6-rewrite",
};
-/* *INDENT-ON* */
VLIB_NODE_FUNCTION_MULTIARCH (ip6_midchain_node, ip6_midchain);
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ip6_rewrite_node) =
{
.function = ip6_rewrite,
.name = "ip6-rewrite",
.vector_size = sizeof (u32),
.format_trace = format_ip6_rewrite_trace,
- .n_next_nodes = 2,
+ .n_next_nodes = IP6_REWRITE_N_NEXT,
.next_nodes =
{
[IP6_REWRITE_NEXT_DROP] = "ip6-drop",
[IP6_REWRITE_NEXT_ICMP_ERROR] = "ip6-icmp-error",
+ [IP6_REWRITE_NEXT_FRAGMENT] = "ip6-frag",
},
};
-/* *INDENT-ON* */
VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_node, ip6_rewrite);
-/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (ip6_rewrite_bcast_node) = {
+ .function = ip6_rewrite_bcast,
+ .name = "ip6-rewrite-bcast",
+ .vector_size = sizeof (u32),
+
+ .format_trace = format_ip6_rewrite_trace,
+ .sibling_of = "ip6-rewrite",
+};
+VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_bcast_node, ip6_rewrite_bcast)
+
VLIB_REGISTER_NODE (ip6_rewrite_mcast_node) =
{
.function = ip6_rewrite_mcast,
.format_trace = format_ip6_rewrite_trace,
.sibling_of = "ip6-rewrite",
};
-/* *INDENT-ON* */
VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_mcast_node, ip6_rewrite_mcast);
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ip6_mcast_midchain_node, static) =
{
.function = ip6_mcast_midchain,
.format_trace = format_ip6_rewrite_trace,
.sibling_of = "ip6-rewrite",
};
-/* *INDENT-ON* */
VLIB_NODE_FUNCTION_MULTIARCH (ip6_mcast_midchain_node, ip6_mcast_midchain);
+/* *INDENT-ON* */
/*
* Hop-by-Hop handling
ip6_hop_by_hop_init (vlib_main_t * vm)
{
ip6_hop_by_hop_main_t *hm = &ip6_hop_by_hop_main;
- memset (hm->options, 0, sizeof (hm->options));
- memset (hm->trace, 0, sizeof (hm->trace));
+ clib_memset (hm->options, 0, sizeof (hm->options));
+ clib_memset (hm->trace, 0, sizeof (hm->trace));
hm->next_override = IP6_LOOKUP_NEXT_POP_HOP_BY_HOP;
return (0);
}
{
icmp6_neighbor_solicitation_header_t p;
- memset (&p, 0, sizeof (p));
+ clib_memset (&p, 0, sizeof (p));
p.ip.ip_version_traffic_class_and_flow_label =
clib_host_to_net_u32 (0x6 << 28);