incus icon indicating copy to clipboard operation
incus copied to clipboard

Add support for `ipv4.dhcp.ranges` on OVN

Open stgraber opened this issue 1 year ago • 6 comments
trafficstars

As discussed in https://discuss.linuxcontainers.org/t/ovn-dhcp-ranges/21290, OVN supports an exclude_ips configuration key on the logical switch. This works as reverse of the Incus syntax but it should be easy enough to take the subnet, remove the DHCP range from it and then put in the rest as the exclusion in OVN.

stgraber avatar Aug 08 '24 16:08 stgraber

Hi Stéphane, I'd like to start contributing to Incus, and I think this is a good first issue. You could give me some advice on where to change the code to add support for DHCP ranges?

Looking into the code, I think I should add a config ipv4.dhcp.ranges here if it's nil and define a default value as auto.

https://github.com/lxc/incus/blob/main/internal/server/network/driver_ovn.go#L1796

Furthermore, I should check here if ipv4.dhcp.ranges has a value and set exclude_ips based on subnets?

https://github.com/lxc/incus/blob/main/internal/server/network/ovn/ovn_nb_actions.go#L1095

winiciusallan avatar Aug 29 '24 01:08 winiciusallan

So the first thing to do is going to be making the configuration option be valid for OVN. For that, you'll need to:

  • Add ipv4.dhcp.ranges to https://github.com/lxc/incus/blob/main/internal/server/network/driver_ovn.go#L351 based on the same definition for the bridge driver at https://github.com/lxc/incus/blob/main/internal/server/network/driver_bridge.go#L221
  • Extend the getDHCPv4Reservations function to return a correct exclude list based on ipv4.dhcp.ranges. That'd be in https://github.com/lxc/incus/blob/main/internal/server/network/driver_ovn.go#L1951

The main catch here is that the logic must be somewhat reversed, so say you have ipv4.address set to 192.168.0.1/24, and you have instances foo and bar with static IP addresses 192.168.0.11 and 192.168.0.12`, currently the exclude list will end up being:

  • 192.168.0.1 (gateway)
  • 192.168.0.11 (static IP on foo)
  • 192.168.0.12 (static IP on bar)
  • 192.168.0.254 (reserved for health checks)

Now if we are to set a ipv4.dhcp.ranges value of 192.168.0.50-192.168.0.75,192.168.0.150-192.168.0.200, this needs to evolve the exclude to be:

  • 192.168.0.1 (gateway)
  • 192.168.0.2 - 192.168.0.10 (outside of DHCP range)
  • 192.168.0.11 (static IP on foo)
  • 192.168.0.12 (static IP on bar)
  • 192.168.0.13 - 192.168.0.49 (outside of DHCP range)
  • 192.168.0.76 - 192.168.0.149 (outside of DHCP range)
  • 192.168.0.201 - 192.168.0.253 (outside of DHCP range)
  • 192.168.0.254 (reserved for health checks)

Per https://man7.org/linux/man-pages/man5/ovn-nb.5.html#Logical_Switch_TABLE OVN supports a range syntax too, so to render a range between 192.168.0.13 and 192.168.0.49, you can use the 192.168.0.13..192.168.0.49 syntax, saving yourself from having to generate all the individual records.

stgraber avatar Aug 29 '24 01:08 stgraber

I've created a pull request with a WIP label because I want to know how I can use the OVN range syntax to parse from it to IP. Range or something like that. I need to treat it like a string, parse it, and before converting it to ip.Range type?

https://github.com/lxc/incus/pull/1201

winiciusallan avatar Sep 07 '24 15:09 winiciusallan

Sorry for the delay.

So yeah, you should be able to:

  • Get the OVN value
  • Split it on spaces
  • For each entry in there, SplitN(val, "..", 2)
  • If you get two slice members, then you're dealing with a range with slice member 1 being the start and slice member 2 being the end
  • You can then use a iprange.Range{Start: net.ParseIP(fields[0]), End: net.ParseIP(fields[1]} as the range. Though you may want to confirm that ParseIP doesn't return nil (invalid IP).

stgraber avatar Sep 11 '24 05:09 stgraber

Sorry for the delay in responding.

Now I can get the OVN range value, but somewhat I need to do the reversed logic. So if I have 192.168.15.5,192.168.15.15, and considering the start being the first member of slice, then I need to put in excluded IPs 192.168.15.1..{start - 1}?

winiciusallan avatar Sep 21 '24 20:09 winiciusallan

Yeah, given 192.168.15.1/24 as the network and a DHCP range of 192.168.15.5-192.168.15.15, you'd end up with an exclude_ips containing:

  • 192.168.15.1 (gateway)
  • 192.168.15.254 (last IP)
  • 192.168.15.2..192.168.15.4 (range leading to DHCP)
  • 192.168.15.16..192.168.15.253 (range following DHCP)

stgraber avatar Sep 22 '24 19:09 stgraber

hi, I'm unassigning this issue due to having no time to work on this. I appreciate the help and I'll pick another issue soon to contribute to the project

@jonatas-lima opened a PR.

winiciusallan avatar Oct 28 '24 14:10 winiciusallan

Hi, @stgraber, glad to contribute to incus!

https://github.com/lxc/incus/pull/1341

jonatas-lima avatar Oct 28 '24 14:10 jonatas-lima