From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id D1EDF9884F for ; Mon, 13 Nov 2023 11:05:03 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id F22AD10A8E for ; Mon, 13 Nov 2023 11:04:39 +0100 (CET) Received: from bastionodiso.odiso.net (bastionodiso.odiso.net [IPv6:2a0a:1580:2000::2d]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS for ; Mon, 13 Nov 2023 11:04:34 +0100 (CET) Received: from kvmformation3.odiso.net (formationkvm3.odiso.net [10.3.94.12]) by bastionodiso.odiso.net (Postfix) with ESMTP id 312897B29; Mon, 13 Nov 2023 11:04:22 +0100 (CET) Received: by kvmformation3.odiso.net (Postfix, from userid 0) id 2FE1613AB34; Mon, 13 Nov 2023 11:04:22 +0100 (CET) From: Alexandre Derumier To: pve-devel@lists.proxmox.com Date: Mon, 13 Nov 2023 11:04:14 +0100 Message-Id: <20231113100419.3317478-11-aderumier@odiso.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231113100419.3317478-1-aderumier@odiso.com> References: <20231113100419.3317478-1-aderumier@odiso.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.020 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy HEADER_FROM_DIFFERENT_DOMAINS 0.249 From and EnvelopeFrom 2nd level mail domains are different KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods SPF_NONE 0.001 SPF: sender does not publish an SPF Record T_SCC_BODY_TEXT_LINE -0.01 - T_SPF_HELO_TEMPERROR 0.01 SPF: test of HELO record failed (temperror) Subject: [pve-devel] [RFC pve-network 5/9] ipam : add get_ips_from_mac X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 13 Nov 2023 10:05:03 -0000 First look ip mac.db cache if not, lookup in ipam , and cache result in mac.db Signed-off-by: Alexandre Derumier --- src/PVE/Network/SDN/Dhcp.pm | 8 ++---- src/PVE/Network/SDN/Ipams.pm | 19 +++++++++++-- src/PVE/Network/SDN/Ipams/NetboxPlugin.pm | 25 +++++++++++++++++ src/PVE/Network/SDN/Ipams/PVEPlugin.pm | 32 ++++++++++++++++++++++ src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm | 29 ++++++++++++++++++++ src/PVE/Network/SDN/Ipams/Plugin.pm | 6 ++++ src/PVE/Network/SDN/Vnets.pm | 11 ++++++++ 7 files changed, 123 insertions(+), 7 deletions(-) diff --git a/src/PVE/Network/SDN/Dhcp.pm b/src/PVE/Network/SDN/Dhcp.pm index 1c32fec..b3c2751 100644 --- a/src/PVE/Network/SDN/Dhcp.pm +++ b/src/PVE/Network/SDN/Dhcp.pm @@ -6,7 +6,6 @@ use warnings; use PVE::Cluster qw(cfs_read_file); use PVE::Network::SDN; -use PVE::Network::SDN::Ipams::Plugin; use PVE::Network::SDN::SubnetPlugin; use PVE::Network::SDN::Dhcp qw(config); use PVE::Network::SDN::Subnets qw(sdn_subnets_config config); @@ -21,9 +20,8 @@ PVE::Network::SDN::Dhcp::Dnsmasq->register(); PVE::Network::SDN::Dhcp::Dnsmasq->init(); sub add_mapping { - my ($vmid, $vnetid, $mac, $ip) = @_; + my ($vnetid, $mac, $ip4, $ip6) = @_; - 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); @@ -32,13 +30,13 @@ sub add_mapping { return if !$dhcptype; my $dhcp_plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($dhcptype); - $dhcp_plugin->add_ip_mapping($zoneid, $mac, $ip); + $dhcp_plugin->add_ip_mapping($zoneid, $mac, $ip4) if $ip4; + $dhcp_plugin->add_ip_mapping($zoneid, $mac, $ip6) if $ip6; } sub remove_mapping { my ($vnetid, $mac) = @_; - 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); diff --git a/src/PVE/Network/SDN/Ipams.pm b/src/PVE/Network/SDN/Ipams.pm index a459441..926df90 100644 --- a/src/PVE/Network/SDN/Ipams.pm +++ b/src/PVE/Network/SDN/Ipams.pm @@ -98,8 +98,8 @@ sub config { } sub get_plugin_config { - my ($vnet) = @_; - my $ipamid = $vnet->{ipam}; + my ($zone) = @_; + my $ipamid = $zone->{ipam}; my $ipam_cfg = PVE::Network::SDN::Ipams::config(); return $ipam_cfg->{ids}->{$ipamid}; } @@ -124,5 +124,20 @@ sub complete_sdn_vnet { return $cmdname eq 'add' ? [] : [ PVE::Network::SDN::Vnets::sdn_ipams_ids($cfg) ]; } +sub get_ips_from_mac { + my ($mac, $zoneid, $zone) = @_; + + my $macdb = read_macdb(); + return ($macdb->{macs}->{$mac}->{ip4}, $macdb->{macs}->{$mac}->{ip6}) if $macdb->{macs}->{$mac}; + + my $plugin_config = get_plugin_config($zone); + my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($plugin_config->{type}); + ($macdb->{macs}->{$mac}->{ip4}, $macdb->{macs}->{$mac}->{ip6}) = $plugin->get_ips_from_mac($plugin_config, $mac, $zoneid); + + write_macdb($macdb); + + return ($macdb->{macs}->{$mac}->{ip4}, $macdb->{macs}->{$mac}->{ip6}); +} + 1; diff --git a/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm b/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm index 2099a7f..e6cc647 100644 --- a/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm +++ b/src/PVE/Network/SDN/Ipams/NetboxPlugin.pm @@ -198,6 +198,31 @@ sub del_ip { } } +sub get_ips_from_mac { + my ($class, $plugin_config, $mac, $zoneid) = @_; + + my $url = $plugin_config->{url}; + my $token = $plugin_config->{token}; + my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Authorization' => "token $token"]; + + my $ip4 = undef; + my $ip6 = undef; + + my $data = PVE::Network::SDN::api_request("GET", "$url/ipam/ip-addresses/?description__ic=$mac", $headers); + for my $ip (@{$data->{results}}) { + if ($ip->{family}->{value} == 4 && !$ip4) { + ($ip4, undef) = split(/\//, $ip->{address}); + } + + if ($ip->{family}->{value} == 6 && !$ip6) { + ($ip6, undef) = split(/\//, $ip->{address}); + } + } + + return ($ip4, $ip6); +} + + sub verify_api { my ($class, $plugin_config) = @_; diff --git a/src/PVE/Network/SDN/Ipams/PVEPlugin.pm b/src/PVE/Network/SDN/Ipams/PVEPlugin.pm index 5790715..0bc2b65 100644 --- a/src/PVE/Network/SDN/Ipams/PVEPlugin.pm +++ b/src/PVE/Network/SDN/Ipams/PVEPlugin.pm @@ -242,6 +242,38 @@ sub del_ip { die "$@" if $@; } +sub get_ips_from_mac { + my ($class, $plugin_config, $mac, $zoneid) = @_; + + #just in case, as this should already be cached in local macs.db + + my $ip4 = undef; + my $ip6 = undef; + + my $db = read_db(); + die "zone $zoneid don't exist in ipam db" if !$db->{zones}->{$zoneid}; + my $dbzone = $db->{zones}->{$zoneid}; + my $subnets = $dbzone->{subnets}; + + for my $subnet ( keys %$subnets) { + next if Net::IP::ip_is_ipv4($subnet) && $ip4; + next if $ip6; + my $ips = $subnets->{$subnet}->{ips}; + for my $ip (keys %$ips) { + my $ipobject = $ips->{$ip}; + if ($ipobject->{mac} && $ipobject->{mac} eq $mac) { + if (Net::IP::ip_is_ipv4($ip)) { + $ip4 = $ip; + } else { + $ip6 = $ip; + } + } + } + last if $ip4 && $ip6; + } + return ($ip4, $ip6); +} + #helpers sub read_db { diff --git a/src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm b/src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm index ad5286b..1b7b666 100644 --- a/src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm +++ b/src/PVE/Network/SDN/Ipams/PhpIpamPlugin.pm @@ -204,6 +204,35 @@ sub del_ip { } } +sub get_ips_from_mac { + my ($class, $plugin_config, $mac, $zoneid) = @_; + + + my $url = $plugin_config->{url}; + my $token = $plugin_config->{token}; + my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'Token' => $token]; + + my $ip4 = undef; + my $ip6 = undef; + + my $ips = PVE::Network::SDN::api_request("GET", "$url/addresses/search_mac/$mac", $headers); + + #fixme + die "parsing of result not yet implemented"; + + for my $ip (@$ips) { +# if ($ip->{family}->{value} == 4 && !$ip4) { +# ($ip4, undef) = split(/\//, $ip->{address}); +# } +# +# if ($ip->{family}->{value} == 6 && !$ip6) { +# ($ip6, undef) = split(/\//, $ip->{address}); +# } + } + + return ($ip4, $ip6); +} + sub verify_api { my ($class, $plugin_config) = @_; diff --git a/src/PVE/Network/SDN/Ipams/Plugin.pm b/src/PVE/Network/SDN/Ipams/Plugin.pm index 4d85b81..59c7e31 100644 --- a/src/PVE/Network/SDN/Ipams/Plugin.pm +++ b/src/PVE/Network/SDN/Ipams/Plugin.pm @@ -111,6 +111,12 @@ sub del_ip { die "please implement inside plugin"; } +sub get_ips_from_mac { + my ($class, $plugin_config, $mac, $zone) = @_; + + die "please implement inside plugin"; +} + sub on_update_hook { my ($class, $plugin_config) = @_; } diff --git a/src/PVE/Network/SDN/Vnets.pm b/src/PVE/Network/SDN/Vnets.pm index 76a6caf..9ba1a1e 100644 --- a/src/PVE/Network/SDN/Vnets.pm +++ b/src/PVE/Network/SDN/Vnets.pm @@ -155,6 +155,17 @@ sub del_cidr { PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname, $skipdns); } +sub get_ips_from_mac { + my ($vnetid, $mac) = @_; + my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid); + my $zoneid = $vnet->{zone}; + my $zone = PVE::Network::SDN::Zones::get_zone($zoneid); + + my $ipam = $zone->{ipam}; + return if !$ipam; + + return PVE::Network::SDN::Ipams::get_ips_from_mac($mac, $zoneid, $zone); +} 1; -- 2.39.2