+ nat_6t_i2o_flow_init (sm, thread_index, s, ip->src_address, 0,
+ ip->dst_address, 0, rx_fib_index, ip->protocol);
+ nat_6t_flow_saddr_rewrite_set (&s->i2o, new_src_addr.as_u32);
+ nat_6t_flow_txfib_rewrite_set (&s->i2o, outside_fib_index);
+
+ // hairpinning?
+ int is_hairpinning =
+ nat44_ed_external_sm_lookup (sm, ip->dst_address, 0, NAT_PROTOCOL_OTHER,
+ outside_fib_index, &new_dst_addr, NULL);
+ s->flags |= is_hairpinning * SNAT_SESSION_FLAG_HAIRPINNING;
+
+ nat_6t_flow_daddr_rewrite_set (&s->i2o, new_dst_addr.as_u32);
+ nat_6t_flow_txfib_rewrite_set (&s->i2o, outside_fib_index);
+
+ nat_6t_o2i_flow_init (sm, thread_index, s, new_dst_addr, 0, new_src_addr, 0,
+ outside_fib_index, ip->protocol);
+ nat_6t_flow_saddr_rewrite_set (&s->o2i, ip->dst_address.as_u32);
+ nat_6t_flow_daddr_rewrite_set (&s->o2i, ip->src_address.as_u32);
+ nat_6t_flow_txfib_rewrite_set (&s->o2i, rx_fib_index);
+
+ s->ext_host_addr.as_u32 = ip->dst_address.as_u32;
+ s->flags |= SNAT_SESSION_FLAG_UNKNOWN_PROTO;
+ s->flags |= SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT;
+ s->out2in.addr.as_u32 = new_src_addr.as_u32;
+ s->out2in.fib_index = outside_fib_index;
+ s->in2out.addr.as_u32 = ip->src_address.as_u32;
+ s->in2out.fib_index = rx_fib_index;
+ s->in2out.port = s->out2in.port = ip->protocol;
+ if (m)
+ s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
+
+ if (nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, s, 1))
+ {
+ nat_elog_notice ("in2out flow hash add failed");
+ nat_ed_session_delete (sm, s, thread_index, 1);
+ return NULL;
+ }
+
+ if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, s, 1))
+ {
+ nat_elog_notice ("out2in flow hash add failed");
+ nat_ed_session_delete (sm, s, thread_index, 1);
+ return NULL;
+ }
+
+ per_vrf_sessions_register_session (s, thread_index);