1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-25 06:03:36 +03:00
one/src/vnm/AddressRange.cc
Ruben S. Montero 03b2b42024
F #3503: Support for overcommitment & VM pinning. Number of VMs per
physical thread can be set for each host with VMS_THREAD
2019-09-22 00:31:08 +02:00

2071 lines
48 KiB
C++

/* -------------------------------------------------------------------------- */
/* Copyright 2002-2019, OpenNebula Project, OpenNebula Systems */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "AddressRange.h"
#include "Attribute.h"
#include "VirtualNetworkPool.h"
#include "NebulaLog.h"
#include "NebulaUtil.h"
#include "Nebula.h"
#include <arpa/inet.h>
#include <algorithm>
using namespace std;
/* ************************************************************************** */
/* ************************************************************************** */
string AddressRange::type_to_str(AddressType ob)
{
switch (ob)
{
case ETHER: return "ETHER" ;
case IP4: return "IP4" ;
case IP6: return "IP6" ;
case IP6_STATIC: return "IP6_STATIC" ;
case IP4_6: return "IP4_6" ;
case IP4_6_STATIC: return "IP4_6_STATIC";
default: return "";
}
};
/* -------------------------------------------------------------------------- */
AddressRange::AddressType AddressRange::str_to_type(string& str_type)
{
one_util::toupper(str_type);
if (str_type == "ETHER")
{
return ETHER;
}
else if (str_type == "IP4")
{
return IP4;
}
else if (str_type == "IP6")
{
return IP6;
}
else if (str_type == "IP4_6")
{
return IP4_6;
}
else if (str_type == "IP4_6_STATIC")
{
return IP4_6_STATIC;
}
else if (str_type == "IP6_STATIC")
{
return IP6_STATIC;
}
else
{
return NONE;
}
}
/* ************************************************************************** */
/* ************************************************************************** */
int AddressRange::init_ipv4(string& error_msg)
{
if (!is_ipv4())
{
attr->remove("IP");
return 0;
}
string value = attr->vector_value("IP");
if (value.empty() || ip_to_i(value, ip) == -1)
{
error_msg = "Wrong or empty IP attribute";
return -1;
}
return 0;
}
/* -------------------------------------------------------------------------- */
int AddressRange::init_ipv6(string& error_msg)
{
if (!is_ipv6())
{
attr->remove("GLOBAL_PREFIX");
attr->remove("ULA_PREFIX");
return 0;
}
string value = attr->vector_value("GLOBAL_PREFIX");
if (prefix6_to_i(value, global6) != 0 )
{
error_msg = "Wrong format for IP6 global address prefix";
return -1;
}
value = attr->vector_value("ULA_PREFIX");
if (prefix6_to_i(value, ula6) != 0 )
{
error_msg = "Wrong format for IP6 unique local address prefix";
return -1;
}
return 0;
}
/* -------------------------------------------------------------------------- */
int AddressRange::init_ipv6_static(string& error_msg)
{
if (!is_ipv6_static())
{
attr->remove("IP6");
return 0;
}
string value = attr->vector_value("IP6");
if (value.empty() || ip6_to_i(value, ip6) == -1)
{
error_msg = "Wrong or empty IP6 attribute";
return -1;
}
int pl;
if ( attr->vector_value("PREFIX_LENGTH", pl) != 0 )
{
error_msg = "Wrong or empty PREFIX_LENGTH";
return -1;
}
return 0;
}
/* -------------------------------------------------------------------------- */
int AddressRange::init_mac(string& error_msg)
{
string value = attr->vector_value("MAC");
if (value.empty())
{
mac[1] = VirtualNetworkPool::mac_prefix();
if ( is_ipv4() )
{
mac[0] = ip;
}
else
{
mac[0] = one_util::random<uint32_t>() & 0xFFFFFFFF;
}
set_mac(0, attr);
}
else
{
if (mac_to_i(value, mac) == -1)
{
error_msg = "Wrong format for MAC attribute";
return -1;
};
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::from_attr(VectorAttribute *vattr, string& error_msg)
{
string value;
attr = vattr;
/* ------------------------- AR Type & Size ---------------------------- */
value = vattr->vector_value("TYPE");
type = str_to_type(value);
if (type == NONE)
{
error_msg = "Unknown or missing address range TYPE.";
return -1;
}
if ( vattr->vector_value("SIZE", size) != 0 || size <= 0 )
{
error_msg = "Wrong SIZE for address range";
return -1;
}
/* ---------------------- L3 & L2 start addresses ---------------------- */
if ( init_ipv4(error_msg) != 0 )
{
return -1;
}
if ( init_ipv6(error_msg) != 0 )
{
return -1;
}
if ( init_ipv6_static(error_msg) != 0 )
{
return -1;
}
if ( init_mac(error_msg) != 0 )
{
return -1;
}
/* ------------------------- Security Groups ---------------------------- */
value = vattr->vector_value("SECURITY_GROUPS");
if (value.empty())
{
security_groups.clear();
}
else
{
one_util::split_unique(value, ',', security_groups);
}
/* ------------------------ AR Internal Data ---------------------------- */
vattr->replace("AR_ID", id);
vattr->remove("ALLOCATED");
vattr->remove("USED_LEASES");
vattr->remove("LEASES");
vattr->remove("PARENT_NETWORK_AR_ID");
vattr->remove("PARENT_NETWORK");
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::update_attributes(
VectorAttribute * vup,
bool keep_restricted,
string& error_msg)
{
/* --------------- Do not allow to modify a reservation ------- */
int pid;
bool is_reservation = (get_attribute("PARENT_NETWORK_AR_ID", pid) == 0);
if (keep_restricted && restricted_set)
{
remove_restricted(vup);
}
/* --------------- Copy non-update attributes ----------------- */
vup->replace("TYPE", attr->vector_value("TYPE"));
vup->replace("MAC", attr->vector_value("MAC"));
string ipam_mad = attr->vector_value("IPAM_MAD");
if ( !ipam_mad.empty() )
{
vup->replace("IPAM_MAD", ipam_mad);
}
vup->replace("MAC", attr->vector_value("MAC"));
vup->remove("IP");
if (is_ipv4())
{
vup->replace("IP", attr->vector_value("IP"));
}
vup->remove("IP6");
if (is_ipv6_static())
{
vup->replace("IP6", attr->vector_value("IP6"));
}
/* ----------------- Remove internal attributes ----------------- */
vup->replace("AR_ID", attr->vector_value("AR_ID"));
vup->replace("ALLOCATED", attr->vector_value("ALLOCATED"));
vup->remove("USED_LEASES");
vup->remove("LEASES");
vup->remove("PARENT_NETWORK_AR_ID");
if (is_reservation)
{
vup->replace("PARENT_NETWORK_AR_ID",
attr->vector_value("PARENT_NETWORK_AR_ID"));
}
/* ------ Remove non-persistent attributes, generated in to_xml() ------ */
vup->remove("MAC_END");
vup->remove("IP_END");
vup->remove("IP6_END");
vup->remove("IP6_ULA");
vup->remove("IP6_ULA_END");
vup->remove("IP6_GLOBAL");
vup->remove("IP6_GLOBAL_END");
/* ----------------- restricted attributes ----------------- */
if (keep_restricted && restricted_set)
{
VectorAttribute va_aux(*attr);
remove_all_except_restricted(&va_aux);
vup->merge(&va_aux, true);
}
/* ----------------- update known attributes ----------------- */
unsigned int new_size;
if (vup->vector_value("SIZE", new_size) == 0)
{
if (is_reservation && new_size != size)
{
error_msg = "The SIZE of a reservation cannot be changed.";
return -1;
}
if (allocated.upper_bound(new_size-1) != allocated.end())
{
error_msg = "New SIZE cannot be applied. There are used leases"
" that would fall outside the range.";
return -1;
}
}
else
{
new_size = size;
}
size = new_size;
vup->replace("SIZE", size);
if ( is_ipv6_static() )
{
int new_pl;
if (vup->vector_value("PREFIX_LENGTH", new_pl) == -1 )
{
vup->replace("PREFIX_LENGTH", attr->vector_value("PREFIX_LENGTH"));
}
}
if ( is_ipv6() )
{
string new_global = vup->vector_value("GLOBAL_PREFIX");
if (prefix6_to_i(new_global, global6) != 0 )
{
error_msg = "Wrong format for IP6 global address prefix";
return -1;
}
string new_ula = vup->vector_value("ULA_PREFIX");
if (prefix6_to_i(new_ula, ula6) != 0 )
{
error_msg = "Wrong format for IP6 unique local address prefix";
return -1;
}
vup->replace("GLOBAL_PREFIX", new_global);
vup->replace("ULA_PREFIX", new_ula);
}
string value = vup->vector_value("SECURITY_GROUPS");
security_groups.clear();
if (!value.empty())
{
one_util::split_unique(value, ',', security_groups);
}
/* Replace with the new attributes */
attr->replace(vup->value());
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::from_vattr_db(VectorAttribute *vattr)
{
string value;
int rc = 0;
this->attr = vattr;
rc += vattr->vector_value("AR_ID", id);
value = vattr->vector_value("TYPE");
type = str_to_type(value);
rc += vattr->vector_value("SIZE", size);
rc += mac_to_i(vattr->vector_value("MAC"), mac);
if (is_ipv4())
{
rc += ip_to_i(vattr->vector_value("IP"), ip);
}
if (is_ipv6_static())
{
rc += ip6_to_i(vattr->vector_value("IP6"), ip6);
}
rc += prefix6_to_i(vattr->vector_value("GLOBAL_PREFIX"), global6);
rc += prefix6_to_i(vattr->vector_value("ULA_PREFIX"), ula6);
rc += attr_to_allocated(vattr->vector_value("ALLOCATED"));
value = vattr->vector_value("SECURITY_GROUPS");
security_groups.clear();
if (!value.empty())
{
one_util::split_unique(value, ',', security_groups);
}
if (type == NONE)
{
rc = -1;
}
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AddressRange::addr_to_xml(unsigned int index, unsigned int rsize,
ostringstream& oss) const
{
unsigned int new_mac[2];
string ip6_s;
new_mac[0] = mac[0] + index;
new_mac[1] = mac[1];
oss << "<ADDRESS>"
<< "<MAC>" << mac_to_s(new_mac) << "</MAC>";
if ( ip != 0 )
{
oss << "<IP>" << ip_to_s(ip + index) << "</IP>";
}
if (ula6[1] != 0 || ula6[0] != 0 )
{
oss << "<IP6_ULA>" << ip6_to_s(ula6, new_mac, ip6_s) << "</IP6_ULA>";
}
if (global6[1] != 0 || global6[0] != 0)
{
oss << "<IP6_GLOBAL>" << ip6_to_s(global6, new_mac, ip6_s)
<< "</IP6_GLOBAL>";
}
if ( ip6[0] != 0 || ip6[1] != 0 || ip6[2] != 0 || ip6[3] != 0 )
{
unsigned int ip_low[4];
ip_low[3] = ip6[3];
ip_low[2] = ip6[2];
ip_low[1] = ip6[1];
ip_low[0] = ip6[0] + index;
oss << "<IP6>" << ip6_to_s(ip_low, ip6_s) << "</IP6>";
}
oss << "<SIZE>" << rsize << "</SIZE>"
<< "</ADDRESS>";
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AddressRange::to_xml(ostringstream &oss) const
{
const map<string,string>& ar_attrs = attr->value();
map<string,string>::const_iterator it;
unsigned int mac_end[2];
oss << "<AR>";
for (it=ar_attrs.begin(); it != ar_attrs.end(); it++)
{
if ( it->first == "ALLOCATED" )
{
continue;
}
oss << "<" << it->first << ">"
<< one_util::escape_xml(it->second)
<< "</"<< it->first << ">";
}
mac_end[1] = mac[1];
mac_end[0] = (mac[0] + size - 1);
oss << "<MAC_END>" << one_util::escape_xml(mac_to_s(mac_end))<<"</MAC_END>";
if (is_ipv4())
{
string aux_st;
unsigned int ip_i;
aux_st = attr->vector_value("IP");
if (ip_to_i(aux_st, ip_i) == 0)
{
oss << "<IP_END>" << one_util::escape_xml(ip_to_s(ip_i + size - 1))
<< "</IP_END>";
}
}
if (is_ipv6())
{
string ip6_s;
if (ula6[1] != 0 || ula6[0] != 0 )
{
ip6_to_s(ula6, mac, ip6_s);
oss << "<IP6_ULA>" << one_util::escape_xml(ip6_s) << "</IP6_ULA>";
ip6_to_s(ula6, mac_end, ip6_s);
oss << "<IP6_ULA_END>" << one_util::escape_xml(ip6_s)
<< "</IP6_ULA_END>";
}
if (global6[1] != 0 || global6[0] != 0 )
{
ip6_to_s(global6, mac, ip6_s);
oss << "<IP6_GLOBAL>" << one_util::escape_xml(ip6_s)
<< "</IP6_GLOBAL>";
ip6_to_s(global6, mac_end, ip6_s);
oss << "<IP6_GLOBAL_END>" << one_util::escape_xml(ip6_s)
<< "</IP6_GLOBAL_END>";
}
}
if (is_ipv6_static())
{
string ip6_s;
unsigned int ip_low[4];
ip_low[3] = ip6[3];
ip_low[2] = ip6[2];
ip_low[1] = ip6[1];
ip_low[0] = ip6[0] + size - 1;
ip6_to_s(ip_low, ip6_s);
oss << "<IP6_END>" << one_util::escape_xml(ip6_s) << "</IP6_END>";
}
oss << "<USED_LEASES>" << get_used_addr() << "</USED_LEASES>";
oss << "</AR>";
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AddressRange::to_xml(ostringstream &oss, const vector<int>& vms,
const vector<int>& vns, const vector<int>& vrs) const
{
const map<string,string>& ar_attrs = attr->value();
map<string,string>::const_iterator it;
int rc;
unsigned int mac_end[2];
string aux_st;
bool all_vms = (vms.size() == 1 && vms[0] == -1);
bool all_vns = (vns.size() == 1 && vns[0] == -1);
bool all_vrs = (vrs.size() == 1 && vrs[0] == -1);
oss << "<AR>";
for (it=ar_attrs.begin(); it != ar_attrs.end(); it++)
{
if ( it->first == "ALLOCATED" )
{
continue;
}
oss << "<" << it->first << ">"
<< one_util::escape_xml(it->second)
<< "</"<< it->first << ">";
}
mac_end[1] = mac[1];
mac_end[0] = (mac[0] + size - 1);
oss << "<MAC_END>" << one_util::escape_xml(mac_to_s(mac_end))<<"</MAC_END>";
if (is_ipv4())
{
unsigned int ip_i;
string aux_st = attr->vector_value("IP");
rc = ip_to_i(aux_st, ip_i);
if (rc == 0)
{
oss << "<IP_END>" << one_util::escape_xml(ip_to_s(ip_i + size - 1))
<< "</IP_END>";
}
}
if (is_ipv6())
{
string ip6_s;
if (ula6[1] != 0 || ula6[0] != 0 ) /* Unique Local Address */
{
ip6_to_s(ula6, mac, ip6_s);
oss << "<IP6_ULA>" << one_util::escape_xml(ip6_s) << "</IP6_ULA>";
ip6_to_s(ula6, mac_end, ip6_s);
oss << "<IP6_ULA_END>" << one_util::escape_xml(ip6_s)
<< "</IP6_ULA_END>";
}
if (global6[1] != 0 || global6[0] != 0 ) /* Glocal Unicast */
{
ip6_to_s(global6, mac, ip6_s);
oss << "<IP6_GLOBAL>" << one_util::escape_xml(ip6_s)
<< "</IP6_GLOBAL>";
ip6_to_s(global6, mac_end, ip6_s);
oss << "<IP6_GLOBAL_END>" << one_util::escape_xml(ip6_s)
<< "</IP6_GLOBAL_END>";
}
}
if (is_ipv6_static())
{
string ip6_s;
unsigned int ip_low[4];
ip_low[3] = ip6[3];
ip_low[2] = ip6[2];
ip_low[1] = ip6[1];
ip_low[0] = ip6[0] + size - 1;
ip6_to_s(ip_low, ip6_s);
oss << "<IP6_END>" << one_util::escape_xml(ip6_s) << "</IP6_END>";
}
oss << "<USED_LEASES>" << get_used_addr() << "</USED_LEASES>";
if (allocated.empty())
{
oss << "<LEASES/>";
}
else
{
map<unsigned int, long long>::const_iterator it;
VectorAttribute lease("LEASE");
bool is_in;
oss << "<LEASES>";
for (it = allocated.begin(); it != allocated.end(); it++)
{
lease.clear();
is_in = false;
if (it->second & PoolObjectSQL::VM)
{
int vmid = it->second & 0x00000000FFFFFFFFLL;
if (all_vms || (find(vms.begin(),vms.end(),vmid) != vms.end()))
{
lease.replace("VM", vmid);
is_in = true;
}
}
else if (it->second & PoolObjectSQL::NET)
{
int vnid = it->second & 0x00000000FFFFFFFFLL;
if (all_vns || (find(vns.begin(),vns.end(),vnid) != vns.end()))
{
lease.replace("VNET", vnid);
is_in = true;
}
}
else if (it->second & PoolObjectSQL::VROUTER)
{
int oid = it->second & 0x00000000FFFFFFFFLL;
if (all_vrs || (find(vrs.begin(),vrs.end(),oid) != vrs.end()))
{
lease.replace("VROUTER", oid);
is_in = true;
}
}
if (!is_in)
{
continue;
}
set_mac(it->first, &lease);
if (is_ipv4())
{
set_ip(it->first, &lease);
}
if (is_ipv6())
{
set_ip6(it->first, &lease);
}
if (is_ipv6_static())
{
set_ip6_static(it->first, &lease);
}
lease.to_xml(oss);
}
oss << "</LEASES>";
}
oss << "</AR>";
}
/* ************************************************************************** */
/* ************************************************************************** */
int AddressRange::mac_to_i(string mac, unsigned int i_mac[]) const
{
istringstream iss;
size_t pos = 0;
int count = 0;
unsigned int tmp;
while ( (pos = mac.find(':')) != string::npos )
{
mac.replace(pos,1," ");
count++;
}
if (count != 5)
{
return -1;
}
iss.str(mac);
i_mac[1] = 0;
i_mac[0] = 0;
iss >> hex >> i_mac[1] >> ws >> hex >> tmp >> ws;
i_mac[1] <<= 8;
i_mac[1] += tmp;
for (int i=0;i<4;i++)
{
iss >> hex >> tmp >> ws;
i_mac[0] <<= 8;
i_mac[0] += tmp;
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string AddressRange::mac_to_s(const unsigned int i_mac[]) const
{
ostringstream oss;
unsigned int temp_byte;
for (int i=5;i>=0;i--)
{
if ( i < 4 )
{
temp_byte = i_mac[0];
temp_byte >>= i*8;
}
else
{
temp_byte = i_mac[1];
temp_byte >>= (i%4)*8;
}
temp_byte &= 255;
oss.width(2);
oss.fill('0');
oss << hex << temp_byte;
if(i!=0)
{
oss << ":";
}
}
return oss.str();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::ip_to_i(const string& _ip, unsigned int& i_ip) const
{
istringstream iss;
size_t pos=0;
int count = 0;
unsigned int tmp;
string ip = _ip;
if ( ip.find_first_not_of("0123456789.") != std::string::npos )
{
return -1;
}
while ( (pos = ip.find('.')) != string::npos )
{
ip.replace(pos,1," ");
count++;
}
if (count != 3)
{
return -1;
}
iss.str(ip);
i_ip = 0;
for (int i=0;i<4;i++)
{
iss >> dec >> tmp >> ws;
if ( tmp > 255 || iss.fail() )
{
return -1;
}
i_ip <<= 8;
i_ip += tmp;
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string AddressRange::ip_to_s(unsigned int i_ip) const
{
ostringstream oss;
unsigned int temp_byte;
for (int index=0;index<4;index++)
{
temp_byte = i_ip;
temp_byte >>= (24-index*8);
temp_byte &= 255;
oss << temp_byte;
if(index!=3)
{
oss << ".";
}
}
return oss.str();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::ip6_to_i(const string& _ip, unsigned int i_ip[]) const
{
struct in6_addr s6;
if (_ip.empty())
{
return -1;
}
int rc = inet_pton(AF_INET6, _ip.c_str(), &s6);
if ( rc != 1 )
{
return -1;
}
i_ip[3] = ntohl(s6.s6_addr32[0]);
i_ip[2] = ntohl(s6.s6_addr32[1]);
i_ip[1] = ntohl(s6.s6_addr32[2]);
i_ip[0] = ntohl(s6.s6_addr32[3]);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::prefix6_to_i(const string& prefix, unsigned int ip[]) const
{
struct in6_addr s6;
if (prefix.empty())
{
ip[1] = ip[0] = 0;
return 0;
}
int rc = inet_pton(AF_INET6, prefix.c_str(), &s6);
if ( rc != 1 )
{
return -1;
}
ip[1] = ntohl(s6.s6_addr32[0]);
ip[0] = ntohl(s6.s6_addr32[1]);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::ip6_to_s(const unsigned int prefix[],
const unsigned int mac[], string& ip6_s) const
{
unsigned int eui64[2];
unsigned int mlow = mac[0];
struct in6_addr ip6;
char dst[INET6_ADDRSTRLEN];
eui64[1] = ((mac[1]^0x0200)<<16) + ((mlow & 0xFF000000)>>16) + 0x000000FF;
eui64[0] = 4261412864 + (mlow & 0x00FFFFFF);
ip6.s6_addr32[2] = htonl(eui64[1]);
ip6.s6_addr32[3] = htonl(eui64[0]);
ip6.s6_addr32[0] = htonl(prefix[1]);
ip6.s6_addr32[1] = htonl(prefix[0]);
if ( inet_ntop(AF_INET6, &ip6, dst, INET6_ADDRSTRLEN) != 0 )
{
ip6_s = dst;
return 0;
}
return -1;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::ip6_to_s(const unsigned int ip6_i[], string& ip6_s) const
{
struct in6_addr ip6;
char dst[INET6_ADDRSTRLEN];
ip6.s6_addr32[3] = htonl(ip6_i[0]);
ip6.s6_addr32[2] = htonl(ip6_i[1]);
ip6.s6_addr32[1] = htonl(ip6_i[2]);
ip6.s6_addr32[0] = htonl(ip6_i[3]);
if ( inet_ntop(AF_INET6, &ip6, dst, INET6_ADDRSTRLEN) != 0 )
{
ip6_s = dst;
return 0;
}
return -1;
}
/* ************************************************************************** */
/* ************************************************************************** */
bool AddressRange::is_valid_mac(unsigned int& index, const string& mac_s,
bool check_free)
{
unsigned int mac_i[2];
if (mac_to_i(mac_s, mac_i) == -1)
{
return false;
}
if ((mac_i[1] != mac[1]) || (mac_i[0] < mac[0]))
{
return false;
}
index = mac_i[0] - mac[0];
if ((check_free && allocated.count(index) != 0) || (index >= size))
{
return false;
}
return true;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
bool AddressRange::is_valid_ip(unsigned int& index, const string& ip_s,
bool check_free)
{
if (!is_ipv4())//Not of type IP4 or IP4_6
{
return false;
}
unsigned int ip_i;
if (ip_to_i(ip_s, ip_i) == -1)
{
return false;
}
if (ip_i < ip)
{
return false;
}
index = ip_i - ip;
if ((check_free && allocated.count(index) != 0) || (index >= size))
{
return false;
}
return true;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
bool AddressRange::is_valid_ip6(unsigned int& index, const string& ip_s,
bool check_free)
{
if (!is_ipv6_static())//Not of type IP6_STATIC or IP4_6_STATIC
{
return false;
}
unsigned int ip_i[4];
if (ip6_to_i(ip_s, ip_i) == -1)
{
return false;
}
//3 most significant 32bit blocks must be equal
if ( ip_i[3] != ip6[3] || ip_i[2] != ip6[2] || ip_i[1] != ip6[1]
|| ip_i[0] < ip6[0] )
{
return false;
}
index = ip_i[0] - ip6[0];
if ((check_free && allocated.count(index) != 0) || (index >= size))
{
return false;
}
return true;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AddressRange::set_mac(unsigned int addr_index, VectorAttribute * nic) const
{
unsigned int new_mac[2];
new_mac[0] = mac[0] + addr_index;
new_mac[1] = mac[1];
nic->replace("MAC", mac_to_s(new_mac));
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AddressRange::set_ip(unsigned int addr_index, VectorAttribute * nic) const
{
nic->replace("IP", ip_to_s(ip + addr_index));
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AddressRange::set_ip6(unsigned int addr_index, VectorAttribute * nic) const
{
unsigned int new_mac[2];
string ip6_s;
new_mac[0] = mac[0] + addr_index;
new_mac[1] = mac[1];
/* Link Local */
unsigned int local_prefix[2] = {0, 0xfe800000};
if (ip6_to_s(local_prefix, new_mac, ip6_s) == 0)
{
nic->replace("IP6_LINK", ip6_s);
}
if (ula6[1] != 0 || ula6[0] != 0 ) /* Unique Local Address */
{
if (ip6_to_s(ula6, new_mac, ip6_s) == 0)
{
nic->replace("IP6_ULA", ip6_s);
}
}
if (global6[1] != 0 || global6[0] != 0 ) /* Global Unicast */
{
if (ip6_to_s(global6, new_mac, ip6_s) == 0)
{
nic->replace("IP6_GLOBAL", ip6_s);
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AddressRange::set_ip6_static(unsigned int addr_index,
VectorAttribute * nic) const
{
unsigned int ip_low[4];
string ip6_s;
ip_low[3] = ip6[3];
ip_low[2] = ip6[2];
ip_low[1] = ip6[1];
ip_low[0] = ip6[0] + addr_index;
if ( ip6_to_s(ip_low, ip6_s) == 0 )
{
nic->replace("IP6", ip6_s);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AddressRange::set_vnet(VectorAttribute *nic, const vector<string> &inherit) const
{
nic->replace("AR_ID", id);
string vn_mad = attr->vector_value("VN_MAD");
string bridge = attr->vector_value("BRIDGE");
string vlanid = attr->vector_value("VLAN_ID");
string phydev = attr->vector_value("PHYDEV");
if (!vn_mad.empty())
{
nic->replace("VN_MAD", vn_mad);
}
if (!bridge.empty())
{
nic->replace("BRIDGE", bridge);
}
if (!phydev.empty())
{
nic->replace("PHYDEV", phydev);
}
if (!vlanid.empty())
{
nic->replace("VLAN_ID", vlanid);
}
vector<string>::const_iterator it;
for (it = inherit.begin(); it != inherit.end(); it++)
{
string inherit_val = attr->vector_value(*it);
if (!inherit_val.empty())
{
nic->replace((*it).c_str(), inherit_val);
}
}
}
/* ************************************************************************** */
/* ************************************************************************** */
void AddressRange::allocated_to_attr()
{
if (allocated.empty())
{
attr->replace("ALLOCATED", "");
return;
}
map<unsigned int, long long>::const_iterator it;
ostringstream oss;
for (it = allocated.begin(); it != allocated.end(); it++)
{
oss << " " << it->first << " " << it->second;
}
attr->replace("ALLOCATED", oss.str());
}
/* -------------------------------------------------------------------------- */
int AddressRange::attr_to_allocated(const string& allocated_s)
{
if (allocated_s.empty())
{
allocated.clear();
return 0;
}
istringstream iss(allocated_s);
unsigned int addr_index;
long long object_pack;
while (!iss.eof())
{
iss >> ws >> addr_index >> ws >> object_pack;
if (iss.fail())
{
return -1;
}
allocated.insert(make_pair(addr_index,object_pack));
}
if ( get_used_addr() > size )
{
return -1;
}
return 0;
}
/* -------------------------------------------------------------------------- */
void AddressRange::set_allocated_addr(PoolObjectSQL::ObjectType ot, int obid,
unsigned int addr_index)
{
long long lobid = obid & 0x00000000FFFFFFFFLL;
allocated.insert(make_pair(addr_index,ot|lobid));
allocated_to_attr();
}
/* -------------------------------------------------------------------------- */
int AddressRange::free_allocated_addr(PoolObjectSQL::ObjectType ot, int obid,
unsigned int addr_index)
{
long long lobid = obid & 0x00000000FFFFFFFFLL;
map<unsigned int, long long>::iterator it;
it = allocated.find(addr_index);
if (it != allocated.end() && it->second == (ot|lobid))
{
allocated.erase(it);
allocated_to_attr();
return 0;
}
return -1;
}
/* ************************************************************************** */
/* ************************************************************************** */
void AddressRange::allocate_by_index(unsigned int index,
PoolObjectSQL::ObjectType ot,
int obid,
VectorAttribute* nic,
const vector<string>& inherit)
{
set_mac(index, nic);
if (is_ipv4())
{
set_ip(index, nic);
}
if (is_ipv6())
{
set_ip6(index, nic);
}
if (is_ipv6_static())
{
set_ip6_static(index, nic);
}
set_vnet(nic, inherit);
set_allocated_addr(ot, obid, index);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::allocate_addr(
PoolObjectSQL::ObjectType ot,
int obid,
VectorAttribute* nic,
const vector<string>& inherit)
{
unsigned int index;
string error_msg;
if ( get_used_addr() >= size )
{
return -1;
}
if ( get_addr(index, 1, error_msg) != 0 )
{
NebulaLog::log("IPM", Log::ERROR, error_msg);
return -1;
}
allocate_by_index(index, ot, obid, nic, inherit);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::allocate_by_mac(
const string& mac_s,
PoolObjectSQL::ObjectType ot,
int obid,
VectorAttribute* nic,
const vector<string>& inherit)
{
string error_msg;
unsigned int index;
if (!is_valid_mac(index, mac_s, true))
{
return -1;
}
if (allocate_addr(index, 1, error_msg) != 0)
{
NebulaLog::log("IPM", Log::ERROR, error_msg);
return -1;
}
allocate_by_index(index, ot, obid, nic, inherit);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::allocate_by_ip(
const string& ip_s,
PoolObjectSQL::ObjectType ot,
int obid,
VectorAttribute* nic,
const vector<string>& inherit)
{
string error_msg;
unsigned int index;
if (!is_valid_ip(index, ip_s, true))
{
return -1;
}
if (allocate_addr(index, 1, error_msg) != 0)
{
NebulaLog::log("IPM", Log::ERROR, error_msg);
return -1;
}
allocate_by_index(index, ot, obid, nic, inherit);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::allocate_by_ip6(
const string& ip6_s,
PoolObjectSQL::ObjectType ot,
int obid,
VectorAttribute* nic,
const vector<string>& inherit)
{
string error_msg;
unsigned int index;
if (!is_valid_ip6(index, ip6_s, true))
{
return -1;
}
if (allocate_addr(index, 1, error_msg) != 0)
{
NebulaLog::log("IPM", Log::ERROR, error_msg);
return -1;
}
allocate_by_index(index, ot, obid, nic, inherit);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::free_addr(PoolObjectSQL::ObjectType ot, int obid,
const string& mac_s)
{
string error_msg;
unsigned int mac_i[2];
mac_to_i(mac_s, mac_i);
unsigned int index = mac_i[0] - mac[0];
if (index < 0 || index >= size)
{
return -1;
}
if (free_addr(index, error_msg) != 0)
{
NebulaLog::log("IPM", Log::ERROR, error_msg);
return -1;
}
return free_allocated_addr(ot, obid, index);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::free_addr_by_ip(PoolObjectSQL::ObjectType ot, int obid,
const string& ip_s)
{
string error_msg;
if (!is_ipv4())
{
return -1;
}
unsigned int ip_i;
if (ip_to_i(ip_s, ip_i) == -1)
{
return -1;
}
unsigned int index = ip_i - ip;
if (index < 0 || index >= size)
{
return -1;
}
if (free_addr(index, error_msg) != 0)
{
return -1;
}
return free_allocated_addr(ot, obid, index);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::free_addr_by_ip6(PoolObjectSQL::ObjectType ot, int obid,
const string& ip_s)
{
string error_msg;
if (!is_ipv6_static())
{
return -1;
}
unsigned int ip_i[4];
if (ip6_to_i(ip_s, ip_i) == -1)
{
return -1;
}
unsigned int index = ip_i[0] - ip6[0];
if (index < 0 || index >= size || ip6[3] != ip_i[3] || ip6[2] != ip_i[2]
|| ip6[1] != ip_i[1])
{
return -1;
}
if (free_addr(index, error_msg) != 0)
{
return -1;
}
return free_allocated_addr(ot, obid, index);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::free_addr_by_owner(PoolObjectSQL::ObjectType ot, int obid)
{
map<unsigned int, long long>::iterator it = allocated.begin();
long long obj_pack = ot | (obid & 0x00000000FFFFFFFFLL);
int freed = 0;
string error_msg;
while (it != allocated.end())
{
if (it->second == obj_pack && free_addr(it->first, error_msg) == 0)
{
map<unsigned int, long long>::iterator prev_it = it++;
allocated.erase(prev_it);
freed++;
}
else
{
it++;
}
}
allocated_to_attr();
return freed;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::free_addr_by_range(PoolObjectSQL::ObjectType ot, int obid,
const string& mac_s, unsigned int rsize)
{
int freed = 0;
unsigned int mac_i[2];
mac_to_i(mac_s, mac_i);
unsigned int index = mac_i[0] - mac[0];
string error_msg;
if ((0 <= index) && (index < size))
{
map<unsigned int, long long>::iterator it = allocated.find(index);
if (it == allocated.end())
{
return freed;
}
long long obj_pack = ot | (obid & 0x00000000FFFFFFFFLL);
for (unsigned int i=0; i<rsize; i++)
{
if (it != allocated.end() && it->second == obj_pack &&
free_addr(it->first, error_msg) == 0)
{
map<unsigned int, long long>::iterator prev_it = it++;
allocated.erase(prev_it);
freed++;
}
else
{
it++;
}
}
allocated_to_attr();
}
return freed;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
const char * AddressRange::SG_RULE_ATTRIBUTES[] = {
"AR_ID",
"TYPE",
"SIZE",
"MAC",
"IP",
"IP6"};
const int AddressRange::NUM_SG_RULE_ATTRIBUTES = 6;
void AddressRange::process_security_rule(VectorAttribute * rule)
{
// Persistent attributes
for ( int i = 0; i < NUM_SG_RULE_ATTRIBUTES; i++ )
{
string st = attr->vector_value(SG_RULE_ATTRIBUTES[i]);
if ( st != "" )
{
rule->replace(SG_RULE_ATTRIBUTES[i], st);
}
}
// Non persistent attributes
string ip6_s;
if (ula6[1] != 0 || ula6[0] != 0 )
{
ip6_to_s(ula6, mac, ip6_s);
rule->replace("IP6_ULA", ip6_s);
}
if (global6[1] != 0 || global6[0] != 0 )
{
ip6_to_s(global6, mac, ip6_s);
rule->replace("IP6_GLOBAL", ip6_s);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::hold_by_ip6(const string& ip_s)
{
string error_msg;
unsigned int index;
if (!is_valid_ip6(index, ip_s, true))
{
return -1;
}
if (allocate_addr(index, 1, error_msg) != 0)
{
NebulaLog::log("IPM", Log::ERROR, error_msg);
return -1;
}
set_allocated_addr(PoolObjectSQL::VM, -1, index);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::hold_by_ip(const string& ip_s)
{
string error_msg;
unsigned int index;
if (!is_valid_ip(index, ip_s, true))
{
return -1;
}
if (allocate_addr(index, 1, error_msg) != 0)
{
NebulaLog::log("IPM", Log::ERROR, error_msg);
return -1;
}
set_allocated_addr(PoolObjectSQL::VM, -1, index);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::hold_by_mac(const string& mac_s)
{
unsigned int index;
string error_msg;
if (!is_valid_mac(index, mac_s, true))
{
return -1;
}
if (allocate_addr(index, 1, error_msg) != 0)
{
NebulaLog::log("IPM", Log::ERROR, error_msg);
return -1;
}
set_allocated_addr(PoolObjectSQL::VM, -1, index);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::reserve_addr(int vid, unsigned int rsize, AddressRange *rar)
{
unsigned int first_index;
string error_msg;
if (rsize > get_free_addr())
{
return -1;
}
if ( get_addr(first_index, rsize, error_msg) != 0 )
{
NebulaLog::log("IPM", Log::ERROR, error_msg);
return -1;
}
for (unsigned int j=0, i=first_index; j<rsize; j++, i++)
{
set_allocated_addr(PoolObjectSQL::NET, vid, i);
}
VectorAttribute * new_ar = attr->clone();
string errmsg;
set_mac(first_index, new_ar);
if ( is_ipv4() )
{
set_ip(first_index, new_ar);
}
if ( is_ipv6_static() )
{
set_ip6_static(first_index, new_ar);
}
new_ar->replace("SIZE",rsize);
new_ar->remove("IPAM_MAD");
rar->from_vattr(new_ar, errmsg);
new_ar->replace("PARENT_NETWORK_AR_ID",id);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::reserve_addr_by_index(int vid, unsigned int rsize,
unsigned int sindex, AddressRange *rar)
{
string error_msg;
/* ----------------- Allocate the new AR from sindex -------------------- */
for (unsigned int j=sindex; j< (sindex+rsize) ; j++)
{
if (allocated.count(j) != 0)
{
return -1;
}
}
if (allocate_addr(sindex, rsize, error_msg) != 0)
{
NebulaLog::log("IPM", Log::ERROR, error_msg);
return -1;
}
for (unsigned int j=sindex; j< (sindex+rsize); j++)
{
set_allocated_addr(PoolObjectSQL::NET, vid, j);
}
/* ------------------------- Initialize the new AR ---------------------- */
VectorAttribute * new_ar = attr->clone();
string errmsg;
set_mac(sindex, new_ar);
if ( is_ipv4() )
{
set_ip(sindex, new_ar);
}
if ( is_ipv6_static() )
{
set_ip6_static(sindex, new_ar);
}
new_ar->replace("SIZE",rsize);
new_ar->remove("IPAM_MAD");
rar->from_vattr(new_ar, errmsg);
new_ar->replace("PARENT_NETWORK_AR_ID",id);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::reserve_addr_by_ip6(int vid, unsigned int rsize,
const string& ip_s, AddressRange *rar)
{
unsigned int sindex;
if (!is_valid_ip6(sindex, ip_s, false))
{
return -1;
}
return reserve_addr_by_index(vid, rsize, sindex, rar);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::reserve_addr_by_ip(int vid, unsigned int rsize,
const string& ip_s, AddressRange *rar)
{
unsigned int sindex;
if (!is_valid_ip(sindex, ip_s, false))
{
return -1;
}
return reserve_addr_by_index(vid, rsize, sindex, rar);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AddressRange::reserve_addr_by_mac(int vid, unsigned int rsize,
const string& mac_s, AddressRange *rar)
{
unsigned int sindex;
if (!is_valid_mac(sindex, mac_s, false))
{
return -1;
}
return reserve_addr_by_index(vid, rsize, sindex, rar);
}
/* ************************************************************************** */
/* ************************************************************************** */
bool AddressRange::restricted_set = false;
set<string> AddressRange::restricted_attributes;
bool AddressRange::check(string& rs_attr) const
{
if (!restricted_set)
{
return false;
}
const map<string,string>& ar_attrs = attr->value();
map<string,string>::const_iterator it;
for (it=ar_attrs.begin(); it != ar_attrs.end(); it++)
{
if (restricted_attributes.count(it->first) > 0)
{
rs_attr = it->first;
return true;
}
}
return false;
};
void AddressRange::set_restricted_attributes(vector<const SingleAttribute *>& rattrs)
{
if (restricted_set)
{
return;
}
restricted_set = true;
for (unsigned int i = 0 ; i < rattrs.size() ; i++ )
{
string attr_s = rattrs[i]->value();
restricted_attributes.insert(one_util::toupper(attr_s));
}
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AddressRange::remove_restricted(VectorAttribute* va)
{
set<string>::const_iterator it;
size_t pos;
for (it=restricted_attributes.begin(); it!=restricted_attributes.end(); it++)
{
pos = it->find("AR/");
if (pos != string::npos)
{
va->remove( it->substr(pos+3) );
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AddressRange::remove_all_except_restricted(VectorAttribute* va)
{
map<string,string>::iterator it;
map<string,string> vals = va->value();
ostringstream oss;
for(it = vals.begin(); it != vals.end(); it++)
{
oss.str("");
oss << "AR/" << it->first;
if (restricted_attributes.count(oss.str()) == 0)
{
va->remove(it->first);
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AddressRange::decrypt()
{
string one_key;
Nebula::instance().get_configuration_attribute("ONE_KEY", one_key);
for ( const auto& ea : VirtualNetworkTemplate::encrypted )
{
attr->decrypt(one_key, ea.second);
}
}