mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
hyperv-fixes for v6.9-rc4
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEIbPD0id6easf0xsudhRwX5BBoF4FAmYYYPkTHHdlaS5saXVA a2VybmVsLm9yZwAKCRB2FHBfkEGgXnxhB/4/8c7lFT53VbujFmVA5sNvpP5Ji5Xg ERhVID7tzDyaVRPr+tpPJIW0Oj/t34SH9seoTYCBCM/UABWe/Gxceg2JaoOzIx+l LHi73T4BBaqExiXbCCFj8N7gLO5P4Xz6ZZRgwHws1KmMXsiWYmYsbv36eSv9x6qK +z/n6p9/ubKFNj2/vsvfiGmY0XHayD3NM4Y4toMbYE/tuRT8uZ7D5sqWdRf+UhW/ goRDA5qppeSfuaQu2LNVoz1e6wRmeJFv8OHgaPvQqAjTRLzPwwss28HICmKc8gh3 HDDUUJCHSs1XItSGDFip6rIFso5X/ZHO0d6pV75hOKCisd7lV0qH6NIZ =k62H -----END PGP SIGNATURE----- Merge tag 'hyperv-fixes-signed-20240411' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux Pull hyperv fixes from Wei Liu: - Some cosmetic changes (Erni Sri Satya Vennela, Li Zhijian) - Introduce hv_numa_node_to_pxm_info() (Nuno Das Neves) - Fix KVP daemon to handle IPv4 and IPv6 combination for keyfile format (Shradha Gupta) - Avoid freeing decrypted memory in a confidential VM (Rick Edgecombe and Michael Kelley) * tag 'hyperv-fixes-signed-20240411' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: Drivers: hv: vmbus: Don't free ring buffers that couldn't be re-encrypted uio_hv_generic: Don't free decrypted memory hv_netvsc: Don't free decrypted memory Drivers: hv: vmbus: Track decrypted status in vmbus_gpadl Drivers: hv: vmbus: Leak pages if set_memory_encrypted() fails hv/hv_kvp_daemon: Handle IPv4 and Ipv6 combination for keyfile format hv: vmbus: Convert sprintf() family to sysfs_emit() family mshyperv: Introduce hv_numa_node_to_pxm_info() x86/hyperv: Cosmetic changes for hv_apic.c
This commit is contained in:
commit
52e5070f60
@ -105,7 +105,7 @@ static bool cpu_is_self(int cpu)
|
|||||||
* IPI implementation on Hyper-V.
|
* IPI implementation on Hyper-V.
|
||||||
*/
|
*/
|
||||||
static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
|
static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
|
||||||
bool exclude_self)
|
bool exclude_self)
|
||||||
{
|
{
|
||||||
struct hv_send_ipi_ex *ipi_arg;
|
struct hv_send_ipi_ex *ipi_arg;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -132,8 +132,8 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
|
|||||||
if (!cpumask_equal(mask, cpu_present_mask) || exclude_self) {
|
if (!cpumask_equal(mask, cpu_present_mask) || exclude_self) {
|
||||||
ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K;
|
ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K;
|
||||||
|
|
||||||
nr_bank = cpumask_to_vpset_skip(&(ipi_arg->vp_set), mask,
|
nr_bank = cpumask_to_vpset_skip(&ipi_arg->vp_set, mask,
|
||||||
exclude_self ? cpu_is_self : NULL);
|
exclude_self ? cpu_is_self : NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 'nr_bank <= 0' means some CPUs in cpumask can't be
|
* 'nr_bank <= 0' means some CPUs in cpumask can't be
|
||||||
@ -147,7 +147,7 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
|
|||||||
}
|
}
|
||||||
|
|
||||||
status = hv_do_rep_hypercall(HVCALL_SEND_IPI_EX, 0, nr_bank,
|
status = hv_do_rep_hypercall(HVCALL_SEND_IPI_EX, 0, nr_bank,
|
||||||
ipi_arg, NULL);
|
ipi_arg, NULL);
|
||||||
|
|
||||||
ipi_mask_ex_done:
|
ipi_mask_ex_done:
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
@ -155,7 +155,7 @@ ipi_mask_ex_done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool __send_ipi_mask(const struct cpumask *mask, int vector,
|
static bool __send_ipi_mask(const struct cpumask *mask, int vector,
|
||||||
bool exclude_self)
|
bool exclude_self)
|
||||||
{
|
{
|
||||||
int cur_cpu, vcpu, this_cpu = smp_processor_id();
|
int cur_cpu, vcpu, this_cpu = smp_processor_id();
|
||||||
struct hv_send_ipi ipi_arg;
|
struct hv_send_ipi ipi_arg;
|
||||||
@ -181,7 +181,7 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
|
if (vector < HV_IPI_LOW_VECTOR || vector > HV_IPI_HIGH_VECTOR)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -218,7 +218,7 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector,
|
|||||||
}
|
}
|
||||||
|
|
||||||
status = hv_do_fast_hypercall16(HVCALL_SEND_IPI, ipi_arg.vector,
|
status = hv_do_fast_hypercall16(HVCALL_SEND_IPI, ipi_arg.vector,
|
||||||
ipi_arg.cpu_mask);
|
ipi_arg.cpu_mask);
|
||||||
return hv_result_success(status);
|
return hv_result_success(status);
|
||||||
|
|
||||||
do_ex_hypercall:
|
do_ex_hypercall:
|
||||||
@ -241,7 +241,7 @@ static bool __send_ipi_one(int cpu, int vector)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
|
if (vector < HV_IPI_LOW_VECTOR || vector > HV_IPI_HIGH_VECTOR)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (vp >= 64)
|
if (vp >= 64)
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/clockchips.h>
|
#include <linux/clockchips.h>
|
||||||
#include <linux/acpi.h>
|
|
||||||
#include <linux/hyperv.h>
|
#include <linux/hyperv.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/cpuhotplug.h>
|
#include <linux/cpuhotplug.h>
|
||||||
@ -116,12 +115,11 @@ free_buf:
|
|||||||
|
|
||||||
int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
|
int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
|
||||||
{
|
{
|
||||||
struct hv_add_logical_processor_in *input;
|
struct hv_input_add_logical_processor *input;
|
||||||
struct hv_add_logical_processor_out *output;
|
struct hv_output_add_logical_processor *output;
|
||||||
u64 status;
|
u64 status;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = HV_STATUS_SUCCESS;
|
int ret = HV_STATUS_SUCCESS;
|
||||||
int pxm = node_to_pxm(node);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When adding a logical processor, the hypervisor may return
|
* When adding a logical processor, the hypervisor may return
|
||||||
@ -137,11 +135,7 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
|
|||||||
|
|
||||||
input->lp_index = lp_index;
|
input->lp_index = lp_index;
|
||||||
input->apic_id = apic_id;
|
input->apic_id = apic_id;
|
||||||
input->flags = 0;
|
input->proximity_domain_info = hv_numa_node_to_pxm_info(node);
|
||||||
input->proximity_domain_info.domain_id = pxm;
|
|
||||||
input->proximity_domain_info.flags.reserved = 0;
|
|
||||||
input->proximity_domain_info.flags.proximity_info_valid = 1;
|
|
||||||
input->proximity_domain_info.flags.proximity_preferred = 1;
|
|
||||||
status = hv_do_hypercall(HVCALL_ADD_LOGICAL_PROCESSOR,
|
status = hv_do_hypercall(HVCALL_ADD_LOGICAL_PROCESSOR,
|
||||||
input, output);
|
input, output);
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
@ -166,7 +160,6 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
|
|||||||
u64 status;
|
u64 status;
|
||||||
unsigned long irq_flags;
|
unsigned long irq_flags;
|
||||||
int ret = HV_STATUS_SUCCESS;
|
int ret = HV_STATUS_SUCCESS;
|
||||||
int pxm = node_to_pxm(node);
|
|
||||||
|
|
||||||
/* Root VPs don't seem to need pages deposited */
|
/* Root VPs don't seem to need pages deposited */
|
||||||
if (partition_id != hv_current_partition_id) {
|
if (partition_id != hv_current_partition_id) {
|
||||||
@ -185,14 +178,7 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
|
|||||||
input->vp_index = vp_index;
|
input->vp_index = vp_index;
|
||||||
input->flags = flags;
|
input->flags = flags;
|
||||||
input->subnode_type = HvSubnodeAny;
|
input->subnode_type = HvSubnodeAny;
|
||||||
if (node != NUMA_NO_NODE) {
|
input->proximity_domain_info = hv_numa_node_to_pxm_info(node);
|
||||||
input->proximity_domain_info.domain_id = pxm;
|
|
||||||
input->proximity_domain_info.flags.reserved = 0;
|
|
||||||
input->proximity_domain_info.flags.proximity_info_valid = 1;
|
|
||||||
input->proximity_domain_info.flags.proximity_preferred = 1;
|
|
||||||
} else {
|
|
||||||
input->proximity_domain_info.as_uint64 = 0;
|
|
||||||
}
|
|
||||||
status = hv_do_hypercall(HVCALL_CREATE_VP, input, NULL);
|
status = hv_do_hypercall(HVCALL_CREATE_VP, input, NULL);
|
||||||
local_irq_restore(irq_flags);
|
local_irq_restore(irq_flags);
|
||||||
|
|
||||||
|
@ -153,7 +153,9 @@ void vmbus_free_ring(struct vmbus_channel *channel)
|
|||||||
hv_ringbuffer_cleanup(&channel->inbound);
|
hv_ringbuffer_cleanup(&channel->inbound);
|
||||||
|
|
||||||
if (channel->ringbuffer_page) {
|
if (channel->ringbuffer_page) {
|
||||||
__free_pages(channel->ringbuffer_page,
|
/* In a CoCo VM leak the memory if it didn't get re-encrypted */
|
||||||
|
if (!channel->ringbuffer_gpadlhandle.decrypted)
|
||||||
|
__free_pages(channel->ringbuffer_page,
|
||||||
get_order(channel->ringbuffer_pagecount
|
get_order(channel->ringbuffer_pagecount
|
||||||
<< PAGE_SHIFT));
|
<< PAGE_SHIFT));
|
||||||
channel->ringbuffer_page = NULL;
|
channel->ringbuffer_page = NULL;
|
||||||
@ -436,9 +438,18 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
|
|||||||
(atomic_inc_return(&vmbus_connection.next_gpadl_handle) - 1);
|
(atomic_inc_return(&vmbus_connection.next_gpadl_handle) - 1);
|
||||||
|
|
||||||
ret = create_gpadl_header(type, kbuffer, size, send_offset, &msginfo);
|
ret = create_gpadl_header(type, kbuffer, size, send_offset, &msginfo);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
gpadl->decrypted = false;
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the "decrypted" flag to true for the set_memory_decrypted()
|
||||||
|
* success case. In the failure case, the encryption state of the
|
||||||
|
* memory is unknown. Leave "decrypted" as true to ensure the
|
||||||
|
* memory will be leaked instead of going back on the free list.
|
||||||
|
*/
|
||||||
|
gpadl->decrypted = true;
|
||||||
ret = set_memory_decrypted((unsigned long)kbuffer,
|
ret = set_memory_decrypted((unsigned long)kbuffer,
|
||||||
PFN_UP(size));
|
PFN_UP(size));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -527,9 +538,15 @@ cleanup:
|
|||||||
|
|
||||||
kfree(msginfo);
|
kfree(msginfo);
|
||||||
|
|
||||||
if (ret)
|
if (ret) {
|
||||||
set_memory_encrypted((unsigned long)kbuffer,
|
/*
|
||||||
PFN_UP(size));
|
* If set_memory_encrypted() fails, the decrypted flag is
|
||||||
|
* left as true so the memory is leaked instead of being
|
||||||
|
* put back on the free list.
|
||||||
|
*/
|
||||||
|
if (!set_memory_encrypted((unsigned long)kbuffer, PFN_UP(size)))
|
||||||
|
gpadl->decrypted = false;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -850,6 +867,8 @@ post_msg_err:
|
|||||||
if (ret)
|
if (ret)
|
||||||
pr_warn("Fail to set mem host visibility in GPADL teardown %d.\n", ret);
|
pr_warn("Fail to set mem host visibility in GPADL teardown %d.\n", ret);
|
||||||
|
|
||||||
|
gpadl->decrypted = ret;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
|
EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
|
||||||
|
@ -237,8 +237,17 @@ int vmbus_connect(void)
|
|||||||
vmbus_connection.monitor_pages[0], 1);
|
vmbus_connection.monitor_pages[0], 1);
|
||||||
ret |= set_memory_decrypted((unsigned long)
|
ret |= set_memory_decrypted((unsigned long)
|
||||||
vmbus_connection.monitor_pages[1], 1);
|
vmbus_connection.monitor_pages[1], 1);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
/*
|
||||||
|
* If set_memory_decrypted() fails, the encryption state
|
||||||
|
* of the memory is unknown. So leak the memory instead
|
||||||
|
* of risking returning decrypted memory to the free list.
|
||||||
|
* For simplicity, always handle both pages the same.
|
||||||
|
*/
|
||||||
|
vmbus_connection.monitor_pages[0] = NULL;
|
||||||
|
vmbus_connection.monitor_pages[1] = NULL;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set_memory_decrypted() will change the memory contents if
|
* Set_memory_decrypted() will change the memory contents if
|
||||||
@ -337,13 +346,19 @@ void vmbus_disconnect(void)
|
|||||||
vmbus_connection.int_page = NULL;
|
vmbus_connection.int_page = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[0], 1);
|
if (vmbus_connection.monitor_pages[0]) {
|
||||||
set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[1], 1);
|
if (!set_memory_encrypted(
|
||||||
|
(unsigned long)vmbus_connection.monitor_pages[0], 1))
|
||||||
|
hv_free_hyperv_page(vmbus_connection.monitor_pages[0]);
|
||||||
|
vmbus_connection.monitor_pages[0] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
hv_free_hyperv_page(vmbus_connection.monitor_pages[0]);
|
if (vmbus_connection.monitor_pages[1]) {
|
||||||
hv_free_hyperv_page(vmbus_connection.monitor_pages[1]);
|
if (!set_memory_encrypted(
|
||||||
vmbus_connection.monitor_pages[0] = NULL;
|
(unsigned long)vmbus_connection.monitor_pages[1], 1))
|
||||||
vmbus_connection.monitor_pages[1] = NULL;
|
hv_free_hyperv_page(vmbus_connection.monitor_pages[1]);
|
||||||
|
vmbus_connection.monitor_pages[1] = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -131,7 +131,7 @@ static ssize_t id_show(struct device *dev, struct device_attribute *dev_attr,
|
|||||||
|
|
||||||
if (!hv_dev->channel)
|
if (!hv_dev->channel)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
return sprintf(buf, "%d\n", hv_dev->channel->offermsg.child_relid);
|
return sysfs_emit(buf, "%d\n", hv_dev->channel->offermsg.child_relid);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(id);
|
static DEVICE_ATTR_RO(id);
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ static ssize_t state_show(struct device *dev, struct device_attribute *dev_attr,
|
|||||||
|
|
||||||
if (!hv_dev->channel)
|
if (!hv_dev->channel)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
return sprintf(buf, "%d\n", hv_dev->channel->state);
|
return sysfs_emit(buf, "%d\n", hv_dev->channel->state);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(state);
|
static DEVICE_ATTR_RO(state);
|
||||||
|
|
||||||
@ -153,7 +153,7 @@ static ssize_t monitor_id_show(struct device *dev,
|
|||||||
|
|
||||||
if (!hv_dev->channel)
|
if (!hv_dev->channel)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
return sprintf(buf, "%d\n", hv_dev->channel->offermsg.monitorid);
|
return sysfs_emit(buf, "%d\n", hv_dev->channel->offermsg.monitorid);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(monitor_id);
|
static DEVICE_ATTR_RO(monitor_id);
|
||||||
|
|
||||||
@ -164,8 +164,8 @@ static ssize_t class_id_show(struct device *dev,
|
|||||||
|
|
||||||
if (!hv_dev->channel)
|
if (!hv_dev->channel)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
return sprintf(buf, "{%pUl}\n",
|
return sysfs_emit(buf, "{%pUl}\n",
|
||||||
&hv_dev->channel->offermsg.offer.if_type);
|
&hv_dev->channel->offermsg.offer.if_type);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(class_id);
|
static DEVICE_ATTR_RO(class_id);
|
||||||
|
|
||||||
@ -176,8 +176,8 @@ static ssize_t device_id_show(struct device *dev,
|
|||||||
|
|
||||||
if (!hv_dev->channel)
|
if (!hv_dev->channel)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
return sprintf(buf, "{%pUl}\n",
|
return sysfs_emit(buf, "{%pUl}\n",
|
||||||
&hv_dev->channel->offermsg.offer.if_instance);
|
&hv_dev->channel->offermsg.offer.if_instance);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(device_id);
|
static DEVICE_ATTR_RO(device_id);
|
||||||
|
|
||||||
@ -186,7 +186,7 @@ static ssize_t modalias_show(struct device *dev,
|
|||||||
{
|
{
|
||||||
struct hv_device *hv_dev = device_to_hv_device(dev);
|
struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||||
|
|
||||||
return sprintf(buf, "vmbus:%*phN\n", UUID_SIZE, &hv_dev->dev_type);
|
return sysfs_emit(buf, "vmbus:%*phN\n", UUID_SIZE, &hv_dev->dev_type);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(modalias);
|
static DEVICE_ATTR_RO(modalias);
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ static ssize_t numa_node_show(struct device *dev,
|
|||||||
if (!hv_dev->channel)
|
if (!hv_dev->channel)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", cpu_to_node(hv_dev->channel->target_cpu));
|
return sysfs_emit(buf, "%d\n", cpu_to_node(hv_dev->channel->target_cpu));
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(numa_node);
|
static DEVICE_ATTR_RO(numa_node);
|
||||||
#endif
|
#endif
|
||||||
@ -212,9 +212,8 @@ static ssize_t server_monitor_pending_show(struct device *dev,
|
|||||||
|
|
||||||
if (!hv_dev->channel)
|
if (!hv_dev->channel)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
return sprintf(buf, "%d\n",
|
return sysfs_emit(buf, "%d\n", channel_pending(hv_dev->channel,
|
||||||
channel_pending(hv_dev->channel,
|
vmbus_connection.monitor_pages[0]));
|
||||||
vmbus_connection.monitor_pages[0]));
|
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(server_monitor_pending);
|
static DEVICE_ATTR_RO(server_monitor_pending);
|
||||||
|
|
||||||
@ -226,9 +225,8 @@ static ssize_t client_monitor_pending_show(struct device *dev,
|
|||||||
|
|
||||||
if (!hv_dev->channel)
|
if (!hv_dev->channel)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
return sprintf(buf, "%d\n",
|
return sysfs_emit(buf, "%d\n", channel_pending(hv_dev->channel,
|
||||||
channel_pending(hv_dev->channel,
|
vmbus_connection.monitor_pages[1]));
|
||||||
vmbus_connection.monitor_pages[1]));
|
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(client_monitor_pending);
|
static DEVICE_ATTR_RO(client_monitor_pending);
|
||||||
|
|
||||||
@ -240,9 +238,8 @@ static ssize_t server_monitor_latency_show(struct device *dev,
|
|||||||
|
|
||||||
if (!hv_dev->channel)
|
if (!hv_dev->channel)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
return sprintf(buf, "%d\n",
|
return sysfs_emit(buf, "%d\n", channel_latency(hv_dev->channel,
|
||||||
channel_latency(hv_dev->channel,
|
vmbus_connection.monitor_pages[0]));
|
||||||
vmbus_connection.monitor_pages[0]));
|
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(server_monitor_latency);
|
static DEVICE_ATTR_RO(server_monitor_latency);
|
||||||
|
|
||||||
@ -254,9 +251,8 @@ static ssize_t client_monitor_latency_show(struct device *dev,
|
|||||||
|
|
||||||
if (!hv_dev->channel)
|
if (!hv_dev->channel)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
return sprintf(buf, "%d\n",
|
return sysfs_emit(buf, "%d\n", channel_latency(hv_dev->channel,
|
||||||
channel_latency(hv_dev->channel,
|
vmbus_connection.monitor_pages[1]));
|
||||||
vmbus_connection.monitor_pages[1]));
|
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(client_monitor_latency);
|
static DEVICE_ATTR_RO(client_monitor_latency);
|
||||||
|
|
||||||
@ -268,9 +264,8 @@ static ssize_t server_monitor_conn_id_show(struct device *dev,
|
|||||||
|
|
||||||
if (!hv_dev->channel)
|
if (!hv_dev->channel)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
return sprintf(buf, "%d\n",
|
return sysfs_emit(buf, "%d\n", channel_conn_id(hv_dev->channel,
|
||||||
channel_conn_id(hv_dev->channel,
|
vmbus_connection.monitor_pages[0]));
|
||||||
vmbus_connection.monitor_pages[0]));
|
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(server_monitor_conn_id);
|
static DEVICE_ATTR_RO(server_monitor_conn_id);
|
||||||
|
|
||||||
@ -282,9 +277,8 @@ static ssize_t client_monitor_conn_id_show(struct device *dev,
|
|||||||
|
|
||||||
if (!hv_dev->channel)
|
if (!hv_dev->channel)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
return sprintf(buf, "%d\n",
|
return sysfs_emit(buf, "%d\n", channel_conn_id(hv_dev->channel,
|
||||||
channel_conn_id(hv_dev->channel,
|
vmbus_connection.monitor_pages[1]));
|
||||||
vmbus_connection.monitor_pages[1]));
|
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(client_monitor_conn_id);
|
static DEVICE_ATTR_RO(client_monitor_conn_id);
|
||||||
|
|
||||||
@ -303,7 +297,7 @@ static ssize_t out_intr_mask_show(struct device *dev,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", outbound.current_interrupt_mask);
|
return sysfs_emit(buf, "%d\n", outbound.current_interrupt_mask);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(out_intr_mask);
|
static DEVICE_ATTR_RO(out_intr_mask);
|
||||||
|
|
||||||
@ -321,7 +315,7 @@ static ssize_t out_read_index_show(struct device *dev,
|
|||||||
&outbound);
|
&outbound);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
return sprintf(buf, "%d\n", outbound.current_read_index);
|
return sysfs_emit(buf, "%d\n", outbound.current_read_index);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(out_read_index);
|
static DEVICE_ATTR_RO(out_read_index);
|
||||||
|
|
||||||
@ -340,7 +334,7 @@ static ssize_t out_write_index_show(struct device *dev,
|
|||||||
&outbound);
|
&outbound);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
return sprintf(buf, "%d\n", outbound.current_write_index);
|
return sysfs_emit(buf, "%d\n", outbound.current_write_index);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(out_write_index);
|
static DEVICE_ATTR_RO(out_write_index);
|
||||||
|
|
||||||
@ -359,7 +353,7 @@ static ssize_t out_read_bytes_avail_show(struct device *dev,
|
|||||||
&outbound);
|
&outbound);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
return sprintf(buf, "%d\n", outbound.bytes_avail_toread);
|
return sysfs_emit(buf, "%d\n", outbound.bytes_avail_toread);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(out_read_bytes_avail);
|
static DEVICE_ATTR_RO(out_read_bytes_avail);
|
||||||
|
|
||||||
@ -378,7 +372,7 @@ static ssize_t out_write_bytes_avail_show(struct device *dev,
|
|||||||
&outbound);
|
&outbound);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
return sprintf(buf, "%d\n", outbound.bytes_avail_towrite);
|
return sysfs_emit(buf, "%d\n", outbound.bytes_avail_towrite);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(out_write_bytes_avail);
|
static DEVICE_ATTR_RO(out_write_bytes_avail);
|
||||||
|
|
||||||
@ -396,7 +390,7 @@ static ssize_t in_intr_mask_show(struct device *dev,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", inbound.current_interrupt_mask);
|
return sysfs_emit(buf, "%d\n", inbound.current_interrupt_mask);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(in_intr_mask);
|
static DEVICE_ATTR_RO(in_intr_mask);
|
||||||
|
|
||||||
@ -414,7 +408,7 @@ static ssize_t in_read_index_show(struct device *dev,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", inbound.current_read_index);
|
return sysfs_emit(buf, "%d\n", inbound.current_read_index);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(in_read_index);
|
static DEVICE_ATTR_RO(in_read_index);
|
||||||
|
|
||||||
@ -432,7 +426,7 @@ static ssize_t in_write_index_show(struct device *dev,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", inbound.current_write_index);
|
return sysfs_emit(buf, "%d\n", inbound.current_write_index);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(in_write_index);
|
static DEVICE_ATTR_RO(in_write_index);
|
||||||
|
|
||||||
@ -451,7 +445,7 @@ static ssize_t in_read_bytes_avail_show(struct device *dev,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", inbound.bytes_avail_toread);
|
return sysfs_emit(buf, "%d\n", inbound.bytes_avail_toread);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(in_read_bytes_avail);
|
static DEVICE_ATTR_RO(in_read_bytes_avail);
|
||||||
|
|
||||||
@ -470,7 +464,7 @@ static ssize_t in_write_bytes_avail_show(struct device *dev,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", inbound.bytes_avail_towrite);
|
return sysfs_emit(buf, "%d\n", inbound.bytes_avail_towrite);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(in_write_bytes_avail);
|
static DEVICE_ATTR_RO(in_write_bytes_avail);
|
||||||
|
|
||||||
@ -480,7 +474,7 @@ static ssize_t channel_vp_mapping_show(struct device *dev,
|
|||||||
{
|
{
|
||||||
struct hv_device *hv_dev = device_to_hv_device(dev);
|
struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||||
struct vmbus_channel *channel = hv_dev->channel, *cur_sc;
|
struct vmbus_channel *channel = hv_dev->channel, *cur_sc;
|
||||||
int buf_size = PAGE_SIZE, n_written, tot_written;
|
int n_written;
|
||||||
struct list_head *cur;
|
struct list_head *cur;
|
||||||
|
|
||||||
if (!channel)
|
if (!channel)
|
||||||
@ -488,25 +482,21 @@ static ssize_t channel_vp_mapping_show(struct device *dev,
|
|||||||
|
|
||||||
mutex_lock(&vmbus_connection.channel_mutex);
|
mutex_lock(&vmbus_connection.channel_mutex);
|
||||||
|
|
||||||
tot_written = snprintf(buf, buf_size, "%u:%u\n",
|
n_written = sysfs_emit(buf, "%u:%u\n",
|
||||||
channel->offermsg.child_relid, channel->target_cpu);
|
channel->offermsg.child_relid,
|
||||||
|
channel->target_cpu);
|
||||||
|
|
||||||
list_for_each(cur, &channel->sc_list) {
|
list_for_each(cur, &channel->sc_list) {
|
||||||
if (tot_written >= buf_size - 1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
cur_sc = list_entry(cur, struct vmbus_channel, sc_list);
|
cur_sc = list_entry(cur, struct vmbus_channel, sc_list);
|
||||||
n_written = scnprintf(buf + tot_written,
|
n_written += sysfs_emit_at(buf, n_written, "%u:%u\n",
|
||||||
buf_size - tot_written,
|
cur_sc->offermsg.child_relid,
|
||||||
"%u:%u\n",
|
cur_sc->target_cpu);
|
||||||
cur_sc->offermsg.child_relid,
|
|
||||||
cur_sc->target_cpu);
|
|
||||||
tot_written += n_written;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&vmbus_connection.channel_mutex);
|
mutex_unlock(&vmbus_connection.channel_mutex);
|
||||||
|
|
||||||
return tot_written;
|
return n_written;
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(channel_vp_mapping);
|
static DEVICE_ATTR_RO(channel_vp_mapping);
|
||||||
|
|
||||||
@ -516,7 +506,7 @@ static ssize_t vendor_show(struct device *dev,
|
|||||||
{
|
{
|
||||||
struct hv_device *hv_dev = device_to_hv_device(dev);
|
struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||||
|
|
||||||
return sprintf(buf, "0x%x\n", hv_dev->vendor_id);
|
return sysfs_emit(buf, "0x%x\n", hv_dev->vendor_id);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(vendor);
|
static DEVICE_ATTR_RO(vendor);
|
||||||
|
|
||||||
@ -526,7 +516,7 @@ static ssize_t device_show(struct device *dev,
|
|||||||
{
|
{
|
||||||
struct hv_device *hv_dev = device_to_hv_device(dev);
|
struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||||
|
|
||||||
return sprintf(buf, "0x%x\n", hv_dev->device_id);
|
return sysfs_emit(buf, "0x%x\n", hv_dev->device_id);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(device);
|
static DEVICE_ATTR_RO(device);
|
||||||
|
|
||||||
@ -551,7 +541,7 @@ static ssize_t driver_override_show(struct device *dev,
|
|||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
device_lock(dev);
|
device_lock(dev);
|
||||||
len = snprintf(buf, PAGE_SIZE, "%s\n", hv_dev->driver_override);
|
len = sysfs_emit(buf, "%s\n", hv_dev->driver_override);
|
||||||
device_unlock(dev);
|
device_unlock(dev);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
|
@ -154,8 +154,11 @@ static void free_netvsc_device(struct rcu_head *head)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
kfree(nvdev->extension);
|
kfree(nvdev->extension);
|
||||||
vfree(nvdev->recv_buf);
|
|
||||||
vfree(nvdev->send_buf);
|
if (!nvdev->recv_buf_gpadl_handle.decrypted)
|
||||||
|
vfree(nvdev->recv_buf);
|
||||||
|
if (!nvdev->send_buf_gpadl_handle.decrypted)
|
||||||
|
vfree(nvdev->send_buf);
|
||||||
bitmap_free(nvdev->send_section_map);
|
bitmap_free(nvdev->send_section_map);
|
||||||
|
|
||||||
for (i = 0; i < VRSS_CHANNEL_MAX; i++) {
|
for (i = 0; i < VRSS_CHANNEL_MAX; i++) {
|
||||||
|
@ -181,12 +181,14 @@ hv_uio_cleanup(struct hv_device *dev, struct hv_uio_private_data *pdata)
|
|||||||
{
|
{
|
||||||
if (pdata->send_gpadl.gpadl_handle) {
|
if (pdata->send_gpadl.gpadl_handle) {
|
||||||
vmbus_teardown_gpadl(dev->channel, &pdata->send_gpadl);
|
vmbus_teardown_gpadl(dev->channel, &pdata->send_gpadl);
|
||||||
vfree(pdata->send_buf);
|
if (!pdata->send_gpadl.decrypted)
|
||||||
|
vfree(pdata->send_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pdata->recv_gpadl.gpadl_handle) {
|
if (pdata->recv_gpadl.gpadl_handle) {
|
||||||
vmbus_teardown_gpadl(dev->channel, &pdata->recv_gpadl);
|
vmbus_teardown_gpadl(dev->channel, &pdata->recv_gpadl);
|
||||||
vfree(pdata->recv_buf);
|
if (!pdata->recv_gpadl.decrypted)
|
||||||
|
vfree(pdata->recv_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,7 +297,8 @@ hv_uio_probe(struct hv_device *dev,
|
|||||||
ret = vmbus_establish_gpadl(channel, pdata->recv_buf,
|
ret = vmbus_establish_gpadl(channel, pdata->recv_buf,
|
||||||
RECV_BUFFER_SIZE, &pdata->recv_gpadl);
|
RECV_BUFFER_SIZE, &pdata->recv_gpadl);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
vfree(pdata->recv_buf);
|
if (!pdata->recv_gpadl.decrypted)
|
||||||
|
vfree(pdata->recv_buf);
|
||||||
goto fail_close;
|
goto fail_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,7 +320,8 @@ hv_uio_probe(struct hv_device *dev,
|
|||||||
ret = vmbus_establish_gpadl(channel, pdata->send_buf,
|
ret = vmbus_establish_gpadl(channel, pdata->send_buf,
|
||||||
SEND_BUFFER_SIZE, &pdata->send_gpadl);
|
SEND_BUFFER_SIZE, &pdata->send_gpadl);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
vfree(pdata->send_buf);
|
if (!pdata->send_gpadl.decrypted)
|
||||||
|
vfree(pdata->send_buf);
|
||||||
goto fail_close;
|
goto fail_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,13 +512,9 @@ struct hv_proximity_domain_flags {
|
|||||||
u32 proximity_info_valid : 1;
|
u32 proximity_info_valid : 1;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
/* Not a union in windows but useful for zeroing */
|
struct hv_proximity_domain_info {
|
||||||
union hv_proximity_domain_info {
|
u32 domain_id;
|
||||||
struct {
|
struct hv_proximity_domain_flags flags;
|
||||||
u32 domain_id;
|
|
||||||
struct hv_proximity_domain_flags flags;
|
|
||||||
};
|
|
||||||
u64 as_uint64;
|
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct hv_lp_startup_status {
|
struct hv_lp_startup_status {
|
||||||
@ -532,14 +528,13 @@ struct hv_lp_startup_status {
|
|||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
/* HvAddLogicalProcessor hypercall */
|
/* HvAddLogicalProcessor hypercall */
|
||||||
struct hv_add_logical_processor_in {
|
struct hv_input_add_logical_processor {
|
||||||
u32 lp_index;
|
u32 lp_index;
|
||||||
u32 apic_id;
|
u32 apic_id;
|
||||||
union hv_proximity_domain_info proximity_domain_info;
|
struct hv_proximity_domain_info proximity_domain_info;
|
||||||
u64 flags;
|
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct hv_add_logical_processor_out {
|
struct hv_output_add_logical_processor {
|
||||||
struct hv_lp_startup_status startup_status;
|
struct hv_lp_startup_status startup_status;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
@ -560,7 +555,7 @@ struct hv_create_vp {
|
|||||||
u8 padding[3];
|
u8 padding[3];
|
||||||
u8 subnode_type;
|
u8 subnode_type;
|
||||||
u64 subnode_id;
|
u64 subnode_id;
|
||||||
union hv_proximity_domain_info proximity_domain_info;
|
struct hv_proximity_domain_info proximity_domain_info;
|
||||||
u64 flags;
|
u64 flags;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
|
#include <acpi/acpi_numa.h>
|
||||||
#include <linux/cpumask.h>
|
#include <linux/cpumask.h>
|
||||||
#include <linux/nmi.h>
|
#include <linux/nmi.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
@ -67,6 +68,19 @@ extern u64 hv_do_fast_hypercall8(u16 control, u64 input8);
|
|||||||
bool hv_isolation_type_snp(void);
|
bool hv_isolation_type_snp(void);
|
||||||
bool hv_isolation_type_tdx(void);
|
bool hv_isolation_type_tdx(void);
|
||||||
|
|
||||||
|
static inline struct hv_proximity_domain_info hv_numa_node_to_pxm_info(int node)
|
||||||
|
{
|
||||||
|
struct hv_proximity_domain_info pxm_info = {};
|
||||||
|
|
||||||
|
if (node != NUMA_NO_NODE) {
|
||||||
|
pxm_info.domain_id = node_to_pxm(node);
|
||||||
|
pxm_info.flags.proximity_info_valid = 1;
|
||||||
|
pxm_info.flags.proximity_preferred = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pxm_info;
|
||||||
|
}
|
||||||
|
|
||||||
/* Helper functions that provide a consistent pattern for checking Hyper-V hypercall status. */
|
/* Helper functions that provide a consistent pattern for checking Hyper-V hypercall status. */
|
||||||
static inline int hv_result(u64 status)
|
static inline int hv_result(u64 status)
|
||||||
{
|
{
|
||||||
|
@ -832,6 +832,7 @@ struct vmbus_gpadl {
|
|||||||
u32 gpadl_handle;
|
u32 gpadl_handle;
|
||||||
u32 size;
|
u32 size;
|
||||||
void *buffer;
|
void *buffer;
|
||||||
|
bool decrypted;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vmbus_channel {
|
struct vmbus_channel {
|
||||||
|
@ -76,6 +76,12 @@ enum {
|
|||||||
DNS
|
DNS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
IPV4 = 1,
|
||||||
|
IPV6,
|
||||||
|
IP_TYPE_MAX
|
||||||
|
};
|
||||||
|
|
||||||
static int in_hand_shake;
|
static int in_hand_shake;
|
||||||
|
|
||||||
static char *os_name = "";
|
static char *os_name = "";
|
||||||
@ -102,6 +108,11 @@ static struct utsname uts_buf;
|
|||||||
|
|
||||||
#define MAX_FILE_NAME 100
|
#define MAX_FILE_NAME 100
|
||||||
#define ENTRIES_PER_BLOCK 50
|
#define ENTRIES_PER_BLOCK 50
|
||||||
|
/*
|
||||||
|
* Change this entry if the number of addresses increases in future
|
||||||
|
*/
|
||||||
|
#define MAX_IP_ENTRIES 64
|
||||||
|
#define OUTSTR_BUF_SIZE ((INET6_ADDRSTRLEN + 1) * MAX_IP_ENTRIES)
|
||||||
|
|
||||||
struct kvp_record {
|
struct kvp_record {
|
||||||
char key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
|
char key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
|
||||||
@ -1171,6 +1182,18 @@ static int process_ip_string(FILE *f, char *ip_string, int type)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ip_version_check(const char *input_addr)
|
||||||
|
{
|
||||||
|
struct in6_addr addr;
|
||||||
|
|
||||||
|
if (inet_pton(AF_INET, input_addr, &addr))
|
||||||
|
return IPV4;
|
||||||
|
else if (inet_pton(AF_INET6, input_addr, &addr))
|
||||||
|
return IPV6;
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only IPv4 subnet strings needs to be converted to plen
|
* Only IPv4 subnet strings needs to be converted to plen
|
||||||
* For IPv6 the subnet is already privided in plen format
|
* For IPv6 the subnet is already privided in plen format
|
||||||
@ -1197,14 +1220,75 @@ static int kvp_subnet_to_plen(char *subnet_addr_str)
|
|||||||
return plen;
|
return plen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int process_dns_gateway_nm(FILE *f, char *ip_string, int type,
|
||||||
|
int ip_sec)
|
||||||
|
{
|
||||||
|
char addr[INET6_ADDRSTRLEN], *output_str;
|
||||||
|
int ip_offset = 0, error = 0, ip_ver;
|
||||||
|
char *param_name;
|
||||||
|
|
||||||
|
if (type == DNS)
|
||||||
|
param_name = "dns";
|
||||||
|
else if (type == GATEWAY)
|
||||||
|
param_name = "gateway";
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
output_str = (char *)calloc(OUTSTR_BUF_SIZE, sizeof(char));
|
||||||
|
if (!output_str)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
memset(addr, 0, sizeof(addr));
|
||||||
|
|
||||||
|
if (!parse_ip_val_buffer(ip_string, &ip_offset, addr,
|
||||||
|
(MAX_IP_ADDR_SIZE * 2)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
ip_ver = ip_version_check(addr);
|
||||||
|
if (ip_ver < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((ip_ver == IPV4 && ip_sec == IPV4) ||
|
||||||
|
(ip_ver == IPV6 && ip_sec == IPV6)) {
|
||||||
|
/*
|
||||||
|
* do a bound check to avoid out-of bound writes
|
||||||
|
*/
|
||||||
|
if ((OUTSTR_BUF_SIZE - strlen(output_str)) >
|
||||||
|
(strlen(addr) + 1)) {
|
||||||
|
strncat(output_str, addr,
|
||||||
|
OUTSTR_BUF_SIZE -
|
||||||
|
strlen(output_str) - 1);
|
||||||
|
strncat(output_str, ",",
|
||||||
|
OUTSTR_BUF_SIZE -
|
||||||
|
strlen(output_str) - 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(output_str)) {
|
||||||
|
/*
|
||||||
|
* This is to get rid of that extra comma character
|
||||||
|
* in the end of the string
|
||||||
|
*/
|
||||||
|
output_str[strlen(output_str) - 1] = '\0';
|
||||||
|
error = fprintf(f, "%s=%s\n", param_name, output_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(output_str);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet,
|
static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet,
|
||||||
int is_ipv6)
|
int ip_sec)
|
||||||
{
|
{
|
||||||
char addr[INET6_ADDRSTRLEN];
|
char addr[INET6_ADDRSTRLEN];
|
||||||
char subnet_addr[INET6_ADDRSTRLEN];
|
char subnet_addr[INET6_ADDRSTRLEN];
|
||||||
int error, i = 0;
|
int error = 0, i = 0;
|
||||||
int ip_offset = 0, subnet_offset = 0;
|
int ip_offset = 0, subnet_offset = 0;
|
||||||
int plen;
|
int plen, ip_ver;
|
||||||
|
|
||||||
memset(addr, 0, sizeof(addr));
|
memset(addr, 0, sizeof(addr));
|
||||||
memset(subnet_addr, 0, sizeof(subnet_addr));
|
memset(subnet_addr, 0, sizeof(subnet_addr));
|
||||||
@ -1216,10 +1300,16 @@ static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet,
|
|||||||
subnet_addr,
|
subnet_addr,
|
||||||
(MAX_IP_ADDR_SIZE *
|
(MAX_IP_ADDR_SIZE *
|
||||||
2))) {
|
2))) {
|
||||||
if (!is_ipv6)
|
ip_ver = ip_version_check(addr);
|
||||||
|
if (ip_ver < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ip_ver == IPV4 && ip_sec == IPV4)
|
||||||
plen = kvp_subnet_to_plen((char *)subnet_addr);
|
plen = kvp_subnet_to_plen((char *)subnet_addr);
|
||||||
else
|
else if (ip_ver == IPV6 && ip_sec == IPV6)
|
||||||
plen = atoi(subnet_addr);
|
plen = atoi(subnet_addr);
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
if (plen < 0)
|
if (plen < 0)
|
||||||
return plen;
|
return plen;
|
||||||
@ -1233,17 +1323,16 @@ static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet,
|
|||||||
memset(subnet_addr, 0, sizeof(subnet_addr));
|
memset(subnet_addr, 0, sizeof(subnet_addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||||
{
|
{
|
||||||
int error = 0;
|
int error = 0, ip_ver;
|
||||||
char if_filename[PATH_MAX];
|
char if_filename[PATH_MAX];
|
||||||
char nm_filename[PATH_MAX];
|
char nm_filename[PATH_MAX];
|
||||||
FILE *ifcfg_file, *nmfile;
|
FILE *ifcfg_file, *nmfile;
|
||||||
char cmd[PATH_MAX];
|
char cmd[PATH_MAX];
|
||||||
int is_ipv6 = 0;
|
|
||||||
char *mac_addr;
|
char *mac_addr;
|
||||||
int str_len;
|
int str_len;
|
||||||
|
|
||||||
@ -1421,52 +1510,94 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
|||||||
if (error)
|
if (error)
|
||||||
goto setval_error;
|
goto setval_error;
|
||||||
|
|
||||||
if (new_val->addr_family & ADDR_FAMILY_IPV6) {
|
|
||||||
error = fprintf(nmfile, "\n[ipv6]\n");
|
|
||||||
if (error < 0)
|
|
||||||
goto setval_error;
|
|
||||||
is_ipv6 = 1;
|
|
||||||
} else {
|
|
||||||
error = fprintf(nmfile, "\n[ipv4]\n");
|
|
||||||
if (error < 0)
|
|
||||||
goto setval_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now we populate the keyfile format
|
* Now we populate the keyfile format
|
||||||
|
*
|
||||||
|
* The keyfile format expects the IPv6 and IPv4 configuration in
|
||||||
|
* different sections. Therefore we iterate through the list twice,
|
||||||
|
* once to populate the IPv4 section and the next time for IPv6
|
||||||
*/
|
*/
|
||||||
|
ip_ver = IPV4;
|
||||||
|
do {
|
||||||
|
if (ip_ver == IPV4) {
|
||||||
|
error = fprintf(nmfile, "\n[ipv4]\n");
|
||||||
|
if (error < 0)
|
||||||
|
goto setval_error;
|
||||||
|
} else {
|
||||||
|
error = fprintf(nmfile, "\n[ipv6]\n");
|
||||||
|
if (error < 0)
|
||||||
|
goto setval_error;
|
||||||
|
}
|
||||||
|
|
||||||
if (new_val->dhcp_enabled) {
|
/*
|
||||||
error = kvp_write_file(nmfile, "method", "", "auto");
|
* Write the configuration for ipaddress, netmask, gateway and
|
||||||
|
* name services
|
||||||
|
*/
|
||||||
|
error = process_ip_string_nm(nmfile, (char *)new_val->ip_addr,
|
||||||
|
(char *)new_val->sub_net,
|
||||||
|
ip_ver);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto setval_error;
|
goto setval_error;
|
||||||
} else {
|
|
||||||
error = kvp_write_file(nmfile, "method", "", "manual");
|
/*
|
||||||
|
* As dhcp_enabled is only valid for ipv4, we do not set dhcp
|
||||||
|
* methods for ipv6 based on dhcp_enabled flag.
|
||||||
|
*
|
||||||
|
* For ipv4, set method to manual only when dhcp_enabled is
|
||||||
|
* false and specific ipv4 addresses are configured. If neither
|
||||||
|
* dhcp_enabled is true and no ipv4 addresses are configured,
|
||||||
|
* set method to 'disabled'.
|
||||||
|
*
|
||||||
|
* For ipv6, set method to manual when we configure ipv6
|
||||||
|
* addresses. Otherwise set method to 'auto' so that SLAAC from
|
||||||
|
* RA may be used.
|
||||||
|
*/
|
||||||
|
if (ip_ver == IPV4) {
|
||||||
|
if (new_val->dhcp_enabled) {
|
||||||
|
error = kvp_write_file(nmfile, "method", "",
|
||||||
|
"auto");
|
||||||
|
if (error < 0)
|
||||||
|
goto setval_error;
|
||||||
|
} else if (error) {
|
||||||
|
error = kvp_write_file(nmfile, "method", "",
|
||||||
|
"manual");
|
||||||
|
if (error < 0)
|
||||||
|
goto setval_error;
|
||||||
|
} else {
|
||||||
|
error = kvp_write_file(nmfile, "method", "",
|
||||||
|
"disabled");
|
||||||
|
if (error < 0)
|
||||||
|
goto setval_error;
|
||||||
|
}
|
||||||
|
} else if (ip_ver == IPV6) {
|
||||||
|
if (error) {
|
||||||
|
error = kvp_write_file(nmfile, "method", "",
|
||||||
|
"manual");
|
||||||
|
if (error < 0)
|
||||||
|
goto setval_error;
|
||||||
|
} else {
|
||||||
|
error = kvp_write_file(nmfile, "method", "",
|
||||||
|
"auto");
|
||||||
|
if (error < 0)
|
||||||
|
goto setval_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error = process_dns_gateway_nm(nmfile,
|
||||||
|
(char *)new_val->gate_way,
|
||||||
|
GATEWAY, ip_ver);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto setval_error;
|
goto setval_error;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
error = process_dns_gateway_nm(nmfile,
|
||||||
* Write the configuration for ipaddress, netmask, gateway and
|
(char *)new_val->dns_addr, DNS,
|
||||||
* name services
|
ip_ver);
|
||||||
*/
|
|
||||||
error = process_ip_string_nm(nmfile, (char *)new_val->ip_addr,
|
|
||||||
(char *)new_val->sub_net, is_ipv6);
|
|
||||||
if (error < 0)
|
|
||||||
goto setval_error;
|
|
||||||
|
|
||||||
/* we do not want ipv4 addresses in ipv6 section and vice versa */
|
|
||||||
if (is_ipv6 != is_ipv4((char *)new_val->gate_way)) {
|
|
||||||
error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way);
|
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto setval_error;
|
goto setval_error;
|
||||||
}
|
|
||||||
|
|
||||||
if (is_ipv6 != is_ipv4((char *)new_val->dns_addr)) {
|
ip_ver++;
|
||||||
error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr);
|
} while (ip_ver < IP_TYPE_MAX);
|
||||||
if (error < 0)
|
|
||||||
goto setval_error;
|
|
||||||
}
|
|
||||||
fclose(nmfile);
|
fclose(nmfile);
|
||||||
fclose(ifcfg_file);
|
fclose(ifcfg_file);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user