all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Stefan Hanreich <s.hanreich@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH v4 pve-network 06/33] subnet: vnet: refactor IPAM related methods
Date: Fri, 17 Nov 2023 12:39:44 +0100	[thread overview]
Message-ID: <20231117114011.834002-7-s.hanreich@proxmox.com> (raw)
In-Reply-To: <20231117114011.834002-1-s.hanreich@proxmox.com>

Those methods are used by the DHCP plugins to attain the next free
IP address for a given DHCP range, as well as delete all entries with
a certain MAC address.

Co-Authored-By: Alexandre Derumier <aderumier@odiso.com>
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
 src/PVE/Network/SDN/SubnetPlugin.pm |   3 +-
 src/PVE/Network/SDN/Subnets.pm      |  50 ++++++++-----
 src/PVE/Network/SDN/Vnets.pm        | 105 +++++++++++++++++-----------
 3 files changed, 101 insertions(+), 57 deletions(-)

diff --git a/src/PVE/Network/SDN/SubnetPlugin.pm b/src/PVE/Network/SDN/SubnetPlugin.pm
index a4adae8..88933f5 100644
--- a/src/PVE/Network/SDN/SubnetPlugin.pm
+++ b/src/PVE/Network/SDN/SubnetPlugin.pm
@@ -172,8 +172,7 @@ sub on_update_hook {
 	}
         if(!$old_gateway || $gateway && $gateway ne $old_gateway) {
 	    my $hostname = "$vnetid-gw";
-	    my $description = "gateway";
-	    PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $gateway, $hostname, $mac, $description, 1);
+	    PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $gateway, $hostname, $mac, undef, 1);
 	}
 
 	#delete old gateway after update
diff --git a/src/PVE/Network/SDN/Subnets.pm b/src/PVE/Network/SDN/Subnets.pm
index 6e74de1..b05b3d9 100644
--- a/src/PVE/Network/SDN/Subnets.pm
+++ b/src/PVE/Network/SDN/Subnets.pm
@@ -98,14 +98,12 @@ sub get_subnet {
 }
 
 sub find_ip_subnet {
-    my ($ip, $mask, $subnets) = @_;
+    my ($ip, $subnets) = @_;
 
     my $subnet = undef;
     my $subnetid = undef;
 
     foreach my $id (sort keys %{$subnets}) {
-
-	next if $mask ne $subnets->{$id}->{mask};
 	my $cidr = $subnets->{$id}->{cidr};
 	my $subnet_matcher = subnet_matcher($cidr);
 	next if !$subnet_matcher->($ip);
@@ -207,12 +205,11 @@ sub del_subnet {
     $plugin->del_subnet($plugin_config, $subnetid, $subnet);
 }
 
-sub next_free_ip {
-    my ($zone, $subnetid, $subnet, $hostname, $mac, $description, $skipdns) = @_;
+sub add_next_free_ip {
+    my ($zone, $subnetid, $subnet, $hostname, $mac, $vmid, $skipdns, $dhcprange) = @_;
 
     my $cidr = undef;
     my $ip = undef;
-    $description = '' if !$description;
 
     my $ipamid = $zone->{ipam};
     my $dns = $zone->{dns};
@@ -230,10 +227,28 @@ sub next_free_ip {
 	my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
 	my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
 	eval {
-	    $cidr = $plugin->add_next_freeip($plugin_config, $subnetid, $subnet, $hostname, $mac, $description);
-	    ($ip, undef) = split(/\//, $cidr);
+	    if ($dhcprange) {
+		my $data = {
+		    mac => $mac,
+		    hostname => $hostname,
+		    vmid => $vmid,
+		};
+
+		my $dhcp_ranges = PVE::Network::SDN::Subnets::get_dhcp_ranges($subnet);
+
+		foreach my $range (@$dhcp_ranges) {
+		    $ip = $plugin->add_range_next_freeip($plugin_config, $subnet, $range, $data);
+	            next if !$ip;
+		}
+	    } else {
+		$ip = $plugin->add_next_freeip($plugin_config, $subnetid, $subnet, $hostname, $mac, $vmid);
+	    }
 	};
+
 	die $@ if $@;
+
+	eval { PVE::Network::SDN::Ipams::add_cache_mac_ip($mac, $ip); };
+	warn $@ if $@;
     }
 
     eval {
@@ -250,15 +265,15 @@ sub next_free_ip {
 	#rollback
 	my $err = $@;
 	eval {
-	    PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname)
+	    PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac)
 	};
 	die $err;
     }
-    return $cidr;
+    return $ip;
 }
 
 sub add_ip {
-    my ($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway, $skipdns) = @_;
+    my ($zone, $subnetid, $subnet, $ip, $hostname, $mac, $vmid, $is_gateway, $skipdns) = @_;
 
     return if !$subnet || !$ip; 
 
@@ -287,7 +302,7 @@ sub add_ip {
 	my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
 
 	eval {
-	    $plugin->add_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description, $is_gateway);
+	    $plugin->add_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $vmid, $is_gateway);
 	};
 	die $@ if $@;
     }
@@ -304,14 +319,14 @@ sub add_ip {
 	#rollback
 	my $err = $@;
 	eval {
-	    PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname)
+	    PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac)
 	};
 	die $err;
     }
 }
 
 sub update_ip {
-    my ($zone, $subnetid, $subnet, $ip, $hostname, $oldhostname, $mac, $description, $skipdns) = @_;
+    my ($zone, $subnetid, $subnet, $ip, $hostname, $oldhostname, $mac, $vmid, $skipdns) = @_;
 
     return if !$subnet || !$ip; 
 
@@ -338,7 +353,7 @@ sub update_ip {
 	my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
 	my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
 	eval {
-	    $plugin->update_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $description);
+	    $plugin->update_ip($plugin_config, $subnetid, $subnet, $ip, $hostname, $mac, $vmid);
 	};
 	die $@ if $@;
     }
