ip6_frag_hdr_t *frag;
u32 frag_id;
int rv;
+ ip4_address_t old_src, old_dst;
ip4 = vlib_buffer_get_current (p);
checksum = &tcp->checksum;
}
- csum = ip_csum_sub_even (*checksum, ip4->src_address.as_u32);
- csum = ip_csum_sub_even (csum, ip4->dst_address.as_u32);
- *checksum = ip_csum_fold (csum);
+ old_src.as_u32 = ip4->src_address.as_u32;
+ old_dst.as_u32 = ip4->dst_address.as_u32;
// Deal with fragmented packets
if (PREDICT_FALSE (ip4->flags_and_fragment_offset &
if ((rv = fn (ip4, ip6, ctx)) != 0)
return rv;
- csum = ip_csum_add_even (*checksum, ip6->src_address.as_u64[0]);
+ csum = ip_csum_sub_even (*checksum, old_src.as_u32);
+ csum = ip_csum_sub_even (csum, old_dst.as_u32);
+ csum = ip_csum_add_even (csum, ip6->src_address.as_u64[0]);
csum = ip_csum_add_even (csum, ip6->src_address.as_u64[1]);
csum = ip_csum_add_even (csum, ip6->dst_address.as_u64[0]);
csum = ip_csum_add_even (csum, ip6->dst_address.as_u64[1]);
return 0;
}
-#endif /* __included_ip4_to_ip6_h__ */
-
-/*
- * fd.io coding-style-patch-verification: ON
+/**
+ * @brief Translate IPv4 packet to IPv6 (IP header only).
+ *
+ * @param p Buffer to translate.
+ * @param fn The function to translate header.
+ * @param ctx A context passed in the header translate function.
*
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
+ * @returns 0 on success, non-zero value otherwise.
*/
+always_inline int
+ip4_to_ip6 (vlib_buffer_t * p, ip4_to_ip6_set_fn_t fn, void *ctx)
+{
+ ip4_header_t *ip4;
+ ip6_header_t *ip6;
+ ip6_frag_hdr_t *frag;
+ u32 frag_id;
+ int rv;
+
+ ip4 = vlib_buffer_get_current (p);
+
+ // Deal with fragmented packets
+ if (PREDICT_FALSE (ip4->flags_and_fragment_offset &
+ clib_host_to_net_u16 (IP4_HEADER_FLAG_MORE_FRAGMENTS)))
+ {
+ ip6 =
+ (ip6_header_t *) u8_ptr_add (ip4,
+ sizeof (*ip4) - sizeof (*ip6) -
+ sizeof (*frag));
+ frag =
+ (ip6_frag_hdr_t *) u8_ptr_add (ip4, sizeof (*ip4) - sizeof (*frag));
+ frag_id = frag_id_4to6 (ip4->fragment_id);
+ vlib_buffer_advance (p, sizeof (*ip4) - sizeof (*ip6) - sizeof (*frag));
+ }
+ else
+ {
+ ip6 = (ip6_header_t *) (((u8 *) ip4) + sizeof (*ip4) - sizeof (*ip6));
+ vlib_buffer_advance (p, sizeof (*ip4) - sizeof (*ip6));
+ frag = NULL;
+ }
+
+ ip6->ip_version_traffic_class_and_flow_label =
+ clib_host_to_net_u32 ((6 << 28) + (ip4->tos << 20));
+ ip6->payload_length = u16_net_add (ip4->length, -sizeof (*ip4));
+ ip6->hop_limit = ip4->ttl;
+ ip6->protocol = ip4->protocol;
+
+ if (PREDICT_FALSE (frag != NULL))
+ {
+ frag->next_hdr = ip6->protocol;
+ frag->identification = frag_id;
+ frag->rsv = 0;
+ frag->fragment_offset_and_more = ip6_frag_hdr_offset_and_more (0, 1);
+ ip6->protocol = IP_PROTOCOL_IPV6_FRAGMENTATION;
+ ip6->payload_length = u16_net_add (ip6->payload_length, sizeof (*frag));
+ }
+
+ if ((rv = fn (ip4, ip6, ctx)) != 0)
+ return rv;
+
+ return 0;
+}
+
+#endif /* __included_ip4_to_ip6_h__ */