+always_inline bool
+ip6_reass_verify_upper_layer_present (vlib_node_runtime_t * node,
+ vlib_buffer_t * b,
+ ip6_frag_hdr_t * frag_hdr)
+{
+ ip6_ext_header_t *tmp = (ip6_ext_header_t *) frag_hdr;
+ while (ip6_ext_hdr (tmp->next_hdr))
+ {
+ tmp = ip6_ext_next_header (tmp);
+ }
+ if (IP_PROTOCOL_IP6_NONXT == tmp->next_hdr)
+ {
+ icmp6_error_set_vnet_buffer (b, ICMP6_parameter_problem,
+ ICMP6_parameter_problem_first_fragment_has_incomplete_header_chain,
+ 0);
+ b->error = node->errors[IP6_ERROR_REASS_MISSING_UPPER];
+
+ return false;
+ }
+ return true;
+}
+
+always_inline bool
+ip6_reass_verify_fragment_multiple_8 (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_buffer_t * b,
+ ip6_frag_hdr_t * frag_hdr)
+{
+ vnet_buffer_opaque_t *vnb = vnet_buffer (b);
+ ip6_header_t *ip = vlib_buffer_get_current (b);
+ int more_fragments = ip6_frag_hdr_more (frag_hdr);
+ u32 fragment_length =
+ vlib_buffer_length_in_chain (vm, b) -
+ (vnb->ip.reass.ip6_frag_hdr_offset + sizeof (*frag_hdr));
+ if (more_fragments && 0 != fragment_length % 8)
+ {
+ icmp6_error_set_vnet_buffer (b, ICMP6_parameter_problem,
+ ICMP6_parameter_problem_erroneous_header_field,
+ (u8 *) & ip->payload_length - (u8 *) ip);
+ return false;
+ }
+ return true;
+}
+
+always_inline bool
+ip6_reass_verify_packet_size_lt_64k (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_buffer_t * b,
+ ip6_frag_hdr_t * frag_hdr)
+{
+ vnet_buffer_opaque_t *vnb = vnet_buffer (b);
+ u32 fragment_first = ip6_frag_hdr_offset_bytes (frag_hdr);
+ u32 fragment_length =
+ vlib_buffer_length_in_chain (vm, b) -
+ (vnb->ip.reass.ip6_frag_hdr_offset + sizeof (*frag_hdr));
+ if (fragment_first + fragment_length > 65535)
+ {
+ ip6_header_t *ip0 = vlib_buffer_get_current (b);
+ icmp6_error_set_vnet_buffer (b, ICMP6_parameter_problem,
+ ICMP6_parameter_problem_erroneous_header_field,
+ (u8 *) & frag_hdr->fragment_offset_and_more
+ - (u8 *) ip0);
+ return false;
+ }
+ return true;
+}
+