Hi Vladislav, Thank you for the references. I will investigate this approach. It would be simpler for us to provide the DHCP this way but will have to dive in to understand how much effort would be required. Really appreciate it.
-Austin Juniper Business Use Only From: Vladislav Odintsov <odiv...@gmail.com> Date: Thursday, August 31, 2023 at 3:19 PM To: Austin Cormier <acorm...@juniper.net> Cc: ovs-discuss@openvswitch.org <ovs-discuss@openvswitch.org> Subject: Re: [ovs-discuss] OVN: DHCP Support for vtep port type [External Email. Be cautious of content] 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<https://urldefense.com/v3/__http:/192.168.3.3:8089/boot.ipxe__;!!NEt6yMaO-gk!AfdRg7WKrtczkbjgobERRNKzATR-BOn8U7axVrVO3AJOaGsP2i_FLcnmeHJpqkCBI6ytfXL2Z9A3W4Sz$>, 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<https://urldefense.com/v3/__http:/192.168.3.3:8089/boot.ipxe__;!!NEt6yMaO-gk!AfdRg7WKrtczkbjgobERRNKzATR-BOn8U7axVrVO3AJOaGsP2i_FLcnmeHJpqkCBI6ytfXL2Z9A3W4Sz$>, 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<https://urldefense.com/v3/__https:/mail.openvswitch.org/mailman/listinfo/ovs-discuss__;!!NEt6yMaO-gk!AfdRg7WKrtczkbjgobERRNKzATR-BOn8U7axVrVO3AJOaGsP2i_FLcnmeHJpqkCBI6ytfXL2Z98F8-mx$> Regards, Vladislav Odintsov
_______________________________________________ discuss mailing list disc...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-discuss