summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Skrzypczak <nathan.skrzypczak@gmail.com>2021-02-25 19:13:19 +0100
committerNathan Skrzypczak <nathan.skrzypczak@gmail.com>2023-08-07 11:34:48 +0200
commitb22da9c7d101dca833a5c4183e7cf13943f16715 (patch)
tree80c21ea31740ee9dd3ec48f94368067e05656b90
parent994a58997dec4a1a34efd8e43440b56d100d44af (diff)
cnat: Support offloaded check sums
This patch removes zero checks for new_addr, new_port meaning sessions with zero values will rewrite the packet with a 0 value instead of leaving it in place. This allows to reduce branchiness in the code, and sessions are fully resolved at creation time anyway. This also adds support for checksum offloads: - IP checksum offload : we always compute the checksum to avoid issues with drivers. We'll revert this if we realize cost gets too important. - TCP/UDP checksum offload : we add the implementation for pseudo header checksum computation. This is needed for the drivers that do not re-compute this pseudo-checksum before the packet is TX-ed (e.g. a few DPDK drivers). Type: improvement Change-Id: I6543f3aec8c120ec50f4219108609138283620ef Signed-off-by: Nathan Skrzypczak <nathan.skrzypczak@gmail.com>
-rw-r--r--src/plugins/cnat/cnat_node.h353
-rw-r--r--src/plugins/cnat/cnat_node_feature.c8
-rw-r--r--src/plugins/cnat/cnat_node_snat.c5
-rw-r--r--src/plugins/cnat/cnat_node_vip.c4
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)
{