diff options
-rw-r--r-- | src/plugins/cnat/cnat_node.h | 353 | ||||
-rw-r--r-- | src/plugins/cnat/cnat_node_feature.c | 8 | ||||
-rw-r--r-- | src/plugins/cnat/cnat_node_snat.c | 5 | ||||
-rw-r--r-- | src/plugins/cnat/cnat_node_vip.c | 4 |
4 files changed, 155 insertions, 215 deletions
diff --git a/src/plugins/cnat/cnat_node.h b/src/plugins/cnat/cnat_node.h index c304c5c83e8..75c1b4ac3ab 100644 --- a/src/plugins/cnat/cnat_node.h +++ b/src/plugins/cnat/cnat_node.h @@ -19,6 +19,7 @@ #include <vlibmemory/api.h> #include <vnet/dpo/load_balance.h> #include <vnet/dpo/load_balance_map.h> +#include <vnet/ip/ip_psh_cksum.h> #include <cnat/cnat_session.h> #include <cnat/cnat_client.h> @@ -169,60 +170,46 @@ cmp_ip6_address (const ip6_address_t * a1, const ip6_address_t * a2) * Inline translation functions */ -static_always_inline u8 -has_ip6_address (ip6_address_t * a) +static_always_inline u16 +ip4_pseudo_header_cksum2 (ip4_header_t *ip4, ip4_address_t address[VLIB_N_DIR]) { - return ((0 != a->as_u64[0]) || (0 != a->as_u64[1])); + ip4_psh_t psh = { 0 }; + psh.src = address[VLIB_RX]; + psh.dst = address[VLIB_TX]; + psh.proto = ip4->protocol; + psh.l4len = clib_host_to_net_u16 (clib_net_to_host_u16 (ip4->length) - + sizeof (ip4_header_t)); + return ~(clib_ip_csum ((u8 *) &psh, sizeof (ip4_psh_t))); } static_always_inline void -cnat_ip4_translate_l4 (ip4_header_t * ip4, udp_header_t * udp, - ip_csum_t * sum, +cnat_ip4_translate_l4 (ip4_header_t *ip4, udp_header_t *udp, ip_csum_t *sum, ip4_address_t new_addr[VLIB_N_DIR], - u16 new_port[VLIB_N_DIR]) + u16 new_port[VLIB_N_DIR], u32 oflags) { u16 old_port[VLIB_N_DIR]; - ip4_address_t old_addr[VLIB_N_DIR]; + old_port[VLIB_TX] = udp->dst_port; + old_port[VLIB_RX] = udp->src_port; - /* Fastpath no checksum */ - if (PREDICT_TRUE (0 == *sum)) + udp->dst_port = new_port[VLIB_TX]; + udp->src_port = new_port[VLIB_RX]; + + if (oflags & + (VNET_BUFFER_OFFLOAD_F_TCP_CKSUM | VNET_BUFFER_OFFLOAD_F_UDP_CKSUM)) { - udp->dst_port = new_port[VLIB_TX]; - udp->src_port = new_port[VLIB_RX]; + *sum = ip4_pseudo_header_cksum2 (ip4, new_addr); return; } - old_port[VLIB_TX] = udp->dst_port; - old_port[VLIB_RX] = udp->src_port; - old_addr[VLIB_TX] = ip4->dst_address; - old_addr[VLIB_RX] = ip4->src_address; + *sum = ip_csum_update (*sum, ip4->dst_address.as_u32, + new_addr[VLIB_TX].as_u32, ip4_header_t, dst_address); + *sum = ip_csum_update (*sum, ip4->src_address.as_u32, + new_addr[VLIB_RX].as_u32, ip4_header_t, src_address); - if (new_addr[VLIB_TX].as_u32) - { - *sum = - ip_csum_update (*sum, old_addr[VLIB_TX].as_u32, - new_addr[VLIB_TX].as_u32, ip4_header_t, dst_address); - } - if (new_port[VLIB_TX]) - { - udp->dst_port = new_port[VLIB_TX]; - *sum = ip_csum_update (*sum, old_port[VLIB_TX], new_port[VLIB_TX], - ip4_header_t /* cheat */ , - length /* changed member */ ); - } - if (new_addr[VLIB_RX].as_u32) - { - *sum = - ip_csum_update (*sum, old_addr[VLIB_RX].as_u32, - new_addr[VLIB_RX].as_u32, ip4_header_t, src_address); - } - if (new_port[VLIB_RX]) - { - udp->src_port = new_port[VLIB_RX]; - *sum = ip_csum_update (*sum, old_port[VLIB_RX], new_port[VLIB_RX], - ip4_header_t /* cheat */ , - length /* changed member */ ); - } + *sum = ip_csum_update (*sum, old_port[VLIB_TX], new_port[VLIB_TX], + udp_header_t, dst_port); + *sum = ip_csum_update (*sum, old_port[VLIB_RX], new_port[VLIB_RX], + udp_header_t, src_port); } static_always_inline void @@ -249,29 +236,26 @@ cnat_ip4_translate_sctp (ip4_header_t *ip4, sctp_header_t *sctp, } static_always_inline void -cnat_ip4_translate_l3 (ip4_header_t * ip4, ip4_address_t new_addr[VLIB_N_DIR]) +cnat_ip4_translate_l3 (ip4_header_t *ip4, ip4_address_t new_addr[VLIB_N_DIR], + u32 oflags) { ip4_address_t old_addr[VLIB_N_DIR]; ip_csum_t sum; - old_addr[VLIB_TX] = ip4->dst_address; old_addr[VLIB_RX] = ip4->src_address; + ip4->dst_address = new_addr[VLIB_TX]; + ip4->src_address = new_addr[VLIB_RX]; + + // We always compute the IP checksum even if oflags & + // VNET_BUFFER_OFFLOAD_F_IP_CKSUM is set as this is relatively inexpensive + // and will allow avoiding issues in driver that do not behave properly + // downstream. sum = ip4->checksum; - if (new_addr[VLIB_TX].as_u32) - { - ip4->dst_address = new_addr[VLIB_TX]; - sum = - ip_csum_update (sum, old_addr[VLIB_TX].as_u32, + sum = ip_csum_update (sum, old_addr[VLIB_TX].as_u32, new_addr[VLIB_TX].as_u32, ip4_header_t, dst_address); - } - if (new_addr[VLIB_RX].as_u32) - { - ip4->src_address = new_addr[VLIB_RX]; - sum = - ip_csum_update (sum, old_addr[VLIB_RX].as_u32, + sum = ip_csum_update (sum, old_addr[VLIB_RX].as_u32, new_addr[VLIB_RX].as_u32, ip4_header_t, src_address); - } ip4->checksum = ip_csum_fold (sum); } @@ -280,48 +264,40 @@ cnat_tcp_update_session_lifetime (tcp_header_t * tcp, u32 index) { cnat_main_t *cm = &cnat_main; if (PREDICT_FALSE (tcp_fin (tcp))) - { - cnat_timestamp_set_lifetime (index, CNAT_DEFAULT_TCP_RST_TIMEOUT); - } + cnat_timestamp_set_lifetime (index, CNAT_DEFAULT_TCP_RST_TIMEOUT); if (PREDICT_FALSE (tcp_rst (tcp))) - { - cnat_timestamp_set_lifetime (index, CNAT_DEFAULT_TCP_RST_TIMEOUT); - } + cnat_timestamp_set_lifetime (index, CNAT_DEFAULT_TCP_RST_TIMEOUT); if (PREDICT_FALSE (tcp_syn (tcp) && tcp_ack (tcp))) - { - cnat_timestamp_set_lifetime (index, cm->tcp_max_age); - } + cnat_timestamp_set_lifetime (index, cm->tcp_max_age); } static_always_inline void -cnat_translation_icmp4_echo (ip4_header_t * ip4, icmp46_header_t * icmp, +cnat_translation_icmp4_echo (ip4_header_t *ip4, icmp46_header_t *icmp, ip4_address_t new_addr[VLIB_N_DIR], - u16 new_port[VLIB_N_DIR]) + u16 new_port[VLIB_N_DIR], u32 oflags) { ip_csum_t sum; u16 old_port; cnat_echo_header_t *echo = (cnat_echo_header_t *) (icmp + 1); - cnat_ip4_translate_l3 (ip4, new_addr); + cnat_ip4_translate_l3 (ip4, new_addr, oflags); old_port = echo->identifier; echo->identifier = new_port[VLIB_RX]; sum = icmp->checksum; - sum = ip_csum_update (sum, old_port, new_port[VLIB_RX], - ip4_header_t /* cheat */ , - length /* changed member */ ); + sum = + ip_csum_update (sum, old_port, new_port[VLIB_RX], udp_header_t, src_port); icmp->checksum = ip_csum_fold (sum); } static_always_inline void -cnat_translation_icmp4_error (ip4_header_t * outer_ip4, - icmp46_header_t * icmp, +cnat_translation_icmp4_error (ip4_header_t *outer_ip4, icmp46_header_t *icmp, ip4_address_t outer_new_addr[VLIB_N_DIR], - u16 outer_new_port[VLIB_N_DIR], - u8 snat_outer_ip) + u16 outer_new_port[VLIB_N_DIR], u8 snat_outer_ip, + u32 oflags) { ip4_address_t new_addr[VLIB_N_DIR]; ip4_address_t old_addr[VLIB_N_DIR]; @@ -350,18 +326,20 @@ cnat_translation_icmp4_error (ip4_header_t * outer_ip4, /* translate outer ip. */ if (!snat_outer_ip) outer_new_addr[VLIB_RX] = outer_ip4->src_address; - cnat_ip4_translate_l3 (outer_ip4, outer_new_addr); + cnat_ip4_translate_l3 (outer_ip4, outer_new_addr, oflags); if (ip4->protocol == IP_PROTOCOL_TCP) { inner_l4_old_sum = inner_l4_sum = tcp->checksum; - cnat_ip4_translate_l4 (ip4, udp, &inner_l4_sum, new_addr, new_port); + cnat_ip4_translate_l4 (ip4, udp, &inner_l4_sum, new_addr, new_port, + 0 /* flags */); tcp->checksum = ip_csum_fold (inner_l4_sum); } else if (ip4->protocol == IP_PROTOCOL_UDP) { inner_l4_old_sum = inner_l4_sum = udp->checksum; - cnat_ip4_translate_l4 (ip4, udp, &inner_l4_sum, new_addr, new_port); + cnat_ip4_translate_l4 (ip4, udp, &inner_l4_sum, new_addr, new_port, + 0 /* flags */); udp->checksum = ip_csum_fold (inner_l4_sum); } else @@ -374,37 +352,30 @@ cnat_translation_icmp4_error (ip4_header_t * outer_ip4, /* UDP/TCP Ports changed */ if (old_port[VLIB_TX] && new_port[VLIB_TX]) sum = ip_csum_update (sum, old_port[VLIB_TX], new_port[VLIB_TX], - ip4_header_t /* cheat */ , - length /* changed member */ ); + udp_header_t, dst_port); if (old_port[VLIB_RX] && new_port[VLIB_RX]) sum = ip_csum_update (sum, old_port[VLIB_RX], new_port[VLIB_RX], - ip4_header_t /* cheat */ , - length /* changed member */ ); - + udp_header_t, src_port); - cnat_ip4_translate_l3 (ip4, new_addr); + cnat_ip4_translate_l3 (ip4, new_addr, 0 /* oflags */); ip_csum_t new_ip_sum = ip4->checksum; /* IP checksum changed */ sum = ip_csum_update (sum, old_ip_sum, new_ip_sum, ip4_header_t, checksum); /* IP src/dst addr changed */ - if (new_addr[VLIB_TX].as_u32) - sum = - ip_csum_update (sum, old_addr[VLIB_TX].as_u32, new_addr[VLIB_TX].as_u32, - ip4_header_t, dst_address); + sum = ip_csum_update (sum, old_addr[VLIB_TX].as_u32, + new_addr[VLIB_TX].as_u32, ip4_header_t, dst_address); - if (new_addr[VLIB_RX].as_u32) - sum = - ip_csum_update (sum, old_addr[VLIB_RX].as_u32, new_addr[VLIB_RX].as_u32, - ip4_header_t, src_address); + sum = ip_csum_update (sum, old_addr[VLIB_RX].as_u32, + new_addr[VLIB_RX].as_u32, ip4_header_t, src_address); icmp->checksum = ip_csum_fold (sum); } static_always_inline void -cnat_translation_ip4 (const cnat_session_t * session, - ip4_header_t * ip4, udp_header_t * udp) +cnat_translation_ip4 (const cnat_session_t *session, ip4_header_t *ip4, + udp_header_t *udp, u32 oflags) { tcp_header_t *tcp = (tcp_header_t *) udp; ip4_address_t new_addr[VLIB_N_DIR]; @@ -418,23 +389,23 @@ cnat_translation_ip4 (const cnat_session_t * session, if (ip4->protocol == IP_PROTOCOL_TCP) { ip_csum_t sum = tcp->checksum; - cnat_ip4_translate_l4 (ip4, udp, &sum, new_addr, new_port); + cnat_ip4_translate_l4 (ip4, udp, &sum, new_addr, new_port, oflags); tcp->checksum = ip_csum_fold (sum); - cnat_ip4_translate_l3 (ip4, new_addr); + cnat_ip4_translate_l3 (ip4, new_addr, oflags); cnat_tcp_update_session_lifetime (tcp, session->value.cs_ts_index); } else if (ip4->protocol == IP_PROTOCOL_UDP) { ip_csum_t sum = udp->checksum; - cnat_ip4_translate_l4 (ip4, udp, &sum, new_addr, new_port); + cnat_ip4_translate_l4 (ip4, udp, &sum, new_addr, new_port, oflags); udp->checksum = ip_csum_fold (sum); - cnat_ip4_translate_l3 (ip4, new_addr); + cnat_ip4_translate_l3 (ip4, new_addr, oflags); } else if (ip4->protocol == IP_PROTOCOL_SCTP) { sctp_header_t *sctp = (sctp_header_t *) udp; cnat_ip4_translate_sctp (ip4, sctp, new_port); - cnat_ip4_translate_l3 (ip4, new_addr); + cnat_ip4_translate_l3 (ip4, new_addr, oflags); } else if (ip4->protocol == IP_PROTOCOL_ICMP) { @@ -446,74 +417,65 @@ cnat_translation_ip4 (const cnat_session_t * session, (ip4->src_address.as_u32 == session->key.cs_ip[VLIB_RX].ip4.as_u32); cnat_translation_icmp4_error (ip4, icmp, new_addr, new_port, - snat_outer_ip); + snat_outer_ip, oflags); } else if (icmp_type_is_echo (icmp->type)) - cnat_translation_icmp4_echo (ip4, icmp, new_addr, new_port); + cnat_translation_icmp4_echo (ip4, icmp, new_addr, new_port, oflags); } } static_always_inline void cnat_ip6_translate_l3 (ip6_header_t * ip6, ip6_address_t new_addr[VLIB_N_DIR]) { - if (has_ip6_address (&new_addr[VLIB_TX])) - ip6_address_copy (&ip6->dst_address, &new_addr[VLIB_TX]); - if (has_ip6_address (&new_addr[VLIB_RX])) - ip6_address_copy (&ip6->src_address, &new_addr[VLIB_RX]); + ip6_address_copy (&ip6->dst_address, &new_addr[VLIB_TX]); + ip6_address_copy (&ip6->src_address, &new_addr[VLIB_RX]); +} + +static_always_inline u16 +ip6_pseudo_header_cksum2 (ip6_header_t *ip6, ip6_address_t address[VLIB_N_DIR]) +{ + ip6_psh_t psh = { 0 }; + psh.src = address[VLIB_RX]; + psh.dst = address[VLIB_TX]; + psh.l4len = ip6->payload_length; + psh.proto = clib_host_to_net_u32 ((u32) ip6->protocol); + return ~(clib_ip_csum ((u8 *) &psh, sizeof (ip6_psh_t))); } static_always_inline void -cnat_ip6_translate_l4 (ip6_header_t * ip6, udp_header_t * udp, - ip_csum_t * sum, +cnat_ip6_translate_l4 (ip6_header_t *ip6, udp_header_t *udp, ip_csum_t *sum, ip6_address_t new_addr[VLIB_N_DIR], - u16 new_port[VLIB_N_DIR]) + u16 new_port[VLIB_N_DIR], u32 oflags) { u16 old_port[VLIB_N_DIR]; - ip6_address_t old_addr[VLIB_N_DIR]; + old_port[VLIB_TX] = udp->dst_port; + old_port[VLIB_RX] = udp->src_port; - /* Fastpath no checksum */ - if (PREDICT_TRUE (0 == *sum)) + udp->dst_port = new_port[VLIB_TX]; + udp->src_port = new_port[VLIB_RX]; + + if (oflags & + (VNET_BUFFER_OFFLOAD_F_TCP_CKSUM | VNET_BUFFER_OFFLOAD_F_UDP_CKSUM)) { - udp->dst_port = new_port[VLIB_TX]; - udp->src_port = new_port[VLIB_RX]; + *sum = ip6_pseudo_header_cksum2 (ip6, new_addr); return; } - old_port[VLIB_TX] = udp->dst_port; - old_port[VLIB_RX] = udp->src_port; - ip6_address_copy (&old_addr[VLIB_TX], &ip6->dst_address); - ip6_address_copy (&old_addr[VLIB_RX], &ip6->src_address); + *sum = ip_csum_add_even (*sum, new_addr[VLIB_TX].as_u64[0]); + *sum = ip_csum_add_even (*sum, new_addr[VLIB_TX].as_u64[1]); + *sum = ip_csum_sub_even (*sum, ip6->dst_address.as_u64[0]); + *sum = ip_csum_sub_even (*sum, ip6->dst_address.as_u64[1]); - if (has_ip6_address (&new_addr[VLIB_TX])) - { - *sum = ip_csum_add_even (*sum, new_addr[VLIB_TX].as_u64[0]); - *sum = ip_csum_add_even (*sum, new_addr[VLIB_TX].as_u64[1]); - *sum = ip_csum_sub_even (*sum, old_addr[VLIB_TX].as_u64[0]); - *sum = ip_csum_sub_even (*sum, old_addr[VLIB_TX].as_u64[1]); - } + *sum = ip_csum_add_even (*sum, new_addr[VLIB_RX].as_u64[0]); + *sum = ip_csum_add_even (*sum, new_addr[VLIB_RX].as_u64[1]); + *sum = ip_csum_sub_even (*sum, ip6->src_address.as_u64[0]); + *sum = ip_csum_sub_even (*sum, ip6->src_address.as_u64[1]); - if (new_port[VLIB_TX]) - { - udp->dst_port = new_port[VLIB_TX]; - *sum = ip_csum_update (*sum, old_port[VLIB_TX], new_port[VLIB_TX], - ip4_header_t /* cheat */ , - length /* changed member */ ); - } - if (has_ip6_address (&new_addr[VLIB_RX])) - { - *sum = ip_csum_add_even (*sum, new_addr[VLIB_RX].as_u64[0]); - *sum = ip_csum_add_even (*sum, new_addr[VLIB_RX].as_u64[1]); - *sum = ip_csum_sub_even (*sum, old_addr[VLIB_RX].as_u64[0]); - *sum = ip_csum_sub_even (*sum, old_addr[VLIB_RX].as_u64[1]); - } + *sum = ip_csum_update (*sum, old_port[VLIB_TX], new_port[VLIB_TX], + udp_header_t, dst_port); - if (new_port[VLIB_RX]) - { - udp->src_port = new_port[VLIB_RX]; - *sum = ip_csum_update (*sum, old_port[VLIB_RX], new_port[VLIB_RX], - ip4_header_t /* cheat */ , - length /* changed member */ ); - } + *sum = ip_csum_update (*sum, old_port[VLIB_RX], new_port[VLIB_RX], + udp_header_t, src_port); } static_always_inline void @@ -532,26 +494,20 @@ cnat_translation_icmp6_echo (ip6_header_t * ip6, icmp46_header_t * icmp, sum = icmp->checksum; cnat_ip6_translate_l3 (ip6, new_addr); - if (has_ip6_address (&new_addr[VLIB_TX])) - { - sum = ip_csum_add_even (sum, new_addr[VLIB_TX].as_u64[0]); - sum = ip_csum_add_even (sum, new_addr[VLIB_TX].as_u64[1]); - sum = ip_csum_sub_even (sum, old_addr[VLIB_TX].as_u64[0]); - sum = ip_csum_sub_even (sum, old_addr[VLIB_TX].as_u64[1]); - } - if (has_ip6_address (&new_addr[VLIB_RX])) - { - sum = ip_csum_add_even (sum, new_addr[VLIB_RX].as_u64[0]); - sum = ip_csum_add_even (sum, new_addr[VLIB_RX].as_u64[1]); - sum = ip_csum_sub_even (sum, old_addr[VLIB_RX].as_u64[0]); - sum = ip_csum_sub_even (sum, old_addr[VLIB_RX].as_u64[1]); - } + sum = ip_csum_add_even (sum, new_addr[VLIB_TX].as_u64[0]); + sum = ip_csum_add_even (sum, new_addr[VLIB_TX].as_u64[1]); + sum = ip_csum_sub_even (sum, old_addr[VLIB_TX].as_u64[0]); + sum = ip_csum_sub_even (sum, old_addr[VLIB_TX].as_u64[1]); + + sum = ip_csum_add_even (sum, new_addr[VLIB_RX].as_u64[0]); + sum = ip_csum_add_even (sum, new_addr[VLIB_RX].as_u64[1]); + sum = ip_csum_sub_even (sum, old_addr[VLIB_RX].as_u64[0]); + sum = ip_csum_sub_even (sum, old_addr[VLIB_RX].as_u64[1]); echo->identifier = new_port[VLIB_RX]; - sum = ip_csum_update (sum, old_port, new_port[VLIB_RX], - ip4_header_t /* cheat */ , - length /* changed member */ ); + sum = + ip_csum_update (sum, old_port, new_port[VLIB_RX], udp_header_t, src_port); icmp->checksum = ip_csum_fold (sum); } @@ -595,79 +551,64 @@ cnat_translation_icmp6_error (ip6_header_t * outer_ip6, if (!snat_outer_ip) ip6_address_copy (&outer_new_addr[VLIB_RX], &outer_ip6->src_address); cnat_ip6_translate_l3 (outer_ip6, outer_new_addr); - if (has_ip6_address (&outer_new_addr[VLIB_TX])) - { - sum = ip_csum_add_even (sum, outer_new_addr[VLIB_TX].as_u64[0]); - sum = ip_csum_add_even (sum, outer_new_addr[VLIB_TX].as_u64[1]); - sum = ip_csum_sub_even (sum, outer_old_addr[VLIB_TX].as_u64[0]); - sum = ip_csum_sub_even (sum, outer_old_addr[VLIB_TX].as_u64[1]); - } - if (has_ip6_address (&outer_new_addr[VLIB_RX])) - { - sum = ip_csum_add_even (sum, outer_new_addr[VLIB_RX].as_u64[0]); - sum = ip_csum_add_even (sum, outer_new_addr[VLIB_RX].as_u64[1]); - sum = ip_csum_sub_even (sum, outer_old_addr[VLIB_RX].as_u64[0]); - sum = ip_csum_sub_even (sum, outer_old_addr[VLIB_RX].as_u64[1]); - } + sum = ip_csum_add_even (sum, outer_new_addr[VLIB_TX].as_u64[0]); + sum = ip_csum_add_even (sum, outer_new_addr[VLIB_TX].as_u64[1]); + sum = ip_csum_sub_even (sum, outer_old_addr[VLIB_TX].as_u64[0]); + sum = ip_csum_sub_even (sum, outer_old_addr[VLIB_TX].as_u64[1]); + + sum = ip_csum_add_even (sum, outer_new_addr[VLIB_RX].as_u64[0]); + sum = ip_csum_add_even (sum, outer_new_addr[VLIB_RX].as_u64[1]); + sum = ip_csum_sub_even (sum, outer_old_addr[VLIB_RX].as_u64[0]); + sum = ip_csum_sub_even (sum, outer_old_addr[VLIB_RX].as_u64[1]); /* Translate inner TCP / UDP */ if (ip6->protocol == IP_PROTOCOL_TCP) { inner_l4_old_sum = inner_l4_sum = tcp->checksum; - cnat_ip6_translate_l4 (ip6, udp, &inner_l4_sum, new_addr, new_port); + cnat_ip6_translate_l4 (ip6, udp, &inner_l4_sum, new_addr, new_port, + 0 /* oflags */); tcp->checksum = ip_csum_fold (inner_l4_sum); } else if (ip6->protocol == IP_PROTOCOL_UDP) { inner_l4_old_sum = inner_l4_sum = udp->checksum; - cnat_ip6_translate_l4 (ip6, udp, &inner_l4_sum, new_addr, new_port); + cnat_ip6_translate_l4 (ip6, udp, &inner_l4_sum, new_addr, new_port, + 0 /* oflags */); udp->checksum = ip_csum_fold (inner_l4_sum); } else return; /* UDP/TCP checksum changed */ - sum = ip_csum_update (sum, inner_l4_old_sum, inner_l4_sum, - ip4_header_t /* cheat */ , + sum = ip_csum_update (sum, inner_l4_old_sum, inner_l4_sum, ip4_header_t, checksum); /* UDP/TCP Ports changed */ - if (old_port[VLIB_TX] && new_port[VLIB_TX]) - sum = ip_csum_update (sum, old_port[VLIB_TX], new_port[VLIB_TX], - ip4_header_t /* cheat */ , - length /* changed member */ ); - - if (old_port[VLIB_RX] && new_port[VLIB_RX]) - sum = ip_csum_update (sum, old_port[VLIB_RX], new_port[VLIB_RX], - ip4_header_t /* cheat */ , - length /* changed member */ ); + sum = ip_csum_update (sum, old_port[VLIB_TX], new_port[VLIB_TX], + udp_header_t, dst_port); + sum = ip_csum_update (sum, old_port[VLIB_RX], new_port[VLIB_RX], + udp_header_t, src_port); cnat_ip6_translate_l3 (ip6, new_addr); /* IP src/dst addr changed */ - if (has_ip6_address (&new_addr[VLIB_TX])) - { - sum = ip_csum_add_even (sum, new_addr[VLIB_TX].as_u64[0]); - sum = ip_csum_add_even (sum, new_addr[VLIB_TX].as_u64[1]); - sum = ip_csum_sub_even (sum, old_addr[VLIB_TX].as_u64[0]); - sum = ip_csum_sub_even (sum, old_addr[VLIB_TX].as_u64[1]); - } + sum = ip_csum_add_even (sum, new_addr[VLIB_TX].as_u64[0]); + sum = ip_csum_add_even (sum, new_addr[VLIB_TX].as_u64[1]); + sum = ip_csum_sub_even (sum, old_addr[VLIB_TX].as_u64[0]); + sum = ip_csum_sub_even (sum, old_addr[VLIB_TX].as_u64[1]); - if (has_ip6_address (&new_addr[VLIB_RX])) - { - sum = ip_csum_add_even (sum, new_addr[VLIB_RX].as_u64[0]); - sum = ip_csum_add_even (sum, new_addr[VLIB_RX].as_u64[1]); - sum = ip_csum_sub_even (sum, old_addr[VLIB_RX].as_u64[0]); - sum = ip_csum_sub_even (sum, old_addr[VLIB_RX].as_u64[1]); - } + sum = ip_csum_add_even (sum, new_addr[VLIB_RX].as_u64[0]); + sum = ip_csum_add_even (sum, new_addr[VLIB_RX].as_u64[1]); + sum = ip_csum_sub_even (sum, old_addr[VLIB_RX].as_u64[0]); + sum = ip_csum_sub_even (sum, old_addr[VLIB_RX].as_u64[1]); icmp->checksum = ip_csum_fold (sum); } static_always_inline void -cnat_translation_ip6 (const cnat_session_t * session, - ip6_header_t * ip6, udp_header_t * udp) +cnat_translation_ip6 (const cnat_session_t *session, ip6_header_t *ip6, + udp_header_t *udp, u32 oflags) { tcp_header_t *tcp = (tcp_header_t *) udp; ip6_address_t new_addr[VLIB_N_DIR]; @@ -681,7 +622,7 @@ cnat_translation_ip6 (const cnat_session_t * session, if (ip6->protocol == IP_PROTOCOL_TCP) { ip_csum_t sum = tcp->checksum; - cnat_ip6_translate_l4 (ip6, udp, &sum, new_addr, new_port); + cnat_ip6_translate_l4 (ip6, udp, &sum, new_addr, new_port, oflags); tcp->checksum = ip_csum_fold (sum); cnat_ip6_translate_l3 (ip6, new_addr); cnat_tcp_update_session_lifetime (tcp, session->value.cs_ts_index); @@ -689,7 +630,7 @@ cnat_translation_ip6 (const cnat_session_t * session, else if (ip6->protocol == IP_PROTOCOL_UDP) { ip_csum_t sum = udp->checksum; - cnat_ip6_translate_l4 (ip6, udp, &sum, new_addr, new_port); + cnat_ip6_translate_l4 (ip6, udp, &sum, new_addr, new_port, oflags); udp->checksum = ip_csum_fold (sum); cnat_ip6_translate_l3 (ip6, new_addr); } diff --git a/src/plugins/cnat/cnat_node_feature.c b/src/plugins/cnat/cnat_node_feature.c index 76aa893983d..2ab5cb232b4 100644 --- a/src/plugins/cnat/cnat_node_feature.c +++ b/src/plugins/cnat/cnat_node_feature.c @@ -156,9 +156,9 @@ cnat_input_feature_fn (vlib_main_t *vm, vlib_node_runtime_t *node, } if (AF_IP4 == ctx->af) - cnat_translation_ip4 (session, ip4, udp0); + cnat_translation_ip4 (session, ip4, udp0, vnet_buffer (b)->oflags); else - cnat_translation_ip6 (session, ip6, udp0); + cnat_translation_ip6 (session, ip6, udp0, vnet_buffer (b)->oflags); if (NULL != ct) { @@ -326,9 +326,9 @@ cnat_output_feature_fn (vlib_main_t *vm, vlib_node_runtime_t *node, } if (AF_IP4 == ctx->af) - cnat_translation_ip4 (session, ip4, udp0); + cnat_translation_ip4 (session, ip4, udp0, vnet_buffer (b)->oflags); else - cnat_translation_ip6 (session, ip6, udp0); + cnat_translation_ip6 (session, ip6, udp0, vnet_buffer (b)->oflags); trace: if (PREDICT_FALSE (ctx->do_trace)) diff --git a/src/plugins/cnat/cnat_node_snat.c b/src/plugins/cnat/cnat_node_snat.c index 9212d67ead6..f5c8a20121c 100644 --- a/src/plugins/cnat/cnat_node_snat.c +++ b/src/plugins/cnat/cnat_node_snat.c @@ -133,11 +133,10 @@ cnat_snat_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, CNAT_SESSION_FLAG_HAS_SNAT); } - if (AF_IP4 == ctx->af) - cnat_translation_ip4 (session, ip4, udp0); + cnat_translation_ip4 (session, ip4, udp0, vnet_buffer (b)->oflags); else - cnat_translation_ip6 (session, ip6, udp0); + cnat_translation_ip6 (session, ip6, udp0, vnet_buffer (b)->oflags); trace: if (PREDICT_FALSE (b->flags & VLIB_BUFFER_IS_TRACED)) diff --git a/src/plugins/cnat/cnat_node_vip.c b/src/plugins/cnat/cnat_node_vip.c index f166bd4f194..5db19d2c61e 100644 --- a/src/plugins/cnat/cnat_node_vip.c +++ b/src/plugins/cnat/cnat_node_vip.c @@ -176,9 +176,9 @@ cnat_vip_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b, } if (AF_IP4 == ctx->af) - cnat_translation_ip4 (session, ip4, udp0); + cnat_translation_ip4 (session, ip4, udp0, vnet_buffer (b)->oflags); else - cnat_translation_ip6 (session, ip6, udp0); + cnat_translation_ip6 (session, ip6, udp0, vnet_buffer (b)->oflags); if (NULL != ct) { |