@@ -358,7 +373,7 @@ sub update_ip {
 }
 
 sub del_ip {
-    my ($zone, $subnetid, $subnet, $ip, $hostname, $skipdns) = @_;
+    my ($zone, $subnetid, $subnet, $ip, $hostname, $mac, $skipdns) = @_;
 
     return if !$subnet || !$ip;
 
@@ -383,6 +398,9 @@ sub del_ip {
 	my $plugin_config = $ipam_cfg->{ids}->{$ipamid};
 	my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type});
 	$plugin->del_ip($plugin_config, $subnetid, $subnet, $ip);
+
+	eval { PVE::Network::SDN::Ipams::del_cache_mac_ip($mac, $ip); };
+	warn $@ if $@;
     }
 
     eval {
diff --git a/src/PVE/Network/SDN/Vnets.pm b/src/PVE/Network/SDN/Vnets.pm
index 39bdda0..4b3276e 100644
--- a/src/PVE/Network/SDN/Vnets.pm
+++ b/src/PVE/Network/SDN/Vnets.pm
@@ -80,81 +80,108 @@ sub get_subnets {
     return $subnets;
 }
 
-sub get_subnet_from_vnet_cidr {
-    my ($vnetid, $cidr) = @_;
+sub get_subnet_from_vnet_ip {
+    my ($vnetid, $ip) = @_;
 
     my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid, 1);
     my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
     my $zoneid = $vnet->{zone};
     my $zone = PVE::Network::SDN::Zones::get_zone($zoneid);
 
-    my ($ip, $mask) = split(/\//, $cidr);
-    die "ip address is not in cidr format" if !$mask;
-
-    my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, $mask, $subnets);
+    my ($subnetid, $subnet) = PVE::Network::SDN::Subnets::find_ip_subnet($ip, $subnets);
 
     return ($zone, $subnetid, $subnet, $ip);
 }
 
-sub get_next_free_cidr {
-    my ($vnetid, $hostname, $mac, $description, $ipversion, $skipdns) = @_;
+sub add_next_free_cidr {
+    my ($vnetid, $hostname, $mac, $vmid, $skipdns, $dhcprange) = @_;
 
     my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
+    return if !$vnet;
+
     my $zoneid = $vnet->{zone};
     my $zone = PVE::Network::SDN::Zones::get_zone($zoneid);
 
-    return if !$zone->{ipam};
+    return if !$zone->{ipam} || !$zone->{dhcp};
 
-    $ipversion = 4 if !$ipversion;
     my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid, 1);
-    my $ip = undef;
-    my $subnetcount = 0;
-
-    foreach my $subnetid (sort keys %{$subnets}) {
-        my $subnet = $subnets->{$subnetid};
-	my $network = $subnet->{network};
-
-	next if $ipversion != Net::IP::ip_get_version($network);
-	$subnetcount++;
 
-	eval {
-	    $ip = PVE::Network::SDN::Subnets::next_free_ip($zone, $subnetid, $subnet, $hostname, $mac, $description, $skipdns);
-	};
-	warn $@ if $@;
-	last if $ip;
+    my $ips = {};
+
+    my @ipversions = qw/ 4 6 /;
+    for my $ipversion (@ipversions) {
+	my $ip = undef;
+	my $subnetcount = 0;
+	foreach my $subnetid (sort keys %{$subnets}) {
+	    my $subnet = $subnets->{$subnetid};
+	    my $network = $subnet->{network};
+
+	    next if Net::IP::ip_get_version($network) != $ipversion || $ips->{$ipversion};
+	    $subnetcount++;
+
+	    eval {
+		$ip = PVE::Network::SDN::Subnets::add_next_free_ip($zone, $subnetid, $subnet, $hostname, $mac, $vmid, $skipdns, $dhcprange);
+	    };
+	    die $@ if $@;
+
+            if ($ip) {
+		$ips->{$ipversion} = $ip;
+		last;
+	    }
+	}
+	die "can't find any free ip" if !$ip && $subnetcount > 0;
     }
-    die "can't find any free ip" if !$ip && $subnetcount > 0;
-
-    return $ip;
 }
 
-sub add_cidr {
-    my ($vnetid, $cidr, $hostname, $mac, $description, $skipdns) = @_;
+sub add_ip {
+    my ($vnetid, $ip, $hostname, $mac, $vmid, $skipdns) = @_;
 
     return if !$vnetid;
     
-    my ($zone, $subnetid, $subnet, $ip) = PVE::Network::SDN::Vnets::get_subnet_from_vnet_cidr($vnetid, $cidr);
-    PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description, undef, $skipdns);
+    my ($zone, $subnetid, $subnet) = PVE::Network::SDN::Vnets::get_subnet_from_vnet_ip($vnetid, $ip);
+    PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $vmid, undef, $skipdns);
 }
 
-sub update_cidr {
-    my ($vnetid, $cidr, $hostname, $oldhostname, $mac, $description, $skipdns) = @_;
+sub update_ip {
+    my ($vnetid, $ip, $hostname, $oldhostname, $mac, $vmid, $skipdns) = @_;
 
     return if !$vnetid;
 
-    my ($zone, $subnetid, $subnet, $ip) = PVE::Network::SDN::Vnets::get_subnet_from_vnet_cidr($vnetid, $cidr);
-    PVE::Network::SDN::Subnets::update_ip($zone, $subnetid, $subnet, $ip, $hostname, $oldhostname, $mac, $description, $skipdns);
+    my ($zone, $subnetid, $subnet) = PVE::Network::SDN::Vnets::get_subnet_from_vnet_ip($vnetid, $ip);
+    PVE::Network::SDN::Subnets::update_ip($zone, $subnetid, $subnet, $ip, $hostname, $oldhostname, $mac, $vmid, $skipdns);
 }
 
-sub del_cidr {
-    my ($vnetid, $cidr, $hostname, $skipdns) = @_;
+sub del_ip {
+    my ($vnetid, $ip, $hostname, $mac, $skipdns) = @_;
 
     return if !$vnetid;
 
-    my ($zone, $subnetid, $subnet, $ip) = PVE::Network::SDN::Vnets::get_subnet_from_vnet_cidr($vnetid, $cidr);
-    PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname, $skipdns);
+    my ($zone, $subnetid, $subnet) = PVE::Network::SDN::Vnets::get_subnet_from_vnet_ip($vnetid, $ip);
+    PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $skipdns);
+}
+
+sub get_ips_from_mac {
+    my ($vnetid, $mac) = @_;
+
+    my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
+    return if !$vnet;
+
+    my $zoneid = $vnet->{zone};
+    my $zone = PVE::Network::SDN::Zones::get_zone($zoneid);
+
+    return if !$zone->{ipam} || !$zone->{dhcp};
+
+    return PVE::Network::SDN::Ipams::get_ips_from_mac($mac, $zoneid, $zone);
 }
 
+sub del_ips_from_mac {
+    my ($vnetid, $mac, $hostname) = @_;
 
+    my ($ip4, $ip6) = PVE::Network::SDN::Vnets::get_ips_from_mac($vnetid, $mac);
+    PVE::Network::SDN::Vnets::del_ip($vnetid, $ip4, $hostname, $mac) if $ip4;
+    PVE::Network::SDN::Vnets::del_ip($vnetid, $ip6, $hostname, $mac) if $ip6;
+
+    return ($ip4, $ip6);
+}
 
 1;
-- 
2.39.2




  parent reply	other threads:[~2023-11-17 11:40 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-17 11:39 [pve-devel] [PATCH v4 cluster/network/manager/qemu-server/container/docs 00/33] Add support for DHCP servers to SDN Stefan Hanreich
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-cluster 01/33] add priv/macs.db Stefan Hanreich
2023-11-17 13:54   ` [pve-devel] applied: " Thomas Lamprecht
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-network 02/33] sdn: preparations for DHCP plugin Stefan Hanreich
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-network 03/33] subnet: add dhcp options Stefan Hanreich
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-network 04/33] sdn: zone: add dhcp option Stefan Hanreich
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-network 05/33] ipam: plugins: preparations for DHCP Stefan Hanreich
2023-11-17 11:39 ` Stefan Hanreich [this message]
2023-11-17 14:13   ` [pve-devel] [PATCH v4 pve-network 06/33] subnet: vnet: refactor IPAM related methods Stefan Lendl
2023-11-17 15:12     ` Stefan Hanreich
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-network 07/33] dhcp: add abstract class for DHCP plugins Stefan Hanreich
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-network 08/33] sdn: dhcp: add dnsmasq plugin Stefan Hanreich
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-network 09/33] sdn: dhcp: add helper for creating DHCP leases Stefan Hanreich
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-network 10/33] api: add endpoints for managing PVE IPAM Stefan Hanreich
2023-11-18 16:27   ` Thomas Lamprecht
2023-11-20 10:55     ` Stefan Hanreich
2023-11-20 12:28       ` DERUMIER, Alexandre
2023-11-20 12:34         ` Stefan Hanreich
2023-11-20 12:50           ` Stefan Hanreich
2023-11-20 16:25           ` DERUMIER, Alexandre
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-network 11/33] api: subnet: add dhcp ranges Stefan Hanreich
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-network 12/33] api: zone: add dhcp option Stefan Hanreich
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-network 13/33] dhcp: regenerate config for DHCP plugins on applying configuration Stefan Hanreich
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-network 14/33] sdn: fix tests Stefan Hanreich
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-network 15/33] sdn: fix subnets && netbox ipam tests Stefan Hanreich
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-network 16/33] add add_dhcp_mapping Stefan Hanreich
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-manager 17/33] sdn: regenerate DHCP config on reload Stefan Hanreich
2023-11-21 21:15   ` [pve-devel] applied: " Thomas Lamprecht
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-manager 18/33] sdn: add DHCP option to Zone dialogue Stefan Hanreich
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-manager 19/33] sdn: subnet: add panel for editing dhcp ranges Stefan Hanreich
2023-11-20 13:20   ` Dominik Csapak
2023-11-17 11:39 ` [pve-devel] [PATCH v4 pve-manager 20/33] sdn: ipam: add ipam panel Stefan Hanreich
2023-11-17 15:04   ` DERUMIER, Alexandre
2023-11-17 15:15     ` Stefan Hanreich
2023-11-18 14:25       ` DERUMIER, Alexandre
2023-11-20 13:44   ` Dominik Csapak
2023-11-17 11:39 ` [pve-devel] [PATCH v4 qemu-server 21/33] vmnic add|remove : add|del ip in ipam Stefan Hanreich
2023-11-21 13:53   ` [pve-devel] applied-series: " Wolfgang Bumiller
2023-11-17 11:40 ` [pve-devel] [PATCH v4 qemu-server 22/33] vm_start : vm-network-scripts: add_dhcp_reservation Stefan Hanreich
2023-11-17 11:40 ` [pve-devel] [PATCH v4 qemu-server 23/33] api2: create|restore|clone: add_free_ip Stefan Hanreich
2023-11-17 11:40 ` [pve-devel] [PATCH v4 qemu-server 24/33] vm_destroy: delete ip from ipam Stefan Hanreich
2023-11-17 11:40 ` [pve-devel] [PATCH v4 qemu-server 25/33] nic hotplug: add_dhcp_mapping Stefan Hanreich
2023-11-17 11:40 ` [pve-devel] [PATCH v4 qemu-server 26/33] nic online bridge/vlan change: link disconnect/reconnect Stefan Hanreich
2023-11-17 11:40 ` [pve-devel] [PATCH v4 pve-container 27/33] nic hotplug : add|del ips in ipam Stefan Hanreich
2023-11-21 13:47   ` [pve-devel] applied-series: " Wolfgang Bumiller
2023-11-17 11:40 ` [pve-devel] [PATCH v4 pve-container 28/33] vm_destroy: remove ips from ipam for all interfaces Stefan Hanreich
2023-11-17 11:40 ` [pve-devel] [PATCH v4 pve-container 29/33] vm_create|restore: create ips in ipam Stefan Hanreich
2023-11-17 11:40 ` [pve-devel] [PATCH v4 pve-container 30/33] vm_clone : create ips in ipams Stefan Hanreich
2023-11-17 11:40 ` [pve-devel] [PATCH v4 pve-container 31/33] vm_apply_pending: add|del ips from ipam for offline changes Stefan Hanreich
2023-11-17 11:40 ` [pve-devel] [PATCH v4 pve-container 32/33] lxc-pve-prestart-hook : add_dhcp_mapping Stefan Hanreich
2023-11-17 11:40 ` [pve-devel] [PATCH v4 pve-docs 33/33] sdn: dhcp: Add documentation for DHCP Stefan Hanreich
2023-11-21 19:03   ` [pve-devel] applied: " Thomas Lamprecht
2023-11-17 15:47 ` [pve-devel] [PATCH v4 cluster/network/manager/qemu-server/container/docs 00/33] Add support for DHCP servers to SDN DERUMIER, Alexandre
2023-11-17 16:05   ` Stefan Hanreich
2023-11-17 16:07     ` Stefan Hanreich
2023-11-17 16:09     ` DERUMIER, Alexandre
2023-11-17 20:44       ` DERUMIER, Alexandre
2023-11-21 11:23   ` Stefan Lendl
2023-11-21 13:02     ` DERUMIER, Alexandre
2023-11-21 13:25     ` DERUMIER, Alexandre
2023-11-21 13:28     ` DERUMIER, Alexandre
2023-11-21 16:34       ` Stefan Lendl
2023-11-21 18:15         ` DERUMIER, Alexandre
2023-11-22  8:06         ` DERUMIER, Alexandre
2023-11-18 14:38 ` DERUMIER, Alexandre
2023-11-20 16:42 ` Thomas Lamprecht

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231117114011.834002-7-s.hanreich@proxmox.com \
    --to=s.hanreich@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal