Hi Austin,

There is a special function in northd.c to handle hairpin traffic - 
build_vtep_hairpin().
The mentioned flows are not matched due to flow [1], which by default sends all 
traffic received from vtep lport to l2lkp table for local delivery.
As you correctly noticed, there is no instance to handle "special" traffic 
coming from VTEP.
But there is a mechanism introduced in [2], [3], where you can attach LS to LR 
and set gw chassis for associated LRP to one of your chassis.
ARP responses for LRPs are made with such logic [4].

You can try to add similar logic for DHCP traffic, set loopback flag and 
resubmit packet to appropriate table. This can be not enough.

Hope this helps.

1: https://github.com/ovn-org/ovn/blob/0d021216c/northd/northd.c#L8374-L8377
2: 
https://github.com/ovn-org/ovn/commit/4e90bcf55c2ef1ab9940836455e4bfe36e57f307
3: 
https://github.com/ovn-org/ovn/commit/f20f664bc962094e4679ff2d3a8d834637bff27f
4: https://github.com/ovn-org/ovn/blob/0d021216c/northd/northd.c#L8403-L8405

> On 31 Aug 2023, at 21:04, Austin Cormier via discuss 
> <ovs-discuss@openvswitch.org> wrote:
> 
> I’m trying to understand whether DHCP is supported (or can easily be 
> supported) for vtep port types.  The use case I am driving towards is to 
> support DHCP/PXE booting for hardware over vxlan overlay network via a TOR 
> switch.  I believe this could work using Neutron DHCP Agent but we’ve hit 
> scaling issues in that area so we’re attempting to use OVN DHCP server if 
> possible.
>  
> In the NB DB, the vtep port is added to the ironic provisioning network with 
> both the IP/MAC set.
>  
>  
> $ ovn-nbctl show
> …
> switch 99a907e0-7525-4d4e-a029-fddaafeff3e5 
> (neutron-a2d49759-d8fa-43a3-8620-35201420f72b) (aka Ironic Provisioning)
>     port provnet-2fd9fb49-7e68-4f86-8690-aec776e9f128
>         type: localnet
>         addresses: ["unknown"]
>     port 2ebf0521-3f7e-44b6-848f-82a0214e3c25
>         type: localport
>         addresses: ["fa:16:3e:7f:e9:56 10.90.100.1"]
>     port 23af2a74-0333-4600-9e11-e99bff860999
>         type: vtep
>         addresses: ["0c:c4:7a:ac:75:4e 10.90.100.32"]
>  
>  
> In the SB database, I see the port binding under the data-switch-01 chassis:
>  
> $ ovn-sbctl show
> Chassis compute-test
>     hostname: compute-test
>     Encap vxlan
>         ip: "10.40.0.1"
>         options: {csum="true"}
>     Port_Binding "04901637-9467-4f01-b16b-e22de768a1b8"
> Chassis data-switch-01
>     Encap vxlan
>         ip: "17.17.17.17"
>         options: {csum="false"}
>     Port_Binding "23af2a74-0333-4600-9e11-e99bff860999"
> Chassis controller-test
>     hostname: controller-test
>     Encap geneve
>         ip: "10.40.0.3"
>         options: {csum="true"}
>     Encap vxlan
>         ip: "10.40.0.3"
>         options: {csum="true"}
>     Port_Binding cr-lrp-876f85ad-0a6f-4668-8736-e122fedc32c2
>  
>  
>  
> In the logical flow list, it appears that the DHCP responses are added:
>  
>   table=19(ls_in_arp_rsp      ), priority=50   , match=(arp.tpa == 
> 10.90.100.1 && arp.op == 1), action=(eth.dst = eth.src; eth.src = 
> fa:16:3e:7f:e9:56; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = 
> fa:16:3e:7f:e9:56; arp.tpa = arp.spa; arp.spa = 10.90.100.1; ou
> tport = inport; flags.loopback = 1; output;)
>   table=19(ls_in_arp_rsp      ), priority=50   , match=(arp.tpa == 
> 10.90.100.32 && arp.op == 1), action=(eth.dst = eth.src; eth.src = 
> 0c:c4:7a:ac:75:4e; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = 
> 0c:c4:7a:ac:75:4e; arp.tpa = arp.spa; arp.spa = 10.90.100.32;
> outport = inport; flags.loopback = 1; output;)
>   table=19(ls_in_arp_rsp      ), priority=0    , match=(1), action=(next;)
>   table=20(ls_in_dhcp_options ), priority=100  , match=(inport == 
> "23af2a74-0333-4600-9e11-e99bff860999" && eth.src == 0c:c4:7a:ac:75:4e && 
> ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst 
> == 67), action=(reg0[3] = put_dhcp_opts(offerip = 10.90
> .100.32, bootfile_name = http://192.168.3.3:8089/boot.ipxe, bootfile_name_alt 
> = "snponly.efi", classless_static_route = {169.254.169.254/32,10.90.100.1}, 
> dns_server = {127.0.0.53}, lease_time = 43200, mtu = 1500, netmask = 
> 255.255.0.0, next_server = 192.168.3.3, server_
> id = 10.90.100.1, tftp_server = "192.168.3.3", tftp_server_address = 
> 192.168.3.3); next;)
> table=20(ls_in_dhcp_options ), priority=100  , match=(inport == 
> "23af2a74-0333-4600-9e11-e99bff860999" && eth.src == 0c:c4:7a:ac:75:4e && 
> ip4.src == 10.90.100.32 && ip4.dst == {10.90.100.1, 255.255.255.255} && 
> udp.src == 68 && udp.dst == 67), action=(reg0[3] = put_dhcp_
> opts(offerip = 10.90.100.32, bootfile_name = 
> http://192.168.3.3:8089/boot.ipxe, bootfile_name_alt = "snponly.efi", 
> classless_static_route = {169.254.169.254/32,10.90.100.1}, dns_server = 
> {127.0.0.53}, lease_time = 43200, mtu = 1500, netmask = 255.255.0.0, 
> next_server =
> 192.168.3.3, server_id = 10.90.100.1, tftp_server = "192.168.3.3", 
> tftp_server_address = 192.168.3.3); next;)
>   table=20(ls_in_dhcp_options ), priority=0    , match=(1), action=(next;)
>   table=21(ls_in_dhcp_response), priority=100  , match=(inport == 
> "23af2a74-0333-4
>  
>  
> But when I packet capture I see the DHCP requests but no responses are sent.  
> Using OVN-trace, it doesn’t appear that we’re hitting the appropriate flow to 
> generate the DHCP response:
>  
> ---
> # ovn-trace 99a907e0-7525-4d4e-a029-fddaafeff3e5 'inport == 
> "23af2a74-0333-4600-9e11-e99bff860999" && eth.src == 0c:c4:7a:ac:75:4e && 
> ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst 
> == 67'
> # 
> udp,reg14=0x3,vlan_tci=0x0000,dl_src=0c:c4:7a:ac:75:4e,dl_dst=00:00:00:00:00:00,nw_src=0.0.0.0,nw_dst=255.255.255.255,nw_tos=0,nw_ecn=0,nw_ttl=0,nw_frag=no,tp_src=68,tp_dst=67
>  
> ingress(dp="Ironic Provisioning", inport="23af2a")
> --------------------------------------------------
> 0. ls_in_check_port_sec (northd.c:5680): inport == "23af2a", priority 70, 
> uuid aaeb17c1
>     reg0[14] = 1;
>     next(16);
> 16. ls_in_hairpin (northd.c:7637): reg0[14] == 1, priority 1000, uuid bee04e33
>     next(25);
> 25. ls_in_l2_lkup (northd.c:8326): 1, priority 0, uuid f7842991
>     outport = get_fdb(eth.dst);
>     next;
> 26. ls_in_l2_unknown (northd.c:8330): outport == "none", priority 50, uuid 
> da5c2086
>     outport = "_MC_unknown";
>     output;
>  
> multicast(dp="Ironic Provisioning", mcgroup="_MC_unknown")
> ----------------------------------------------------------
>  
>     egress(dp="Ironic Provisioning", inport="23af2a", outport="port_a")
>     -------------------------------------------------------------------
>          0. ls_out_pre_acl (northd.c:5904): ip, priority 100, uuid 87214ca2
>             reg0[0] = 1;
>             next;
>          2. ls_out_pre_stateful (northd.c:6116): reg0[0] == 1, priority 100, 
> uuid 00a32995
>             ct_next;
>  
>         ct_next(ct_state=est|trk /* default (use --ct to customize) */)
>         ---------------------------------------------------------------
>          3. ls_out_acl_hint (northd.c:6201): !ct.new && ct.est && !ct.rpl && 
> ct_label.blocked == 0, priority 4, uuid c617b2cb
>             reg0[8] = 1;
>             reg0[10] = 1;
>             next;
>          8. ls_out_check_port_sec (northd.c:5757): 1, priority 0, uuid 
> 2816b94d
>             reg0[15] = check_out_port_sec();
>             next;
>          9. ls_out_apply_port_sec (northd.c:5762): 1, priority 0, uuid 
> 74fbe3e4
>             output;
>             /* output to "port_a", type "" */
>  
>     egress(dp="Ironic Provisioning", inport="23af2a", 
> outport="provnet-2fd9fb")
>     
> ---------------------------------------------------------------------------
>          0. ls_out_pre_acl (northd.c:5790): ip && outport == 
> "provnet-2fd9fb", priority 110, uuid 35b95f2e
>             next;
>          1. ls_out_pre_lb (northd.c:5790): ip && outport == "provnet-2fd9fb", 
> priority 110, uuid 27a6943d
>             next;
>          2. ls_out_pre_stateful (northd.c:6116): reg0[0] == 1, priority 100, 
> uuid 00a32995
>             ct_next;
>  
>         ct_next(ct_state=est|trk /* default (use --ct to customize) */)
>         ---------------------------------------------------------------
>          3. ls_out_acl_hint (northd.c:6201): !ct.new && ct.est && !ct.rpl && 
> ct_label.blocked == 0, priority 4, uuid c617b2cb
>             reg0[8] = 1;
>             reg0[10] = 1;
>             next;
>          8. ls_out_check_port_sec (northd.c:5757): 1, priority 0, uuid 
> 2816b94d
>             reg0[15] = check_out_port_sec();
>             next;
>          9. ls_out_apply_port_sec (northd.c:5762): 1, priority 0, uuid 
> 74fbe3e4
>             output;
>             /* output to "provnet-2fd9fb", type "localnet" */
>  
>  
> One theory I have is that it CANNOT work this way because without an 
> “external” port there’s no OVS which would actually handle the flow at the 
> datapath layer.  I figured it was worth a shot to send an email to see if 
> this is the case and whether there is any potential workaround for having OVN 
> generate the DHCP responses.
>  
> Appreciate any guidance.
>  
> -Austin
>  
> 
> Juniper Business Use Only
> 
> _______________________________________________
> discuss mailing list
> disc...@openvswitch.org <mailto:disc...@openvswitch.org>
> https://mail.openvswitch.org/mailman/listinfo/ovs-discuss




Regards,
Vladislav Odintsov

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

Reply via email to