[Kea-users] Unable To Support Multiple Subnets via DHCP Relay

Tomek Mrugalski tomasz at isc.org
Fri Dec 23 11:49:05 UTC 2016


Hi,
Apologies for not joining that discussion earlier. Been busy with the
parsers rewrite recently.

The shared network mechanism available in dhcpd (using one subnet and
then switching to the next one once the first one is full) is not
supported yet in Kea. For some cases we can use client classification
and restrict access to subnets to selected class, but that will only get
you so far.

There's a good reason why we don't support this capability yet. That's
because shared networks significantly alters the whole logic of the DHCP
server. If it was simple to implement, we would have done that long time
ago.

The discussion below is pretty complex stuff. It is doable, but it's
tricky. This is getting into some deep parts of how Kea operates, so
apologies to people who don't expect this kind of stuff on kea-users. It
would be probably better for kea-dev list, but this thread started
gently and just escalated quickly... :)

W dniu 22.12.2016 o 14:42, Igor Smitran pisze:
> In order to solve this problem:
> 
> Is one able to create something like:
> 
> 1. create subnet4_select hook
>  Inside hook based on some conditions we set NEXT_STEP_DROP/SKIP
>  subnet will not be selected
Using NEXT_STEP_SKIP here won't help at all. This will tell Kea to not
select a subnet at all. In most cases the packet will be dropped as a
result. There are some border cases when the packet processing could
still continue (e.g. sending some global information in response to
DHCPINFORM), but this will not give you anything in your case.

Using NEXT_STEP_DROP is not supported in this hook.

What you can do here is to set a different subnet. Kea will use whatever
subnet the hook specified in subnet4 parameter. By default that's the
subnet Kea selected in the first place.

The tricky part is to decide which subnet to select out of those.
There are couple possible ways to solve this problem. The idea to call
pickAddress is one approach. It would do allocation in the subnet
selection phase, but I don't think mixing the steps is avoidable.

Another thing to consider here is to use statistics. You can retrieve
subnet[id].assigned-addresses and compare it with
subnet[id].total-addresses. If those match, then this subnet is full and
you need to pick the next subnet. This is slightly oversimplified, as
you should also take declined addresses into consideration. But let's
forget about them for now. This statistics check is definitely much
faster than attempt to pick a lease.

> 2. create lease4_select hook
>  subnet is not selected yet, we use getCfgSubnets4()->getAll(); and now
> we have all defined subnets
>  then we pick first subnet that matches relayip
>  we call Allocator and pickaddress. in case we don't get any address we
> pick another subnet and repeat
>  in case we go through all subnets/pools and don't get any address we
> decide to DROP packet because we don't have any free lease to handout
This would almost work. But there's one problem with it. The subnet has
already been selected at the time lease4_select is called. So the new
lease will be created with the subnet_id of previously selected subnet.
You can probably override it in a hook, but then the allocation engine
would use whatever the subnet was originally selected to assign options.
You could almost get away with it by specifying the same option values
in all subnets, so it wouldn't matter. Except the router option... it
has to match the actual subnet. Otherwise your clients won't know how to
reach their default gateway.

So the solution will likely need to be slightly more complex than that.
You would select the subnet as you described, but you would do that in
select4_subnet and depending on your decision, your hook would tell Kea
to use that specific subnet. Now, to not repeat the costly allocation
procedure twice, you can store the lease (or just the IP address
selected) in hook context.

Then in another hook installed on lease4_select, you'd retrieve that
information from the context and tell Kea to use that lease.

This should work for new clients, but there's another problem to solve:
returning clients. The trick here is that returning clients will need to
be assigned the same subnet as before. Fortunately, that's easy to
do. When the subnet4_select is caled, query4 contains the source packet.
You need to look at its ciaddr field. If this is set, that means the
client already has an address. If it has one, you can select a subnet
based on that.

Sounds complicated? Well, did I mention there's a reason why it was not
yet implemented? I wasn't making that up.

> Some help from Kea developers would be very appreciated :)

One day we will implement shared subnets in the Kea code. I (or any
other Kea engineer) haven't done a proper design for this yet, but I
have some ideas. Please treat them with a grain of salt.

Design 1: Kea code currently checks that the pools really belong to the
subnet in which they're defined. In non-shared subnet deployment, that's
a very useful sanity check that catches misconfiguration. With shared
subnets enabled, we could simply disable that check and allow pools to
belong to different classes. Kea would select subnet normally and then
start allocating from the next pool within this subnet once the first
pool is fully allocated.

There are places in the code that try to select subnet based on the IP
address. Those would have to be augmented slightly.

One thing to address here is how to assign different options (in
particular routers option) to clients using different pools. We already
have capability to assign different options for each IPv6 pool. Similar
capability would have to be developed for IPv4.

Design 2: Kea allows specifying subnet_id explicitly. It rejects a
configuration that has duplicate subnet_ids. In this approach, we would
allow those ids to be duplicate. When a duplicate is found, those would
be treated as a shared subnet. This approach would require some sort of
a connection between subnets. A pointer to shared_subnet structure that
lists all the subnets perhaps? The allocation engine would have to be
augmented to not give up when completed through the current subnet, but
rather check if this subnet is part of a shared subnet. If it is, then
hop to the next subnet and try to allocated somewhere from that.

In any case, there are many tricky cases, like new clients coming in,
returning clients renewing, having an address not used, but reserved for
client A when client B comes in, sysadmin adding reservation for client
A while the address is being used by client B etc.

Ok, that's it. These are my thoughts on the matter. If you were hoping
for a simple trick to make it magically work - I'm sorry, I'm not aware
of any.

Finally, there are couple of non-technical things that may or may not be
useful here. We're currently working on 1.2, which is fully scoped and
it's rather unlikely we would add any new features to it. However, the
discussion for 1.3 is yet to be started. I presume you'd like shared
subnet to be implemented in 1.3, but the same is true for lots of other
missing features. Here's the caveat. Kea is open source, but we need to
fund its development somehow. Therefore we tend to pick the features
that give the highest chance of getting support or development contracts
signed. As such, saying "I'd like shared subnets in 1.3" is nice, but
"I'm willing to sign a support contract with you if you develop shared
subnets" is better. That is generally true for any not yet developed
feature.

Hope that helps,
Tomek Mrugalski
ISC




More information about the Kea-users mailing list