};
/* *INDENT-ON* */
+static_always_inline u8
+ip6_tcp_udp_icmp_bad_length (vlib_main_t * vm, vlib_buffer_t * p0)
+{
+
+ u16 payload_length_host_byte_order;
+ u32 n_this_buffer, n_bytes_left;
+ ip6_header_t *ip0 = vlib_buffer_get_current (p0);
+ u32 headers_size = sizeof (ip0[0]);
+ u8 *data_this_buffer;
+
+
+ data_this_buffer = (u8 *) (ip0 + 1);
+
+ ip6_hop_by_hop_ext_t *ext_hdr = (ip6_hop_by_hop_ext_t *) data_this_buffer;
+
+ /* validate really icmp6 next */
+
+ if (!(ext_hdr->next_hdr == IP_PROTOCOL_ICMP6)
+ || (ext_hdr->next_hdr == IP_PROTOCOL_UDP))
+ return 0;
+
+
+ payload_length_host_byte_order = clib_net_to_host_u16 (ip0->payload_length);
+ n_bytes_left = n_this_buffer = payload_length_host_byte_order;
+
+
+ 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_bytes_left -= n_this_buffer;
+ n_bytes_left -= p0->total_length_not_including_first_buffer;
+
+ if (n_bytes_left == 0)
+ return 0;
+ else
+ return 1;
+}
+
+
always_inline uword
ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
vlib_frame_t * frame, int head_of_feature_arc)
{
flags[0] = ip6_tcp_udp_icmp_validate_checksum (vm, b[0]);
good_l4_csum[0] = flags[0] & VNET_BUFFER_F_L4_CHECKSUM_CORRECT;
+ error[0] = IP6_ERROR_UNKNOWN_PROTOCOL;
+ }
+ else
+ {
+ if (ip6_tcp_udp_icmp_bad_length (vm, b[0]))
+ error[0] = IP6_ERROR_BAD_LENGTH;
}
if (PREDICT_FALSE (need_csum[1]))
{
flags[1] = ip6_tcp_udp_icmp_validate_checksum (vm, b[1]);
good_l4_csum[1] = flags[1] & VNET_BUFFER_F_L4_CHECKSUM_CORRECT;
+ error[1] = IP6_ERROR_UNKNOWN_PROTOCOL;
+ }
+ else
+ {
+ if (ip6_tcp_udp_icmp_bad_length (vm, b[1]))
+ error[1] = IP6_ERROR_BAD_LENGTH;
}
- error[0] = IP6_ERROR_UNKNOWN_PROTOCOL;
+
error[0] = len_diff[0] < 0 ? IP6_ERROR_UDP_LENGTH : error[0];
- error[1] = IP6_ERROR_UNKNOWN_PROTOCOL;
+
error[1] = len_diff[1] < 0 ? IP6_ERROR_UDP_LENGTH : error[1];
STATIC_ASSERT (IP6_ERROR_UDP_CHECKSUM + IP_BUILTIN_PROTOCOL_UDP ==
{
flags = ip6_tcp_udp_icmp_validate_checksum (vm, b[0]);
good_l4_csum = flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT;
+ error = IP6_ERROR_UNKNOWN_PROTOCOL;
+ }
+ else
+ {
+ if (ip6_tcp_udp_icmp_bad_length (vm, b[0]))
+ error = IP6_ERROR_BAD_LENGTH;
}
- error = IP6_ERROR_UNKNOWN_PROTOCOL;
+
+
error = len_diff < 0 ? IP6_ERROR_UDP_LENGTH : error;
STATIC_ASSERT (IP6_ERROR_UDP_CHECKSUM + IP_BUILTIN_PROTOCOL_UDP ==
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)
+ u32 * next, u8 is_midchain, u32 * error)
{
if (adj_packet_bytes >= 1280 && packet_bytes > adj_packet_bytes)
{
{
/* IP fragmentation */
ip_frag_set_vnet_buffer (b, adj_packet_bytes,
- IP6_FRAG_NEXT_IP6_REWRITE, 0);
+ (is_midchain ?
+ IP_FRAG_NEXT_IP_REWRITE_MIDCHAIN :
+ IP_FRAG_NEXT_IP_REWRITE), 0);
*next = IP6_REWRITE_NEXT_FRAGMENT;
*error = IP6_ERROR_MTU_EXCEEDED;
}
ip6_rewrite_inline_with_gso (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * frame,
- int do_counters, int is_midchain, int is_mcast,
- int do_gso)
+ int do_counters, int is_midchain, int is_mcast)
{
ip_lookup_main_t *lm = &ip6_main.lookup_main;
u32 *from = vlib_frame_vector_args (frame);
while (n_left_from >= 4 && n_left_to_next >= 2)
{
- ip_adjacency_t *adj0, *adj1;
+ const ip_adjacency_t *adj0, *adj1;
vlib_buffer_t *p0, *p1;
ip6_header_t *ip0, *ip1;
u32 pi0, rw_len0, next0, error0, adj_index0;
u16 ip1_len =
clib_net_to_host_u16 (ip1->payload_length) +
sizeof (ip6_header_t);
- if (do_gso && (p0->flags & VNET_BUFFER_F_GSO))
+ if (p0->flags & VNET_BUFFER_F_GSO)
ip0_len = gso_mtu_sz (p0);
- if (do_gso && (p1->flags & VNET_BUFFER_F_GSO))
+ if (p1->flags & VNET_BUFFER_F_GSO)
ip1_len = gso_mtu_sz (p1);
ip6_mtu_check (p0, ip0_len,
adj0[0].rewrite_header.max_l3_packet_bytes,
- is_locally_originated0, &next0, &error0);
+ is_locally_originated0, &next0, is_midchain,
+ &error0);
ip6_mtu_check (p1, ip1_len,
adj1[0].rewrite_header.max_l3_packet_bytes,
- is_locally_originated1, &next1, &error1);
+ is_locally_originated1, &next1, is_midchain,
+ &error1);
/* Don't adjust the buffer for hop count issue; icmp-error node
* wants to see the IP header */
u16 ip0_len =
clib_net_to_host_u16 (ip0->payload_length) +
sizeof (ip6_header_t);
- if (do_gso && (p0->flags & VNET_BUFFER_F_GSO))
+ if (p0->flags & VNET_BUFFER_F_GSO)
ip0_len = gso_mtu_sz (p0);
ip6_mtu_check (p0, ip0_len,
adj0[0].rewrite_header.max_l3_packet_bytes,
- is_locally_originated0, &next0, &error0);
+ is_locally_originated0, &next0, is_midchain,
+ &error0);
/* Don't adjust the buffer for hop count issue; icmp-error node
* wants to see the IP header */
vlib_frame_t * frame,
int do_counters, int is_midchain, int is_mcast)
{
- vnet_main_t *vnm = vnet_get_main ();
- if (PREDICT_FALSE (vnm->interface_main.gso_interface_count > 0))
- return ip6_rewrite_inline_with_gso (vm, node, frame, do_counters,
- is_midchain, is_mcast,
- 1 /* do_gso */ );
- else
- return ip6_rewrite_inline_with_gso (vm, node, frame, do_counters,
- is_midchain, is_mcast,
- 0 /* no do_gso */ );
+ return ip6_rewrite_inline_with_gso (vm, node, frame, do_counters,
+ is_midchain, is_mcast);
}
VLIB_NODE_FN (ip6_rewrite_node) (vlib_main_t * vm,