On Wed, Jan 24, 2024 at 6:05 PM Martin Kalcok via discuss
<ovs-discuss@openvswitch.org> wrote:
>
> Hi everyone,
> We are encountering an issue with our (Openstack) topology where we
> need to directly access hosts in SNATed network from external network.
> While the traffic like ICMP works fine, TCP traffic gets SNATed on the
> way back **after** the initial handshake. Our setup looks something
> like this:
>
> OVN from git (0ce21f2)
> OVS from git (4102674)
>
> 3x Nova Compute hypervisor, each with GW Chassis
>
> External network:                   10.5.0./16
> Host on ext. net (S1):              10.5.0.16
> Logical Router (r1) ext. IP:        10.5.150.143
> Internal network (a_net) with SNAT: 192.168.10.0/24
> Guest VM (A1) on the int. network:  192.168.10.83
>
> (Host S1 has static routes for the internal network via r1's external
> IP)
>
> I think the problem is best demonstrated on the tcpdump captured on the
> S1 trying to communicate with A1 [0] (I'm going to use pastebin to keep
> this mail shorter, I hope that it's OK). As you can see, after the
> initial handshake, S1 pushes data, but ACK comes back from SNATed
> router's IP.
>
> I also took OVN traces:
>
> * S1 -> A1 (New direction)[1]
> * A1 -> S1 (Reply direction)[2]
>
> The traces themselves look good as they don't show any SNAT in the
> reply direction but I'm not sure that this is what's actually happening
> when the packet goes through the router. I see that the SNAT rules
> should not match for packets in "reply" direction [3] but I don't see
> (in the trace) that the router would apply connection tracking on the
> packets with "ct_next". If I understand this correctly, if the router
> does not commit flow into the connection tracking, it is not able to
> match on ct_state.
>
> I tried to apply following changes that initiate CT and commit packets
> to the conntrack and it seems to fix the issue without breaking
> anything. The gist of the change is that the router initiates CT in the
> ingress and commits the packet into CT before moving it to the egress
> pipeline. That way, when the packets in the reply direction show up,
> router can determine that they are replies and does not perform the
> SNAT.
>
> I very much just eyeballed where to put the "ct_next" and "ct_commit"
> so I'm sure that this is not the final solution, but I'd just like to
> know if I'm going in the right direction.
>
> diff --git a/northd/northd.c b/northd/northd.c
> index 952f8200d..4eea38cbd 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -11792,7 +11792,7 @@ add_route(struct hmap *lflows, struct
> ovn_datapath *od,
>                        "eth.src = %s; "
>                        "outport = %s; "
>                        "flags.loopback = 1; "
> -                      "next;",
> +                      "ct_next;",
>                        is_ipv4 ? REG_SRC_IPV4 : REG_SRC_IPV6,
>                        lrp_addr_s,
>                        op->lrp_networks.ea_s,
> @@ -14331,7 +14331,7 @@ build_arp_request_flows_for_lrouter(
>                        "};",
>                        copp_meter_get(COPP_ND_NS_RESOLVE, od->nbr-
> >copp,
>                                       meter_groups));
> -    ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, 0, "1",
> "output;");
> +    ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, 0, "1",
> "ct_commit { }; output;");
>  }
>
>  /* Logical router egress table DELIVERY: Delivery (priority 100-110).
> @@ -15692,7 +15692,7 @@ build_lrouter_nat_defrag_and_lb(struct
> ovn_datapath *od, struct hmap *lflows,
>      ovn_lflow_add(lflows, od, S_ROUTER_IN_DEFRAG, 0, "1", "next;");
>      ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, 0, "1", "next;");
>      ovn_lflow_add(lflows, od, S_ROUTER_OUT_CHECK_DNAT_LOCAL, 0, "1",
> -                  REGBIT_DST_NAT_IP_LOCAL" = 0; next;");
> +                  REGBIT_DST_NAT_IP_LOCAL" = 0; ct_next;");
>      ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT, 0, "1", "next;");
>      ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 0, "1", "next;");
>      ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 0, "1", "next;");
>
>
> Thank you for any suggestions,
> Martin.
>
> -----
> [0] https://pastebin.com/gmbNP1Bg
> [1] https://pastebin.com/155aVzYj
> [2] https://pastebin.com/pcAuCFhT
> [3]
> https://github.com/ovn-org/ovn/blob/0ce21f2adda1edeeafe10a1d62cd976039a42492/northd/northd.c#L15418

Thanks alot for starting this discussion, Martin!

I just wanted to chime in with the desire to see this use case working
and I know we have examples of end users coming from ML2/OVS with this
expectation. There are also other facets of this problem complex with
issues such as internal IP access to a DNAT'ed address backed by an IP
on the same network etc. but I'm sure we will get onto those as part
of the discussion.

FWIW; there are some descriptions of the handling of this use case in
OpenStack documentation and specs, so I thought it would be useful to
reference that here [4] to support the discussion.

4: 
https://github.com/openstack/neutron/blob/3ef02cc2fb44a665001df1074b9e6e383a9d83a6/doc/source/contributor/internals/address_scopes.rst#l3-agent

-- 
Frode Nordahl

> _______________________________________________
> discuss mailing list
> disc...@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-discuss
_______________________________________________
discuss mailing list
disc...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-discuss

Reply via email to