static inline int
nat_not_translate_output_feature (snat_main_t * sm, ip4_header_t * ip0,
- u32 proto0, u32 thread_index)
+ u32 proto0, u16 src_port, u16 dst_port,
+ u32 thread_index, u32 sw_if_index)
{
- udp_header_t * udp0 = ip4_next_header (ip0);
snat_session_key_t key0;
clib_bihash_kv_8_8_t kv0, value0;
+ snat_interface_t *i;
+ /* src NAT check */
key0.addr = ip0->src_address;
- key0.port = udp0->src_port;
+ key0.port = src_port;
key0.protocol = proto0;
key0.fib_index = sm->outside_fib_index;
kv0.key = key0.as_u64;
if (!clib_bihash_search_8_8 (&sm->per_thread_data[thread_index].out2in, &kv0,
- &value0))
+ &value0))
+ return 1;
+
+ /* dst NAT check */
+ key0.addr = ip0->dst_address;
+ key0.port = dst_port;
+ key0.protocol = proto0;
+ key0.fib_index = sm->inside_fib_index;
+ kv0.key = key0.as_u64;
+ if (!clib_bihash_search_8_8 (&sm->per_thread_data[thread_index].in2out, &kv0,
+ &value0))
+ {
+ /* hairpinning */
+ pool_foreach (i, sm->output_feature_interfaces,
+ ({
+ if ((nat_interface_is_inside(i)) && (sw_if_index == i->sw_if_index))
+ return 0;
+ }));
return 1;
+ }
return 0;
}
if (vnet_buffer(b0)->sw_if_index[VLIB_TX] != ~0)
{
if (PREDICT_FALSE(nat_not_translate_output_feature(sm,
- ip0, IP_PROTOCOL_ICMP, thread_index)))
+ ip0, SNAT_PROTOCOL_ICMP, key0.port, key0.port, thread_index, sw_if_index0)))
{
dont_translate = 1;
goto out;
else
{
if (PREDICT_FALSE(snat_not_translate(sm, node, sw_if_index0,
- ip0, IP_PROTOCOL_ICMP, rx_fib_index0, thread_index)))
+ ip0, SNAT_PROTOCOL_ICMP, rx_fib_index0, thread_index)))
{
dont_translate = 1;
goto out;
src_address /* changed member */);
ip0->checksum = ip_csum_fold (sum0);
+ if (icmp0->checksum == 0)
+ icmp0->checksum = 0xffff;
+
if (!icmp_is_error_message (icmp0))
{
new_id0 = sm0.port;
key.fib_index = rx_fib_index;
key.proto = ip->protocol;
key.l_port = 0;
- key.l_port = 0;
+ key.r_port = 0;
s_kv.key[0] = key.as_u64[0];
s_kv.key[1] = key.as_u64[1];
s->outside_address_index = ~0;
s->in2out = l_key;
s->out2in = e_key;
+ s->out2in.protocol = l_key.protocol;
u->nstaticsessions++;
/* Add to lookup tables */
if (is_output_feature)
{
if (PREDICT_FALSE(nat_not_translate_output_feature(sm,
- ip0, proto0, thread_index)))
+ ip0, proto0, udp0->src_port, udp0->dst_port, thread_index, sw_if_index0)))
goto trace00;
}
else
if (is_output_feature)
{
if (PREDICT_FALSE(nat_not_translate_output_feature(sm,
- ip1, proto1, thread_index)))
- goto trace00;
+ ip1, proto1, udp1->src_port, udp1->dst_port, thread_index, sw_if_index1)))
+ goto trace01;
}
else
{
if (is_output_feature)
{
if (PREDICT_FALSE(nat_not_translate_output_feature(sm,
- ip0, proto0, thread_index)))
+ ip0, proto0, udp0->src_port, udp0->dst_port, thread_index, sw_if_index0)))
goto trace0;
}
else