[pve-devel] [RFC pve-network 4/9] ipam : add macs.db for fast mac lookup

Alexandre Derumier aderumier at odiso.com
Mon Nov 13 11:04:13 CET 2023


Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
 src/PVE/Network/SDN/Ipams.pm           | 61 +++++++++++++++++++++++++-
 src/PVE/Network/SDN/Ipams/PVEPlugin.pm |  4 +-
 src/PVE/Network/SDN/Subnets.pm         |  8 +++-
 src/test/run_test_subnets.pl           |  6 +++
 4 files changed, 75 insertions(+), 4 deletions(-)

diff --git a/src/PVE/Network/SDN/Ipams.pm b/src/PVE/Network/SDN/Ipams.pm
index e8a4b0b..a459441 100644
--- a/src/PVE/Network/SDN/Ipams.pm
+++ b/src/PVE/Network/SDN/Ipams.pm
@@ -4,9 +4,10 @@ use strict;
 use warnings;
 
 use JSON;
+use Net::IP;
 
 use PVE::Tools qw(extract_param dir_glob_regex run_command);
-use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_lock_file);
+use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
 use PVE::Network;
 
 use PVE::Network::SDN::Ipams::PVEPlugin;
@@ -19,6 +20,64 @@ PVE::Network::SDN::Ipams::NetboxPlugin->register();
 PVE::Network::SDN::Ipams::PhpIpamPlugin->register();
 PVE::Network::SDN::Ipams::Plugin->init();
 
+my $macdb_filename = 'priv/macs.db';
+
+cfs_register_file($macdb_filename, \&json_reader, \&json_writer);
+
+sub json_reader {
+    my ($filename, $data) = @_;
+
+    return defined($data) && length($data) > 0 ? decode_json($data) : {};
+}
+
+sub json_writer {
+    my ($filename, $data) = @_;
+
+    return encode_json($data);
+}
+
+sub read_macdb {
+    my () = @_;
+
+    return cfs_read_file($macdb_filename);
+}
+
+sub write_macdb {
+    my ($data) = @_;
+
+    cfs_write_file($macdb_filename, $data);
+}
+
+sub add_cache_mac_ip {
+    my ($mac, $ip) = @_;
+
+    cfs_lock_file($macdb_filename, undef, sub {
+	my $db = read_macdb();
+	if (Net::IP::ip_is_ipv4($ip)) {
+	    $db->{macs}->{$mac}->{ip4} = $ip;
+	} else {
+	    $db->{macs}->{$mac}->{ip6} = $ip;
+	}
+	write_macdb($db);
+    });
+    warn "$@" if $@;
+}
+
+sub del_cache_mac_ip {
+    my ($mac, $ip) = @_;
+
+    cfs_lock_file($macdb_filename, undef, sub {
+	my $db = read_macdb();
+	if (Net::IP::ip_is_ipv4($ip)) {
+	    delete $db->{macs}->{$mac}->{ip4};
+	} else {
+	    delete $db->{macs}->{$mac}->{ip6};
+	}
+        delete $db->{macs}->{$mac} if !defined($db->{macs}->{$mac}->{ip4}) && !defined($db->{macs}->{$mac}->{ip6});
+	write_macdb($db);
+    });
+    warn "$@" if $@;
+}
 
 sub sdn_ipams_config {
     my ($cfg, $id, $noerr) = @_;
diff --git a/src/PVE/Network/SDN/Ipams/PVEPlugin.pm b/src/PVE/Network/SDN/Ipams/PVEPlugin.pm
index 37b47e4..5790715 100644
--- a/src/PVE/Network/SDN/Ipams/PVEPlugin.pm
+++ b/src/PVE/Network/SDN/Ipams/PVEPlugin.pm
@@ -173,13 +173,14 @@ sub add_range_next_freeip {
 
 	my $ip = new Net::IP ("$range->{'start-address'} - $range->{'end-address'}")
 	    or die "Invalid IP address(es) in Range!\n";
+	my $mac = $data->{mac};
 
 	do {
 	    my $ip_address = $ip->ip();
 	    if (!$dbsubnet->{ips}->{$ip_address}) {
 		$dbsubnet->{ips}->{$ip_address} = $data;
 		write_db($db);
-
+		
 		return $ip_address;
 	    }
 	} while (++$ip);
@@ -236,7 +237,6 @@ sub del_ip {
 
 	die "IP '$ip' does not exist in IPAM DB\n" if !defined($dbsubnet->{ips}->{$ip});
 	delete $dbsubnet->{ips}->{$ip};
-
 	write_db($db);
     });
     die "$@" if $@;
diff --git a/src/PVE/Network/SDN/Subnets.pm b/src/PVE/Network/SDN/Subnets.pm
index 9f953a6..b2125a1 100644
--- a/src/PVE/Network/SDN/Subnets.pm
+++ b/src/PVE/Network/SDN/Subnets.pm
@@ -240,6 +240,9 @@ sub add_next_free_ip {
 	};
 
 	die $@ if $@;
+
+	eval { PVE::Network::SDN::Ipams::add_cache_mac_ip($mac, $ip); };
+	warn $@ if $@;
     }
 
     eval {
@@ -364,7 +367,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;
 
@@ -389,6 +392,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/test/run_test_subnets.pl b/src/test/run_test_subnets.pl
index 9692f4c..c98359a 100755
--- a/src/test/run_test_subnets.pl
+++ b/src/test/run_test_subnets.pl
@@ -109,6 +109,12 @@ foreach my $path (@plugins) {
 	    my $ipam_config = read_sdn_config ("$path/ipam_config");
 	    return $ipam_config;
 	},
+	add_cache_mac_ip => sub {
+	    return;
+	},
+	del_cache_mac_ip => sub {
+	    return;
+	}
     );
 
     ## add_subnet
-- 
2.39.2





More information about the pve-devel mailing list