xref: /dpdk/examples/vm_power_manager/channel_manager.c (revision 96d3d532f9f2e42cf8b620ad3ba9da1f04ccb3f0)
13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
23998e2a0SBruce Richardson  * Copyright(c) 2010-2014 Intel Corporation
3e8ae9b66SAlan Carew  */
4e8ae9b66SAlan Carew 
5e8ae9b66SAlan Carew #include <stdio.h>
6e8ae9b66SAlan Carew #include <stdlib.h>
7e8ae9b66SAlan Carew #include <sys/un.h>
8e8ae9b66SAlan Carew #include <fcntl.h>
9e8ae9b66SAlan Carew #include <unistd.h>
10e8ae9b66SAlan Carew #include <inttypes.h>
11e8ae9b66SAlan Carew #include <dirent.h>
12e8ae9b66SAlan Carew #include <errno.h>
13e8ae9b66SAlan Carew 
14e8ae9b66SAlan Carew #include <sys/queue.h>
15e8ae9b66SAlan Carew #include <sys/types.h>
163618326fSDavid Hunt #include <sys/stat.h>
17e8ae9b66SAlan Carew #include <sys/socket.h>
18e8ae9b66SAlan Carew #include <sys/select.h>
19e8ae9b66SAlan Carew 
206723c0fcSBruce Richardson #include <rte_string_fns.h>
21e8ae9b66SAlan Carew #include <rte_malloc.h>
22e8ae9b66SAlan Carew #include <rte_memory.h>
23e8ae9b66SAlan Carew #include <rte_mempool.h>
24e8ae9b66SAlan Carew #include <rte_log.h>
25e8ae9b66SAlan Carew #include <rte_atomic.h>
26e8ae9b66SAlan Carew #include <rte_spinlock.h>
27e8ae9b66SAlan Carew 
28e8ae9b66SAlan Carew #include <libvirt/libvirt.h>
29e8ae9b66SAlan Carew 
30e8ae9b66SAlan Carew #include "channel_manager.h"
31e8ae9b66SAlan Carew #include "channel_commands.h"
32e8ae9b66SAlan Carew #include "channel_monitor.h"
33fd73630eSDavid Hunt #include "power_manager.h"
34e8ae9b66SAlan Carew 
35e8ae9b66SAlan Carew 
36e8ae9b66SAlan Carew #define RTE_LOGTYPE_CHANNEL_MANAGER RTE_LOGTYPE_USER1
37e8ae9b66SAlan Carew 
38*96d3d532SThomas Monjalon struct libvirt_vm_info lvm_info[MAX_CLIENTS];
39*96d3d532SThomas Monjalon 
40e8ae9b66SAlan Carew /* Global pointer to libvirt connection */
41e8ae9b66SAlan Carew static virConnectPtr global_vir_conn_ptr;
42e8ae9b66SAlan Carew 
43e8ae9b66SAlan Carew static unsigned char *global_cpumaps;
44e8ae9b66SAlan Carew static virVcpuInfo *global_vircpuinfo;
45e8ae9b66SAlan Carew static size_t global_maplen;
46e8ae9b66SAlan Carew 
47e0207366SDavid Hunt static unsigned int global_n_host_cpus;
48e0207366SDavid Hunt static bool global_hypervisor_available;
49e8ae9b66SAlan Carew 
50e8ae9b66SAlan Carew /*
51e8ae9b66SAlan Carew  * Represents a single Virtual Machine
52e8ae9b66SAlan Carew  */
53e8ae9b66SAlan Carew struct virtual_machine_info {
54e8ae9b66SAlan Carew 	char name[CHANNEL_MGR_MAX_NAME_LEN];
55751227a0SDavid Hunt 	uint16_t pcpu_map[RTE_MAX_LCORE];
56751227a0SDavid Hunt 	struct channel_info *channels[RTE_MAX_LCORE];
57751227a0SDavid Hunt 	char channel_mask[RTE_MAX_LCORE];
58e8ae9b66SAlan Carew 	uint8_t num_channels;
59e8ae9b66SAlan Carew 	enum vm_status status;
60e8ae9b66SAlan Carew 	virDomainPtr domainPtr;
61e8ae9b66SAlan Carew 	virDomainInfo info;
62e8ae9b66SAlan Carew 	rte_spinlock_t config_spinlock;
631deb502eSMarcin Hajkowski 	int allow_query;
64e8ae9b66SAlan Carew 	LIST_ENTRY(virtual_machine_info) vms_info;
65e8ae9b66SAlan Carew };
66e8ae9b66SAlan Carew 
67e8ae9b66SAlan Carew LIST_HEAD(, virtual_machine_info) vm_list_head;
68e8ae9b66SAlan Carew 
69e8ae9b66SAlan Carew static struct virtual_machine_info *
70e8ae9b66SAlan Carew find_domain_by_name(const char *name)
71e8ae9b66SAlan Carew {
72e8ae9b66SAlan Carew 	struct virtual_machine_info *info;
73e8ae9b66SAlan Carew 	LIST_FOREACH(info, &vm_list_head, vms_info) {
74e8ae9b66SAlan Carew 		if (!strncmp(info->name, name, CHANNEL_MGR_MAX_NAME_LEN-1))
75e8ae9b66SAlan Carew 			return info;
76e8ae9b66SAlan Carew 	}
77e8ae9b66SAlan Carew 	return NULL;
78e8ae9b66SAlan Carew }
79e8ae9b66SAlan Carew 
80e8ae9b66SAlan Carew static int
81e8ae9b66SAlan Carew update_pcpus_mask(struct virtual_machine_info *vm_info)
82e8ae9b66SAlan Carew {
83e8ae9b66SAlan Carew 	virVcpuInfoPtr cpuinfo;
84e8ae9b66SAlan Carew 	unsigned i, j;
85e8ae9b66SAlan Carew 	int n_vcpus;
86e8ae9b66SAlan Carew 
87751227a0SDavid Hunt 	memset(global_cpumaps, 0, RTE_MAX_LCORE*global_maplen);
88e8ae9b66SAlan Carew 
89e8ae9b66SAlan Carew 	if (!virDomainIsActive(vm_info->domainPtr)) {
90e8ae9b66SAlan Carew 		n_vcpus = virDomainGetVcpuPinInfo(vm_info->domainPtr,
91e8ae9b66SAlan Carew 				vm_info->info.nrVirtCpu, global_cpumaps, global_maplen,
92e8ae9b66SAlan Carew 				VIR_DOMAIN_AFFECT_CONFIG);
93e8ae9b66SAlan Carew 		if (n_vcpus < 0) {
94e8ae9b66SAlan Carew 			RTE_LOG(ERR, CHANNEL_MANAGER, "Error getting vCPU info for "
95e8ae9b66SAlan Carew 					"in-active VM '%s'\n", vm_info->name);
96e8ae9b66SAlan Carew 			return -1;
97e8ae9b66SAlan Carew 		}
98e8ae9b66SAlan Carew 		goto update_pcpus;
99e8ae9b66SAlan Carew 	}
100e8ae9b66SAlan Carew 
101e8ae9b66SAlan Carew 	memset(global_vircpuinfo, 0, sizeof(*global_vircpuinfo)*
102751227a0SDavid Hunt 			RTE_MAX_LCORE);
103e8ae9b66SAlan Carew 
104e8ae9b66SAlan Carew 	cpuinfo = global_vircpuinfo;
105e8ae9b66SAlan Carew 
106e8ae9b66SAlan Carew 	n_vcpus = virDomainGetVcpus(vm_info->domainPtr, cpuinfo,
107751227a0SDavid Hunt 			RTE_MAX_LCORE, global_cpumaps, global_maplen);
108e8ae9b66SAlan Carew 	if (n_vcpus < 0) {
109e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error getting vCPU info for "
110e8ae9b66SAlan Carew 				"active VM '%s'\n", vm_info->name);
111e8ae9b66SAlan Carew 		return -1;
112e8ae9b66SAlan Carew 	}
113e8ae9b66SAlan Carew update_pcpus:
114751227a0SDavid Hunt 	if (n_vcpus >= RTE_MAX_LCORE) {
115e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Number of vCPUS(%u) is out of range "
116751227a0SDavid Hunt 				"0...%d\n", n_vcpus, RTE_MAX_LCORE-1);
117e8ae9b66SAlan Carew 		return -1;
118e8ae9b66SAlan Carew 	}
119e8ae9b66SAlan Carew 	if (n_vcpus != vm_info->info.nrVirtCpu) {
120e8ae9b66SAlan Carew 		RTE_LOG(INFO, CHANNEL_MANAGER, "Updating the number of vCPUs for VM '%s"
121e8ae9b66SAlan Carew 				" from %d -> %d\n", vm_info->name, vm_info->info.nrVirtCpu,
122e8ae9b66SAlan Carew 				n_vcpus);
123e8ae9b66SAlan Carew 		vm_info->info.nrVirtCpu = n_vcpus;
124e8ae9b66SAlan Carew 	}
1255776b7a3SDavid Hunt 	rte_spinlock_lock(&(vm_info->config_spinlock));
126e8ae9b66SAlan Carew 	for (i = 0; i < vm_info->info.nrVirtCpu; i++) {
127e8ae9b66SAlan Carew 		for (j = 0; j < global_n_host_cpus; j++) {
1285776b7a3SDavid Hunt 			if (VIR_CPU_USABLE(global_cpumaps,
1295776b7a3SDavid Hunt 					global_maplen, i, j) <= 0)
1305776b7a3SDavid Hunt 				continue;
1315776b7a3SDavid Hunt 			vm_info->pcpu_map[i] = j;
132e8ae9b66SAlan Carew 		}
133e8ae9b66SAlan Carew 	}
1345776b7a3SDavid Hunt 	rte_spinlock_unlock(&(vm_info->config_spinlock));
135e8ae9b66SAlan Carew 	return 0;
136e8ae9b66SAlan Carew }
137e8ae9b66SAlan Carew 
138e8ae9b66SAlan Carew int
1395776b7a3SDavid Hunt set_pcpu(char *vm_name, unsigned int vcpu, unsigned int pcpu)
140e8ae9b66SAlan Carew {
141e8ae9b66SAlan Carew 	int flags = VIR_DOMAIN_AFFECT_LIVE|VIR_DOMAIN_AFFECT_CONFIG;
142e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info;
143e8ae9b66SAlan Carew 
144751227a0SDavid Hunt 	if (vcpu >= RTE_MAX_LCORE) {
145e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "vCPU(%u) exceeds max allowable(%d)\n",
146751227a0SDavid Hunt 				vcpu, RTE_MAX_LCORE-1);
147e8ae9b66SAlan Carew 		return -1;
148e8ae9b66SAlan Carew 	}
149e8ae9b66SAlan Carew 
150e8ae9b66SAlan Carew 	vm_info = find_domain_by_name(vm_name);
151e8ae9b66SAlan Carew 	if (vm_info == NULL) {
152e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "VM '%s' not found\n", vm_name);
153e8ae9b66SAlan Carew 		return -1;
154e8ae9b66SAlan Carew 	}
155e8ae9b66SAlan Carew 
156e8ae9b66SAlan Carew 	if (!virDomainIsActive(vm_info->domainPtr)) {
157e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to set vCPU(%u) to pCPU "
158fd73630eSDavid Hunt 				" for VM '%s', VM is not active\n",
159fd73630eSDavid Hunt 				vcpu, vm_info->name);
160e8ae9b66SAlan Carew 		return -1;
161e8ae9b66SAlan Carew 	}
162e8ae9b66SAlan Carew 
163e8ae9b66SAlan Carew 	if (vcpu >= vm_info->info.nrVirtCpu) {
164e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "vCPU(%u) exceeds the assigned number of "
165e8ae9b66SAlan Carew 				"vCPUs(%u)\n", vcpu, vm_info->info.nrVirtCpu);
166e8ae9b66SAlan Carew 		return -1;
167e8ae9b66SAlan Carew 	}
168751227a0SDavid Hunt 	memset(global_cpumaps, 0, RTE_MAX_LCORE * global_maplen);
1695776b7a3SDavid Hunt 
1705776b7a3SDavid Hunt 	VIR_USE_CPU(global_cpumaps, pcpu);
1715776b7a3SDavid Hunt 
1725776b7a3SDavid Hunt 	if (pcpu >= global_n_host_cpus) {
173e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "CPU(%u) exceeds the available "
174fd73630eSDavid Hunt 				"number of CPUs(%u)\n",
1755776b7a3SDavid Hunt 				pcpu, global_n_host_cpus);
176e8ae9b66SAlan Carew 		return -1;
177e8ae9b66SAlan Carew 	}
1785776b7a3SDavid Hunt 
179e8ae9b66SAlan Carew 	if (virDomainPinVcpuFlags(vm_info->domainPtr, vcpu, global_cpumaps,
180e8ae9b66SAlan Carew 			global_maplen, flags) < 0) {
181e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to set vCPU(%u) to pCPU "
182fd73630eSDavid Hunt 				" for VM '%s'\n", vcpu,
183e8ae9b66SAlan Carew 				vm_info->name);
184e8ae9b66SAlan Carew 		return -1;
185e8ae9b66SAlan Carew 	}
186fd73630eSDavid Hunt 	rte_spinlock_lock(&(vm_info->config_spinlock));
1875776b7a3SDavid Hunt 	vm_info->pcpu_map[vcpu] = pcpu;
188fd73630eSDavid Hunt 	rte_spinlock_unlock(&(vm_info->config_spinlock));
189e8ae9b66SAlan Carew 	return 0;
190e8ae9b66SAlan Carew }
191e8ae9b66SAlan Carew 
1925776b7a3SDavid Hunt uint16_t
1935776b7a3SDavid Hunt get_pcpu(struct channel_info *chan_info, unsigned int vcpu)
194e8ae9b66SAlan Carew {
195e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info =
196e8ae9b66SAlan Carew 			(struct virtual_machine_info *)chan_info->priv_info;
197e0207366SDavid Hunt 
1985776b7a3SDavid Hunt 	if (global_hypervisor_available && (vm_info != NULL)) {
1995776b7a3SDavid Hunt 		uint16_t pcpu;
2005776b7a3SDavid Hunt 		rte_spinlock_lock(&(vm_info->config_spinlock));
2015776b7a3SDavid Hunt 		pcpu = vm_info->pcpu_map[vcpu];
2025776b7a3SDavid Hunt 		rte_spinlock_unlock(&(vm_info->config_spinlock));
2035776b7a3SDavid Hunt 		return pcpu;
2045776b7a3SDavid Hunt 	} else
205e0207366SDavid Hunt 		return 0;
206e8ae9b66SAlan Carew }
207e8ae9b66SAlan Carew 
208e8ae9b66SAlan Carew static inline int
209e8ae9b66SAlan Carew channel_exists(struct virtual_machine_info *vm_info, unsigned channel_num)
210e8ae9b66SAlan Carew {
211e8ae9b66SAlan Carew 	rte_spinlock_lock(&(vm_info->config_spinlock));
212fd73630eSDavid Hunt 	if (vm_info->channel_mask[channel_num] == 1) {
213e8ae9b66SAlan Carew 		rte_spinlock_unlock(&(vm_info->config_spinlock));
214e8ae9b66SAlan Carew 		return 1;
215e8ae9b66SAlan Carew 	}
216e8ae9b66SAlan Carew 	rte_spinlock_unlock(&(vm_info->config_spinlock));
217e8ae9b66SAlan Carew 	return 0;
218e8ae9b66SAlan Carew }
219e8ae9b66SAlan Carew 
220e8ae9b66SAlan Carew 
221e8ae9b66SAlan Carew 
222e8ae9b66SAlan Carew static int
223e8ae9b66SAlan Carew open_non_blocking_channel(struct channel_info *info)
224e8ae9b66SAlan Carew {
225e8ae9b66SAlan Carew 	int ret, flags;
226e8ae9b66SAlan Carew 	struct sockaddr_un sock_addr;
227e8ae9b66SAlan Carew 	fd_set soc_fd_set;
228e8ae9b66SAlan Carew 	struct timeval tv;
229e8ae9b66SAlan Carew 
230e8ae9b66SAlan Carew 	info->fd = socket(AF_UNIX, SOCK_STREAM, 0);
2311b897991SLukasz Krakowiak 	if (info->fd < 0) {
232e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error(%s) creating socket for '%s'\n",
233e8ae9b66SAlan Carew 				strerror(errno),
234e8ae9b66SAlan Carew 				info->channel_path);
235e8ae9b66SAlan Carew 		return -1;
236e8ae9b66SAlan Carew 	}
237e8ae9b66SAlan Carew 	sock_addr.sun_family = AF_UNIX;
238e8ae9b66SAlan Carew 	memcpy(&sock_addr.sun_path, info->channel_path,
239e8ae9b66SAlan Carew 			strlen(info->channel_path)+1);
240e8ae9b66SAlan Carew 
241e8ae9b66SAlan Carew 	/* Get current flags */
242e8ae9b66SAlan Carew 	flags = fcntl(info->fd, F_GETFL, 0);
243e8ae9b66SAlan Carew 	if (flags < 0) {
244e8ae9b66SAlan Carew 		RTE_LOG(WARNING, CHANNEL_MANAGER, "Error(%s) fcntl get flags socket for"
245e8ae9b66SAlan Carew 				"'%s'\n", strerror(errno), info->channel_path);
246e8ae9b66SAlan Carew 		return 1;
247e8ae9b66SAlan Carew 	}
248e8ae9b66SAlan Carew 	/* Set to Non Blocking */
249e8ae9b66SAlan Carew 	flags |= O_NONBLOCK;
250e8ae9b66SAlan Carew 	if (fcntl(info->fd, F_SETFL, flags) < 0) {
251e8ae9b66SAlan Carew 		RTE_LOG(WARNING, CHANNEL_MANAGER, "Error(%s) setting non-blocking "
252e8ae9b66SAlan Carew 				"socket for '%s'\n", strerror(errno), info->channel_path);
253e8ae9b66SAlan Carew 		return -1;
254e8ae9b66SAlan Carew 	}
255e8ae9b66SAlan Carew 	ret = connect(info->fd, (struct sockaddr *)&sock_addr,
256e8ae9b66SAlan Carew 			sizeof(sock_addr));
257e8ae9b66SAlan Carew 	if (ret < 0) {
258e8ae9b66SAlan Carew 		/* ECONNREFUSED error is given when VM is not active */
259e8ae9b66SAlan Carew 		if (errno == ECONNREFUSED) {
260e8ae9b66SAlan Carew 			RTE_LOG(WARNING, CHANNEL_MANAGER, "VM is not active or has not "
261e8ae9b66SAlan Carew 					"activated its endpoint to channel %s\n",
262e8ae9b66SAlan Carew 					info->channel_path);
263e8ae9b66SAlan Carew 			return -1;
264e8ae9b66SAlan Carew 		}
265e8ae9b66SAlan Carew 		/* Wait for tv_sec if in progress */
266e8ae9b66SAlan Carew 		else if (errno == EINPROGRESS) {
267e8ae9b66SAlan Carew 			tv.tv_sec = 2;
268e8ae9b66SAlan Carew 			tv.tv_usec = 0;
269e8ae9b66SAlan Carew 			FD_ZERO(&soc_fd_set);
270e8ae9b66SAlan Carew 			FD_SET(info->fd, &soc_fd_set);
271e8ae9b66SAlan Carew 			if (select(info->fd+1, NULL, &soc_fd_set, NULL, &tv) > 0) {
272e8ae9b66SAlan Carew 				RTE_LOG(WARNING, CHANNEL_MANAGER, "Timeout or error on channel "
273e8ae9b66SAlan Carew 						"'%s'\n", info->channel_path);
274e8ae9b66SAlan Carew 				return -1;
275e8ae9b66SAlan Carew 			}
276e8ae9b66SAlan Carew 		} else {
277e8ae9b66SAlan Carew 			/* Any other error */
278e8ae9b66SAlan Carew 			RTE_LOG(WARNING, CHANNEL_MANAGER, "Error(%s) connecting socket"
279e8ae9b66SAlan Carew 					" for '%s'\n", strerror(errno), info->channel_path);
280e8ae9b66SAlan Carew 			return -1;
281e8ae9b66SAlan Carew 		}
282e8ae9b66SAlan Carew 	}
283e8ae9b66SAlan Carew 	return 0;
284e8ae9b66SAlan Carew }
285e8ae9b66SAlan Carew 
286e8ae9b66SAlan Carew static int
2873618326fSDavid Hunt open_host_channel(struct channel_info *info)
2883618326fSDavid Hunt {
2893618326fSDavid Hunt 	int flags;
2903618326fSDavid Hunt 
2913618326fSDavid Hunt 	info->fd = open(info->channel_path, O_RDWR | O_RSYNC);
2921b897991SLukasz Krakowiak 	if (info->fd < 0) {
2933618326fSDavid Hunt 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error(%s) opening fifo for '%s'\n",
2943618326fSDavid Hunt 				strerror(errno),
2953618326fSDavid Hunt 				info->channel_path);
2963618326fSDavid Hunt 		return -1;
2973618326fSDavid Hunt 	}
2983618326fSDavid Hunt 
2993618326fSDavid Hunt 	/* Get current flags */
3003618326fSDavid Hunt 	flags = fcntl(info->fd, F_GETFL, 0);
3013618326fSDavid Hunt 	if (flags < 0) {
3023618326fSDavid Hunt 		RTE_LOG(WARNING, CHANNEL_MANAGER, "Error(%s) fcntl get flags socket for"
3033618326fSDavid Hunt 				"'%s'\n", strerror(errno), info->channel_path);
3043618326fSDavid Hunt 		return 1;
3053618326fSDavid Hunt 	}
3063618326fSDavid Hunt 	/* Set to Non Blocking */
3073618326fSDavid Hunt 	flags |= O_NONBLOCK;
3083618326fSDavid Hunt 	if (fcntl(info->fd, F_SETFL, flags) < 0) {
3093618326fSDavid Hunt 		RTE_LOG(WARNING, CHANNEL_MANAGER,
3103618326fSDavid Hunt 				"Error(%s) setting non-blocking "
3113618326fSDavid Hunt 				"socket for '%s'\n",
3123618326fSDavid Hunt 				strerror(errno), info->channel_path);
3133618326fSDavid Hunt 		return -1;
3143618326fSDavid Hunt 	}
3153618326fSDavid Hunt 	return 0;
3163618326fSDavid Hunt }
3173618326fSDavid Hunt 
3183618326fSDavid Hunt static int
319e8ae9b66SAlan Carew setup_channel_info(struct virtual_machine_info **vm_info_dptr,
320e8ae9b66SAlan Carew 		struct channel_info **chan_info_dptr, unsigned channel_num)
321e8ae9b66SAlan Carew {
322e8ae9b66SAlan Carew 	struct channel_info *chan_info = *chan_info_dptr;
323e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info = *vm_info_dptr;
324e8ae9b66SAlan Carew 
325e8ae9b66SAlan Carew 	chan_info->channel_num = channel_num;
326e8ae9b66SAlan Carew 	chan_info->priv_info = (void *)vm_info;
327e8ae9b66SAlan Carew 	chan_info->status = CHANNEL_MGR_CHANNEL_DISCONNECTED;
3283618326fSDavid Hunt 	chan_info->type = CHANNEL_TYPE_BINARY;
329e8ae9b66SAlan Carew 	if (open_non_blocking_channel(chan_info) < 0) {
330e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Could not open channel: "
331e8ae9b66SAlan Carew 				"'%s' for VM '%s'\n",
332e8ae9b66SAlan Carew 				chan_info->channel_path, vm_info->name);
333e8ae9b66SAlan Carew 		return -1;
334e8ae9b66SAlan Carew 	}
335e8ae9b66SAlan Carew 	if (add_channel_to_monitor(&chan_info) < 0) {
336e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Could add channel: "
337e8ae9b66SAlan Carew 				"'%s' to epoll ctl for VM '%s'\n",
338e8ae9b66SAlan Carew 				chan_info->channel_path, vm_info->name);
339e8ae9b66SAlan Carew 		return -1;
340e8ae9b66SAlan Carew 
341e8ae9b66SAlan Carew 	}
342e8ae9b66SAlan Carew 	rte_spinlock_lock(&(vm_info->config_spinlock));
343e8ae9b66SAlan Carew 	vm_info->num_channels++;
344fd73630eSDavid Hunt 	vm_info->channel_mask[channel_num] = 1;
345e8ae9b66SAlan Carew 	vm_info->channels[channel_num] = chan_info;
346e8ae9b66SAlan Carew 	chan_info->status = CHANNEL_MGR_CHANNEL_CONNECTED;
347e8ae9b66SAlan Carew 	rte_spinlock_unlock(&(vm_info->config_spinlock));
348e8ae9b66SAlan Carew 	return 0;
349e8ae9b66SAlan Carew }
350e8ae9b66SAlan Carew 
351221e7026SMarcin Hajkowski static int
352221e7026SMarcin Hajkowski fifo_path(char *dst, unsigned int len, unsigned int id)
3533618326fSDavid Hunt {
354221e7026SMarcin Hajkowski 	int cnt;
355221e7026SMarcin Hajkowski 
356221e7026SMarcin Hajkowski 	cnt = snprintf(dst, len, "%s%s%d", CHANNEL_MGR_SOCKET_PATH,
357221e7026SMarcin Hajkowski 			CHANNEL_MGR_FIFO_PATTERN_NAME, id);
358221e7026SMarcin Hajkowski 
359221e7026SMarcin Hajkowski 	if ((cnt < 0) || (cnt > (int)len - 1)) {
360221e7026SMarcin Hajkowski 		RTE_LOG(ERR, CHANNEL_MANAGER, "Could not create proper "
361221e7026SMarcin Hajkowski 			"string for fifo path\n");
362221e7026SMarcin Hajkowski 
363221e7026SMarcin Hajkowski 		return -1;
364221e7026SMarcin Hajkowski 	}
365221e7026SMarcin Hajkowski 
366221e7026SMarcin Hajkowski 	return 0;
3673618326fSDavid Hunt }
3683618326fSDavid Hunt 
3693618326fSDavid Hunt static int
3703618326fSDavid Hunt setup_host_channel_info(struct channel_info **chan_info_dptr,
3713618326fSDavid Hunt 		unsigned int channel_num)
3723618326fSDavid Hunt {
3733618326fSDavid Hunt 	struct channel_info *chan_info = *chan_info_dptr;
3743618326fSDavid Hunt 
3753618326fSDavid Hunt 	chan_info->channel_num = channel_num;
3763618326fSDavid Hunt 	chan_info->priv_info = (void *)NULL;
3773618326fSDavid Hunt 	chan_info->status = CHANNEL_MGR_CHANNEL_DISCONNECTED;
3783618326fSDavid Hunt 	chan_info->type = CHANNEL_TYPE_JSON;
3793618326fSDavid Hunt 
3803618326fSDavid Hunt 	if (open_host_channel(chan_info) < 0) {
3813618326fSDavid Hunt 		RTE_LOG(ERR, CHANNEL_MANAGER, "Could not open host channel: "
3823618326fSDavid Hunt 				"'%s'\n",
3833618326fSDavid Hunt 				chan_info->channel_path);
3843618326fSDavid Hunt 		return -1;
3853618326fSDavid Hunt 	}
3863618326fSDavid Hunt 	if (add_channel_to_monitor(&chan_info) < 0) {
3873618326fSDavid Hunt 		RTE_LOG(ERR, CHANNEL_MANAGER, "Could add channel: "
3883618326fSDavid Hunt 				"'%s' to epoll ctl\n",
3893618326fSDavid Hunt 				chan_info->channel_path);
3903618326fSDavid Hunt 		return -1;
3913618326fSDavid Hunt 
3923618326fSDavid Hunt 	}
3933618326fSDavid Hunt 	chan_info->status = CHANNEL_MGR_CHANNEL_CONNECTED;
3943618326fSDavid Hunt 	return 0;
3953618326fSDavid Hunt }
3963618326fSDavid Hunt 
397e8ae9b66SAlan Carew int
398e8ae9b66SAlan Carew add_all_channels(const char *vm_name)
399e8ae9b66SAlan Carew {
400e8ae9b66SAlan Carew 	DIR *d;
401e8ae9b66SAlan Carew 	struct dirent *dir;
402e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info;
403e8ae9b66SAlan Carew 	struct channel_info *chan_info;
404e8ae9b66SAlan Carew 	char *token, *remaining, *tail_ptr;
405e8ae9b66SAlan Carew 	char socket_name[PATH_MAX];
406e8ae9b66SAlan Carew 	unsigned channel_num;
407e8ae9b66SAlan Carew 	int num_channels_enabled = 0;
408e8ae9b66SAlan Carew 
409e8ae9b66SAlan Carew 	/* verify VM exists */
410e8ae9b66SAlan Carew 	vm_info = find_domain_by_name(vm_name);
411e8ae9b66SAlan Carew 	if (vm_info == NULL) {
412e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "VM: '%s' not found"
413e8ae9b66SAlan Carew 				" during channel discovery\n", vm_name);
414e8ae9b66SAlan Carew 		return 0;
415e8ae9b66SAlan Carew 	}
416e8ae9b66SAlan Carew 	if (!virDomainIsActive(vm_info->domainPtr)) {
417e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "VM: '%s' is not active\n", vm_name);
418e8ae9b66SAlan Carew 		vm_info->status = CHANNEL_MGR_VM_INACTIVE;
419e8ae9b66SAlan Carew 		return 0;
420e8ae9b66SAlan Carew 	}
421e8ae9b66SAlan Carew 	d = opendir(CHANNEL_MGR_SOCKET_PATH);
422e8ae9b66SAlan Carew 	if (d == NULL) {
423e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error opening directory '%s': %s\n",
424e8ae9b66SAlan Carew 				CHANNEL_MGR_SOCKET_PATH, strerror(errno));
425e8ae9b66SAlan Carew 		return -1;
426e8ae9b66SAlan Carew 	}
427e8ae9b66SAlan Carew 	while ((dir = readdir(d)) != NULL) {
428e8ae9b66SAlan Carew 		if (!strncmp(dir->d_name, ".", 1) ||
429e8ae9b66SAlan Carew 				!strncmp(dir->d_name, "..", 2))
430e8ae9b66SAlan Carew 			continue;
431e8ae9b66SAlan Carew 
4326723c0fcSBruce Richardson 		strlcpy(socket_name, dir->d_name, sizeof(socket_name));
433e8ae9b66SAlan Carew 		remaining = socket_name;
434e8ae9b66SAlan Carew 		/* Extract vm_name from "<vm_name>.<channel_num>" */
435e8ae9b66SAlan Carew 		token = strsep(&remaining, ".");
436e8ae9b66SAlan Carew 		if (remaining == NULL)
437e8ae9b66SAlan Carew 			continue;
438e8ae9b66SAlan Carew 		if (strncmp(vm_name, token, CHANNEL_MGR_MAX_NAME_LEN))
439e8ae9b66SAlan Carew 			continue;
440e8ae9b66SAlan Carew 
441e8ae9b66SAlan Carew 		/* remaining should contain only <channel_num> */
442e8ae9b66SAlan Carew 		errno = 0;
443e8ae9b66SAlan Carew 		channel_num = (unsigned)strtol(remaining, &tail_ptr, 0);
444e8ae9b66SAlan Carew 		if ((errno != 0) || (remaining[0] == '\0') ||
4455b628fe1SBruce Richardson 				tail_ptr == NULL || (*tail_ptr != '\0')) {
446e8ae9b66SAlan Carew 			RTE_LOG(WARNING, CHANNEL_MANAGER, "Malformed channel name"
447e8ae9b66SAlan Carew 					"'%s' found it should be in the form of "
448e8ae9b66SAlan Carew 					"'<guest_name>.<channel_num>(decimal)'\n",
449e8ae9b66SAlan Carew 					dir->d_name);
450e8ae9b66SAlan Carew 			continue;
451e8ae9b66SAlan Carew 		}
452751227a0SDavid Hunt 		if (channel_num >= RTE_MAX_LCORE) {
453e8ae9b66SAlan Carew 			RTE_LOG(WARNING, CHANNEL_MANAGER, "Channel number(%u) is "
454e8ae9b66SAlan Carew 					"greater than max allowable: %d, skipping '%s%s'\n",
455751227a0SDavid Hunt 					channel_num, RTE_MAX_LCORE-1,
456e8ae9b66SAlan Carew 					CHANNEL_MGR_SOCKET_PATH, dir->d_name);
457e8ae9b66SAlan Carew 			continue;
458e8ae9b66SAlan Carew 		}
459e8ae9b66SAlan Carew 		/* if channel has not been added previously */
460e8ae9b66SAlan Carew 		if (channel_exists(vm_info, channel_num))
461e8ae9b66SAlan Carew 			continue;
462e8ae9b66SAlan Carew 
463e8ae9b66SAlan Carew 		chan_info = rte_malloc(NULL, sizeof(*chan_info),
464fdf20fa7SSergio Gonzalez Monroy 				RTE_CACHE_LINE_SIZE);
465e8ae9b66SAlan Carew 		if (chan_info == NULL) {
466e8ae9b66SAlan Carew 			RTE_LOG(ERR, CHANNEL_MANAGER, "Error allocating memory for "
467e8ae9b66SAlan Carew 				"channel '%s%s'\n", CHANNEL_MGR_SOCKET_PATH, dir->d_name);
468e8ae9b66SAlan Carew 			continue;
469e8ae9b66SAlan Carew 		}
470e8ae9b66SAlan Carew 
471e8ae9b66SAlan Carew 		snprintf(chan_info->channel_path,
472e8ae9b66SAlan Carew 				sizeof(chan_info->channel_path), "%s%s",
473e8ae9b66SAlan Carew 				CHANNEL_MGR_SOCKET_PATH, dir->d_name);
474e8ae9b66SAlan Carew 
475e8ae9b66SAlan Carew 		if (setup_channel_info(&vm_info, &chan_info, channel_num) < 0) {
476e8ae9b66SAlan Carew 			rte_free(chan_info);
477e8ae9b66SAlan Carew 			continue;
478e8ae9b66SAlan Carew 		}
479e8ae9b66SAlan Carew 
480e8ae9b66SAlan Carew 		num_channels_enabled++;
481e8ae9b66SAlan Carew 	}
482e8ae9b66SAlan Carew 	closedir(d);
483e8ae9b66SAlan Carew 	return num_channels_enabled;
484e8ae9b66SAlan Carew }
485e8ae9b66SAlan Carew 
486e8ae9b66SAlan Carew int
487e8ae9b66SAlan Carew add_channels(const char *vm_name, unsigned *channel_list,
488e8ae9b66SAlan Carew 		unsigned len_channel_list)
489e8ae9b66SAlan Carew {
490e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info;
491e8ae9b66SAlan Carew 	struct channel_info *chan_info;
492e8ae9b66SAlan Carew 	char socket_path[PATH_MAX];
493e8ae9b66SAlan Carew 	unsigned i;
494e8ae9b66SAlan Carew 	int num_channels_enabled = 0;
495e8ae9b66SAlan Carew 
496e8ae9b66SAlan Carew 	vm_info = find_domain_by_name(vm_name);
497e8ae9b66SAlan Carew 	if (vm_info == NULL) {
498e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to add channels: VM '%s' "
499e8ae9b66SAlan Carew 				"not found\n", vm_name);
500e8ae9b66SAlan Carew 		return 0;
501e8ae9b66SAlan Carew 	}
502e8ae9b66SAlan Carew 
503e8ae9b66SAlan Carew 	if (!virDomainIsActive(vm_info->domainPtr)) {
504e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "VM: '%s' is not active\n", vm_name);
505e8ae9b66SAlan Carew 		vm_info->status = CHANNEL_MGR_VM_INACTIVE;
506e8ae9b66SAlan Carew 		return 0;
507e8ae9b66SAlan Carew 	}
508e8ae9b66SAlan Carew 
509e8ae9b66SAlan Carew 	for (i = 0; i < len_channel_list; i++) {
510e8ae9b66SAlan Carew 
511751227a0SDavid Hunt 		if (channel_list[i] >= RTE_MAX_LCORE) {
512e8ae9b66SAlan Carew 			RTE_LOG(INFO, CHANNEL_MANAGER, "Channel(%u) is out of range "
513e8ae9b66SAlan Carew 							"0...%d\n", channel_list[i],
514751227a0SDavid Hunt 							RTE_MAX_LCORE-1);
515e8ae9b66SAlan Carew 			continue;
516e8ae9b66SAlan Carew 		}
517e8ae9b66SAlan Carew 		if (channel_exists(vm_info, channel_list[i])) {
518e8ae9b66SAlan Carew 			RTE_LOG(INFO, CHANNEL_MANAGER, "Channel already exists, skipping  "
519e8ae9b66SAlan Carew 					"'%s.%u'\n", vm_name, i);
520e8ae9b66SAlan Carew 			continue;
521e8ae9b66SAlan Carew 		}
522e8ae9b66SAlan Carew 
523e8ae9b66SAlan Carew 		snprintf(socket_path, sizeof(socket_path), "%s%s.%u",
524e8ae9b66SAlan Carew 				CHANNEL_MGR_SOCKET_PATH, vm_name, channel_list[i]);
525e8ae9b66SAlan Carew 		errno = 0;
526e8ae9b66SAlan Carew 		if (access(socket_path, F_OK) < 0) {
527e8ae9b66SAlan Carew 			RTE_LOG(ERR, CHANNEL_MANAGER, "Channel path '%s' error: "
528e8ae9b66SAlan Carew 					"%s\n", socket_path, strerror(errno));
529e8ae9b66SAlan Carew 			continue;
530e8ae9b66SAlan Carew 		}
531e8ae9b66SAlan Carew 		chan_info = rte_malloc(NULL, sizeof(*chan_info),
532fdf20fa7SSergio Gonzalez Monroy 				RTE_CACHE_LINE_SIZE);
533e8ae9b66SAlan Carew 		if (chan_info == NULL) {
534e8ae9b66SAlan Carew 			RTE_LOG(ERR, CHANNEL_MANAGER, "Error allocating memory for "
535e8ae9b66SAlan Carew 					"channel '%s'\n", socket_path);
536e8ae9b66SAlan Carew 			continue;
537e8ae9b66SAlan Carew 		}
538e8ae9b66SAlan Carew 		snprintf(chan_info->channel_path,
539e8ae9b66SAlan Carew 				sizeof(chan_info->channel_path), "%s%s.%u",
540e8ae9b66SAlan Carew 				CHANNEL_MGR_SOCKET_PATH, vm_name, channel_list[i]);
541e8ae9b66SAlan Carew 		if (setup_channel_info(&vm_info, &chan_info, channel_list[i]) < 0) {
542e8ae9b66SAlan Carew 			rte_free(chan_info);
543e8ae9b66SAlan Carew 			continue;
544e8ae9b66SAlan Carew 		}
545e8ae9b66SAlan Carew 		num_channels_enabled++;
546e8ae9b66SAlan Carew 
547e8ae9b66SAlan Carew 	}
548e8ae9b66SAlan Carew 	return num_channels_enabled;
549e8ae9b66SAlan Carew }
550e8ae9b66SAlan Carew 
551e8ae9b66SAlan Carew int
552221e7026SMarcin Hajkowski add_host_channels(void)
5533618326fSDavid Hunt {
5543618326fSDavid Hunt 	struct channel_info *chan_info;
5553618326fSDavid Hunt 	char socket_path[PATH_MAX];
5563618326fSDavid Hunt 	int num_channels_enabled = 0;
5573618326fSDavid Hunt 	int ret;
558221e7026SMarcin Hajkowski 	struct core_info *ci;
559221e7026SMarcin Hajkowski 	struct channel_info *chan_infos[RTE_MAX_LCORE];
560221e7026SMarcin Hajkowski 	int i;
5613618326fSDavid Hunt 
562221e7026SMarcin Hajkowski 	for (i = 0; i < RTE_MAX_LCORE; i++)
563221e7026SMarcin Hajkowski 		chan_infos[i] = NULL;
5643618326fSDavid Hunt 
565221e7026SMarcin Hajkowski 	ci = get_core_info();
566221e7026SMarcin Hajkowski 	if (ci == NULL) {
567221e7026SMarcin Hajkowski 		RTE_LOG(ERR, CHANNEL_MANAGER, "Cannot allocate memory for core_info\n");
5683618326fSDavid Hunt 		return 0;
5693618326fSDavid Hunt 	}
5703618326fSDavid Hunt 
571221e7026SMarcin Hajkowski 	for (i = 0; i < ci->core_count; i++) {
572221e7026SMarcin Hajkowski 		if (ci->cd[i].global_enabled_cpus == 0)
573221e7026SMarcin Hajkowski 			continue;
574221e7026SMarcin Hajkowski 
575221e7026SMarcin Hajkowski 		ret = fifo_path(socket_path, sizeof(socket_path), i);
576221e7026SMarcin Hajkowski 		if (ret < 0)
577221e7026SMarcin Hajkowski 			goto error;
578221e7026SMarcin Hajkowski 
579221e7026SMarcin Hajkowski 		ret = mkfifo(socket_path, 0660);
580221e7026SMarcin Hajkowski 		RTE_LOG(DEBUG, CHANNEL_MANAGER, "TRY CREATE fifo '%s'\n",
581221e7026SMarcin Hajkowski 			socket_path);
582221e7026SMarcin Hajkowski 		if ((errno != EEXIST) && (ret < 0)) {
583221e7026SMarcin Hajkowski 			RTE_LOG(ERR, CHANNEL_MANAGER, "Cannot create fifo '%s' error: "
5843618326fSDavid Hunt 					"%s\n", socket_path, strerror(errno));
585221e7026SMarcin Hajkowski 			goto error;
5863618326fSDavid Hunt 		}
5873618326fSDavid Hunt 		chan_info = rte_malloc(NULL, sizeof(*chan_info), 0);
5883618326fSDavid Hunt 		if (chan_info == NULL) {
5893618326fSDavid Hunt 			RTE_LOG(ERR, CHANNEL_MANAGER, "Error allocating memory for "
5903618326fSDavid Hunt 					"channel '%s'\n", socket_path);
591221e7026SMarcin Hajkowski 			goto error;
5923618326fSDavid Hunt 		}
593221e7026SMarcin Hajkowski 		chan_infos[i] = chan_info;
594135393d4SDavid Hunt 		strlcpy(chan_info->channel_path, socket_path,
595221e7026SMarcin Hajkowski 				sizeof(chan_info->channel_path));
59660dea75fSLukasz Krakowiak 
597221e7026SMarcin Hajkowski 		if (setup_host_channel_info(&chan_info, i) < 0) {
5983618326fSDavid Hunt 			rte_free(chan_info);
599221e7026SMarcin Hajkowski 			chan_infos[i] = NULL;
600221e7026SMarcin Hajkowski 			goto error;
6013618326fSDavid Hunt 		}
6023618326fSDavid Hunt 		num_channels_enabled++;
603221e7026SMarcin Hajkowski 	}
6043618326fSDavid Hunt 
6053618326fSDavid Hunt 	return num_channels_enabled;
606221e7026SMarcin Hajkowski error:
607221e7026SMarcin Hajkowski 	/* Clean up the channels opened before we hit an error. */
608221e7026SMarcin Hajkowski 	for (i = 0; i < ci->core_count; i++) {
609221e7026SMarcin Hajkowski 		if (chan_infos[i] != NULL) {
610221e7026SMarcin Hajkowski 			remove_channel_from_monitor(chan_infos[i]);
611221e7026SMarcin Hajkowski 			close(chan_infos[i]->fd);
612221e7026SMarcin Hajkowski 			rte_free(chan_infos[i]);
613221e7026SMarcin Hajkowski 		}
614221e7026SMarcin Hajkowski 	}
615221e7026SMarcin Hajkowski 	return 0;
6163618326fSDavid Hunt }
6173618326fSDavid Hunt 
6183618326fSDavid Hunt int
619e8ae9b66SAlan Carew remove_channel(struct channel_info **chan_info_dptr)
620e8ae9b66SAlan Carew {
621e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info;
622e8ae9b66SAlan Carew 	struct channel_info *chan_info = *chan_info_dptr;
623e8ae9b66SAlan Carew 
624e8ae9b66SAlan Carew 	close(chan_info->fd);
625e8ae9b66SAlan Carew 
626e8ae9b66SAlan Carew 	vm_info = (struct virtual_machine_info *)chan_info->priv_info;
627e8ae9b66SAlan Carew 
628e8ae9b66SAlan Carew 	rte_spinlock_lock(&(vm_info->config_spinlock));
629fd73630eSDavid Hunt 	vm_info->channel_mask[chan_info->channel_num] = 0;
630e8ae9b66SAlan Carew 	vm_info->num_channels--;
631e8ae9b66SAlan Carew 	rte_spinlock_unlock(&(vm_info->config_spinlock));
632e8ae9b66SAlan Carew 
633e8ae9b66SAlan Carew 	rte_free(chan_info);
634e8ae9b66SAlan Carew 	return 0;
635e8ae9b66SAlan Carew }
636e8ae9b66SAlan Carew 
637e8ae9b66SAlan Carew int
638e8ae9b66SAlan Carew set_channel_status_all(const char *vm_name, enum channel_status status)
639e8ae9b66SAlan Carew {
640e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info;
641e8ae9b66SAlan Carew 	unsigned i;
642751227a0SDavid Hunt 	char mask[RTE_MAX_LCORE];
643e8ae9b66SAlan Carew 	int num_channels_changed = 0;
644e8ae9b66SAlan Carew 
645e8ae9b66SAlan Carew 	if (!(status == CHANNEL_MGR_CHANNEL_CONNECTED ||
646e8ae9b66SAlan Carew 			status == CHANNEL_MGR_CHANNEL_DISABLED)) {
647e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Channels can only be enabled or "
648e8ae9b66SAlan Carew 				"disabled: Unable to change status for VM '%s'\n", vm_name);
649e8ae9b66SAlan Carew 	}
650e8ae9b66SAlan Carew 	vm_info = find_domain_by_name(vm_name);
651e8ae9b66SAlan Carew 	if (vm_info == NULL) {
652e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to disable channels: VM '%s' "
653e8ae9b66SAlan Carew 				"not found\n", vm_name);
654e8ae9b66SAlan Carew 		return 0;
655e8ae9b66SAlan Carew 	}
656e8ae9b66SAlan Carew 
657e8ae9b66SAlan Carew 	rte_spinlock_lock(&(vm_info->config_spinlock));
658751227a0SDavid Hunt 	memcpy(mask, (char *)vm_info->channel_mask, RTE_MAX_LCORE);
659751227a0SDavid Hunt 	for (i = 0; i < RTE_MAX_LCORE; i++) {
660fd73630eSDavid Hunt 		if (mask[i] != 1)
661fd73630eSDavid Hunt 			continue;
662e8ae9b66SAlan Carew 		vm_info->channels[i]->status = status;
663e8ae9b66SAlan Carew 		num_channels_changed++;
664e8ae9b66SAlan Carew 	}
665e8ae9b66SAlan Carew 	rte_spinlock_unlock(&(vm_info->config_spinlock));
666e8ae9b66SAlan Carew 	return num_channels_changed;
667e8ae9b66SAlan Carew 
668e8ae9b66SAlan Carew }
669e8ae9b66SAlan Carew 
670e8ae9b66SAlan Carew int
671e8ae9b66SAlan Carew set_channel_status(const char *vm_name, unsigned *channel_list,
672e8ae9b66SAlan Carew 		unsigned len_channel_list, enum channel_status status)
673e8ae9b66SAlan Carew {
674e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info;
675e8ae9b66SAlan Carew 	unsigned i;
676e8ae9b66SAlan Carew 	int num_channels_changed = 0;
677e8ae9b66SAlan Carew 
678e8ae9b66SAlan Carew 	if (!(status == CHANNEL_MGR_CHANNEL_CONNECTED ||
679e8ae9b66SAlan Carew 			status == CHANNEL_MGR_CHANNEL_DISABLED)) {
680e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Channels can only be enabled or "
681e8ae9b66SAlan Carew 				"disabled: Unable to change status for VM '%s'\n", vm_name);
682e8ae9b66SAlan Carew 	}
683e8ae9b66SAlan Carew 	vm_info = find_domain_by_name(vm_name);
684e8ae9b66SAlan Carew 	if (vm_info == NULL) {
685e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to add channels: VM '%s' "
686e8ae9b66SAlan Carew 				"not found\n", vm_name);
687e8ae9b66SAlan Carew 		return 0;
688e8ae9b66SAlan Carew 	}
689e8ae9b66SAlan Carew 	for (i = 0; i < len_channel_list; i++) {
690e8ae9b66SAlan Carew 		if (channel_exists(vm_info, channel_list[i])) {
691e8ae9b66SAlan Carew 			rte_spinlock_lock(&(vm_info->config_spinlock));
692e8ae9b66SAlan Carew 			vm_info->channels[channel_list[i]]->status = status;
693e8ae9b66SAlan Carew 			rte_spinlock_unlock(&(vm_info->config_spinlock));
694e8ae9b66SAlan Carew 			num_channels_changed++;
695e8ae9b66SAlan Carew 		}
696e8ae9b66SAlan Carew 	}
697e8ae9b66SAlan Carew 	return num_channels_changed;
698e8ae9b66SAlan Carew }
699e8ae9b66SAlan Carew 
700dff22404SDavid Hunt void
701dff22404SDavid Hunt get_all_vm(int *num_vm, int *num_vcpu)
702dff22404SDavid Hunt {
703dff22404SDavid Hunt 
704dff22404SDavid Hunt 	virNodeInfo node_info;
705dff22404SDavid Hunt 	virDomainPtr *domptr;
706fd73630eSDavid Hunt 	int i, ii, numVcpus[MAX_VCPUS], n_vcpus;
707dff22404SDavid Hunt 	unsigned int jj;
708dff22404SDavid Hunt 	const char *vm_name;
709dff22404SDavid Hunt 	unsigned int domain_flags = VIR_CONNECT_LIST_DOMAINS_RUNNING |
710dff22404SDavid Hunt 				VIR_CONNECT_LIST_DOMAINS_PERSISTENT;
711dff22404SDavid Hunt 	unsigned int domain_flag = VIR_DOMAIN_VCPU_CONFIG;
712dff22404SDavid Hunt 
713e0207366SDavid Hunt 	if (!global_hypervisor_available)
714e0207366SDavid Hunt 		return;
715dff22404SDavid Hunt 
716751227a0SDavid Hunt 	memset(global_cpumaps, 0, RTE_MAX_LCORE*global_maplen);
717dff22404SDavid Hunt 	if (virNodeGetInfo(global_vir_conn_ptr, &node_info)) {
718dff22404SDavid Hunt 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to retrieve node Info\n");
719dff22404SDavid Hunt 		return;
720dff22404SDavid Hunt 	}
721dff22404SDavid Hunt 
722dff22404SDavid Hunt 	/* Returns number of pcpus */
723dff22404SDavid Hunt 	global_n_host_cpus = (unsigned int)node_info.cpus;
724dff22404SDavid Hunt 
725dff22404SDavid Hunt 	/* Returns number of active domains */
726dff22404SDavid Hunt 	*num_vm = virConnectListAllDomains(global_vir_conn_ptr, &domptr,
727dff22404SDavid Hunt 					domain_flags);
728dff22404SDavid Hunt 	if (*num_vm <= 0) {
729dff22404SDavid Hunt 		RTE_LOG(ERR, CHANNEL_MANAGER, "No Active Domains Running\n");
730dff22404SDavid Hunt 		return;
731dff22404SDavid Hunt 	}
732dff22404SDavid Hunt 
733dff22404SDavid Hunt 	for (i = 0; i < *num_vm; i++) {
734dff22404SDavid Hunt 
735dff22404SDavid Hunt 		/* Get Domain Names */
736dff22404SDavid Hunt 		vm_name = virDomainGetName(domptr[i]);
737dff22404SDavid Hunt 		lvm_info[i].vm_name = vm_name;
738dff22404SDavid Hunt 
739dff22404SDavid Hunt 		/* Get Number of Vcpus */
740dff22404SDavid Hunt 		numVcpus[i] = virDomainGetVcpusFlags(domptr[i], domain_flag);
741dff22404SDavid Hunt 
742dff22404SDavid Hunt 		/* Get Number of VCpus & VcpuPinInfo */
743dff22404SDavid Hunt 		n_vcpus = virDomainGetVcpuPinInfo(domptr[i],
744dff22404SDavid Hunt 				numVcpus[i], global_cpumaps,
745dff22404SDavid Hunt 				global_maplen, domain_flag);
746dff22404SDavid Hunt 
747dff22404SDavid Hunt 		if ((int)n_vcpus > 0) {
748dff22404SDavid Hunt 			*num_vcpu = n_vcpus;
749dff22404SDavid Hunt 			lvm_info[i].num_cpus = n_vcpus;
750dff22404SDavid Hunt 		}
751dff22404SDavid Hunt 
752dff22404SDavid Hunt 		/* Save pcpu in use by libvirt VMs */
753dff22404SDavid Hunt 		for (ii = 0; ii < n_vcpus; ii++) {
754dff22404SDavid Hunt 			for (jj = 0; jj < global_n_host_cpus; jj++) {
755dff22404SDavid Hunt 				if (VIR_CPU_USABLE(global_cpumaps,
756dff22404SDavid Hunt 						global_maplen, ii, jj) > 0) {
757fd73630eSDavid Hunt 					lvm_info[i].pcpus[ii] = jj;
758dff22404SDavid Hunt 				}
759dff22404SDavid Hunt 			}
760dff22404SDavid Hunt 		}
761dff22404SDavid Hunt 	}
762dff22404SDavid Hunt }
763dff22404SDavid Hunt 
764e8ae9b66SAlan Carew int
765e8ae9b66SAlan Carew get_info_vm(const char *vm_name, struct vm_info *info)
766e8ae9b66SAlan Carew {
767e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info;
768e8ae9b66SAlan Carew 	unsigned i, channel_num = 0;
769751227a0SDavid Hunt 	char mask[RTE_MAX_LCORE];
770e8ae9b66SAlan Carew 
771e8ae9b66SAlan Carew 	vm_info = find_domain_by_name(vm_name);
772e8ae9b66SAlan Carew 	if (vm_info == NULL) {
773e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "VM '%s' not found\n", vm_name);
774e8ae9b66SAlan Carew 		return -1;
775e8ae9b66SAlan Carew 	}
776e8ae9b66SAlan Carew 	info->status = CHANNEL_MGR_VM_ACTIVE;
777e8ae9b66SAlan Carew 	if (!virDomainIsActive(vm_info->domainPtr))
778e8ae9b66SAlan Carew 		info->status = CHANNEL_MGR_VM_INACTIVE;
779e8ae9b66SAlan Carew 
780e8ae9b66SAlan Carew 	rte_spinlock_lock(&(vm_info->config_spinlock));
781e8ae9b66SAlan Carew 
782751227a0SDavid Hunt 	memcpy(mask, (char *)vm_info->channel_mask, RTE_MAX_LCORE);
783751227a0SDavid Hunt 	for (i = 0; i < RTE_MAX_LCORE; i++) {
784fd73630eSDavid Hunt 		if (mask[i] != 1)
785fd73630eSDavid Hunt 			continue;
786e8ae9b66SAlan Carew 		info->channels[channel_num].channel_num = i;
787e8ae9b66SAlan Carew 		memcpy(info->channels[channel_num].channel_path,
788fd73630eSDavid Hunt 				vm_info->channels[i]->channel_path,
789fd73630eSDavid Hunt 				UNIX_PATH_MAX);
790fd73630eSDavid Hunt 		info->channels[channel_num].status =
791fd73630eSDavid Hunt 				vm_info->channels[i]->status;
792fd73630eSDavid Hunt 		info->channels[channel_num].fd =
793fd73630eSDavid Hunt 				vm_info->channels[i]->fd;
794e8ae9b66SAlan Carew 		channel_num++;
795e8ae9b66SAlan Carew 	}
796e8ae9b66SAlan Carew 
7971deb502eSMarcin Hajkowski 	info->allow_query = vm_info->allow_query;
798e8ae9b66SAlan Carew 	info->num_channels = channel_num;
799e8ae9b66SAlan Carew 	info->num_vcpus = vm_info->info.nrVirtCpu;
800e8ae9b66SAlan Carew 	rte_spinlock_unlock(&(vm_info->config_spinlock));
801e8ae9b66SAlan Carew 
802e8ae9b66SAlan Carew 	memcpy(info->name, vm_info->name, sizeof(vm_info->name));
8035776b7a3SDavid Hunt 	rte_spinlock_lock(&(vm_info->config_spinlock));
804e8ae9b66SAlan Carew 	for (i = 0; i < info->num_vcpus; i++) {
8055776b7a3SDavid Hunt 		info->pcpu_map[i] = vm_info->pcpu_map[i];
806e8ae9b66SAlan Carew 	}
8075776b7a3SDavid Hunt 	rte_spinlock_unlock(&(vm_info->config_spinlock));
808e8ae9b66SAlan Carew 	return 0;
809e8ae9b66SAlan Carew }
810e8ae9b66SAlan Carew 
811e8ae9b66SAlan Carew int
812e8ae9b66SAlan Carew add_vm(const char *vm_name)
813e8ae9b66SAlan Carew {
814e8ae9b66SAlan Carew 	struct virtual_machine_info *new_domain;
815e8ae9b66SAlan Carew 	virDomainPtr dom_ptr;
816e8ae9b66SAlan Carew 	int i;
817e8ae9b66SAlan Carew 
818e8ae9b66SAlan Carew 	if (find_domain_by_name(vm_name) != NULL) {
819e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to add VM: VM '%s' "
820e8ae9b66SAlan Carew 				"already exists\n", vm_name);
821e8ae9b66SAlan Carew 		return -1;
822e8ae9b66SAlan Carew 	}
823e8ae9b66SAlan Carew 
824e8ae9b66SAlan Carew 	if (global_vir_conn_ptr == NULL) {
825e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "No connection to hypervisor exists\n");
826e8ae9b66SAlan Carew 		return -1;
827e8ae9b66SAlan Carew 	}
828e8ae9b66SAlan Carew 	dom_ptr = virDomainLookupByName(global_vir_conn_ptr, vm_name);
829e8ae9b66SAlan Carew 	if (dom_ptr == NULL) {
830e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error on VM lookup with libvirt: "
831e8ae9b66SAlan Carew 				"VM '%s' not found\n", vm_name);
832e8ae9b66SAlan Carew 		return -1;
833e8ae9b66SAlan Carew 	}
834e8ae9b66SAlan Carew 
835e8ae9b66SAlan Carew 	new_domain = rte_malloc("virtual_machine_info", sizeof(*new_domain),
836fdf20fa7SSergio Gonzalez Monroy 			RTE_CACHE_LINE_SIZE);
837e8ae9b66SAlan Carew 	if (new_domain == NULL) {
838e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to allocate memory for VM "
839e8ae9b66SAlan Carew 				"info\n");
840e8ae9b66SAlan Carew 		return -1;
841e8ae9b66SAlan Carew 	}
842e8ae9b66SAlan Carew 	new_domain->domainPtr = dom_ptr;
843e8ae9b66SAlan Carew 	if (virDomainGetInfo(new_domain->domainPtr, &new_domain->info) != 0) {
844e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to get libvirt VM info\n");
845e8ae9b66SAlan Carew 		rte_free(new_domain);
846e8ae9b66SAlan Carew 		return -1;
847e8ae9b66SAlan Carew 	}
848751227a0SDavid Hunt 	if (new_domain->info.nrVirtCpu > RTE_MAX_LCORE) {
849e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error the number of virtual CPUs(%u) is "
850e8ae9b66SAlan Carew 				"greater than allowable(%d)\n", new_domain->info.nrVirtCpu,
851751227a0SDavid Hunt 				RTE_MAX_LCORE);
852e8ae9b66SAlan Carew 		rte_free(new_domain);
853e8ae9b66SAlan Carew 		return -1;
854e8ae9b66SAlan Carew 	}
855e8ae9b66SAlan Carew 
856751227a0SDavid Hunt 	for (i = 0; i < RTE_MAX_LCORE; i++)
8575776b7a3SDavid Hunt 		new_domain->pcpu_map[i] = 0;
858751227a0SDavid Hunt 
859e8ae9b66SAlan Carew 	if (update_pcpus_mask(new_domain) < 0) {
860e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error getting physical CPU pinning\n");
861e8ae9b66SAlan Carew 		rte_free(new_domain);
862e8ae9b66SAlan Carew 		return -1;
863e8ae9b66SAlan Carew 	}
864e8ae9b66SAlan Carew 	strncpy(new_domain->name, vm_name, sizeof(new_domain->name));
86542b3f505SDaniel Mrzyglod 	new_domain->name[sizeof(new_domain->name) - 1] = '\0';
866751227a0SDavid Hunt 	memset(new_domain->channel_mask, 0, RTE_MAX_LCORE);
867e8ae9b66SAlan Carew 	new_domain->num_channels = 0;
868e8ae9b66SAlan Carew 
869e8ae9b66SAlan Carew 	if (!virDomainIsActive(dom_ptr))
870e8ae9b66SAlan Carew 		new_domain->status = CHANNEL_MGR_VM_INACTIVE;
871e8ae9b66SAlan Carew 	else
872e8ae9b66SAlan Carew 		new_domain->status = CHANNEL_MGR_VM_ACTIVE;
873e8ae9b66SAlan Carew 
8741deb502eSMarcin Hajkowski 	new_domain->allow_query = 0;
875e8ae9b66SAlan Carew 	rte_spinlock_init(&(new_domain->config_spinlock));
876e8ae9b66SAlan Carew 	LIST_INSERT_HEAD(&vm_list_head, new_domain, vms_info);
877e8ae9b66SAlan Carew 	return 0;
878e8ae9b66SAlan Carew }
879e8ae9b66SAlan Carew 
880e8ae9b66SAlan Carew int
881e8ae9b66SAlan Carew remove_vm(const char *vm_name)
882e8ae9b66SAlan Carew {
883e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info = find_domain_by_name(vm_name);
884e8ae9b66SAlan Carew 
885e8ae9b66SAlan Carew 	if (vm_info == NULL) {
886e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to remove VM: VM '%s' "
887e8ae9b66SAlan Carew 				"not found\n", vm_name);
888e8ae9b66SAlan Carew 		return -1;
889e8ae9b66SAlan Carew 	}
890e8ae9b66SAlan Carew 	rte_spinlock_lock(&vm_info->config_spinlock);
891e8ae9b66SAlan Carew 	if (vm_info->num_channels != 0) {
892e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to remove VM '%s', there are "
893e8ae9b66SAlan Carew 				"%"PRId8" channels still active\n",
894e8ae9b66SAlan Carew 				vm_name, vm_info->num_channels);
895e8ae9b66SAlan Carew 		rte_spinlock_unlock(&vm_info->config_spinlock);
896e8ae9b66SAlan Carew 		return -1;
897e8ae9b66SAlan Carew 	}
898e8ae9b66SAlan Carew 	LIST_REMOVE(vm_info, vms_info);
899e8ae9b66SAlan Carew 	rte_spinlock_unlock(&vm_info->config_spinlock);
900e8ae9b66SAlan Carew 	rte_free(vm_info);
901e8ae9b66SAlan Carew 	return 0;
902e8ae9b66SAlan Carew }
903e8ae9b66SAlan Carew 
9041deb502eSMarcin Hajkowski int
9051deb502eSMarcin Hajkowski set_query_status(char *vm_name,
9061deb502eSMarcin Hajkowski 		bool allow_query)
9071deb502eSMarcin Hajkowski {
9081deb502eSMarcin Hajkowski 	struct virtual_machine_info *vm_info;
9091deb502eSMarcin Hajkowski 
9101deb502eSMarcin Hajkowski 	vm_info = find_domain_by_name(vm_name);
9111deb502eSMarcin Hajkowski 	if (vm_info == NULL) {
9121deb502eSMarcin Hajkowski 		RTE_LOG(ERR, CHANNEL_MANAGER, "VM '%s' not found\n", vm_name);
9131deb502eSMarcin Hajkowski 		return -1;
9141deb502eSMarcin Hajkowski 	}
9151deb502eSMarcin Hajkowski 	rte_spinlock_lock(&(vm_info->config_spinlock));
9161deb502eSMarcin Hajkowski 	vm_info->allow_query = allow_query ? 1 : 0;
9171deb502eSMarcin Hajkowski 	rte_spinlock_unlock(&(vm_info->config_spinlock));
9181deb502eSMarcin Hajkowski 	return 0;
9191deb502eSMarcin Hajkowski }
9201deb502eSMarcin Hajkowski 
921e8ae9b66SAlan Carew static void
922e8ae9b66SAlan Carew disconnect_hypervisor(void)
923e8ae9b66SAlan Carew {
924e8ae9b66SAlan Carew 	if (global_vir_conn_ptr != NULL) {
925e8ae9b66SAlan Carew 		virConnectClose(global_vir_conn_ptr);
926e8ae9b66SAlan Carew 		global_vir_conn_ptr = NULL;
927e8ae9b66SAlan Carew 	}
928e8ae9b66SAlan Carew }
929e8ae9b66SAlan Carew 
930e8ae9b66SAlan Carew static int
931e8ae9b66SAlan Carew connect_hypervisor(const char *path)
932e8ae9b66SAlan Carew {
933e8ae9b66SAlan Carew 	if (global_vir_conn_ptr != NULL) {
934e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error connecting to %s, connection "
935e8ae9b66SAlan Carew 				"already established\n", path);
936e8ae9b66SAlan Carew 		return -1;
937e8ae9b66SAlan Carew 	}
938e8ae9b66SAlan Carew 	global_vir_conn_ptr = virConnectOpen(path);
939e8ae9b66SAlan Carew 	if (global_vir_conn_ptr == NULL) {
940e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error failed to open connection to "
941e8ae9b66SAlan Carew 				"Hypervisor '%s'\n", path);
942e8ae9b66SAlan Carew 		return -1;
943e8ae9b66SAlan Carew 	}
944e8ae9b66SAlan Carew 	return 0;
945e8ae9b66SAlan Carew }
946e8ae9b66SAlan Carew int
947e0207366SDavid Hunt channel_manager_init(const char *path __rte_unused)
948e8ae9b66SAlan Carew {
949f7f14fe3SYong Liu 	virNodeInfo info;
950e8ae9b66SAlan Carew 
951e8ae9b66SAlan Carew 	LIST_INIT(&vm_list_head);
952e8ae9b66SAlan Carew 	if (connect_hypervisor(path) < 0) {
953e0207366SDavid Hunt 		global_n_host_cpus = 64;
954e0207366SDavid Hunt 		global_hypervisor_available = 0;
955e0207366SDavid Hunt 		RTE_LOG(INFO, CHANNEL_MANAGER, "Unable to initialize channel manager\n");
956e0207366SDavid Hunt 	} else {
957e0207366SDavid Hunt 		global_hypervisor_available = 1;
958e8ae9b66SAlan Carew 
959751227a0SDavid Hunt 		global_maplen = VIR_CPU_MAPLEN(RTE_MAX_LCORE);
960e8ae9b66SAlan Carew 
961e0207366SDavid Hunt 		global_vircpuinfo = rte_zmalloc(NULL,
962e0207366SDavid Hunt 				sizeof(*global_vircpuinfo) *
963751227a0SDavid Hunt 				RTE_MAX_LCORE, RTE_CACHE_LINE_SIZE);
964e8ae9b66SAlan Carew 		if (global_vircpuinfo == NULL) {
965e8ae9b66SAlan Carew 			RTE_LOG(ERR, CHANNEL_MANAGER, "Error allocating memory for CPU Info\n");
966e8ae9b66SAlan Carew 			goto error;
967e8ae9b66SAlan Carew 		}
968e0207366SDavid Hunt 		global_cpumaps = rte_zmalloc(NULL,
969751227a0SDavid Hunt 				RTE_MAX_LCORE * global_maplen,
970fdf20fa7SSergio Gonzalez Monroy 				RTE_CACHE_LINE_SIZE);
971e0207366SDavid Hunt 		if (global_cpumaps == NULL)
972e8ae9b66SAlan Carew 			goto error;
973e8ae9b66SAlan Carew 
974f7f14fe3SYong Liu 		if (virNodeGetInfo(global_vir_conn_ptr, &info)) {
975f7f14fe3SYong Liu 			RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to retrieve node Info\n");
976e8ae9b66SAlan Carew 			goto error;
977e8ae9b66SAlan Carew 		}
978e0207366SDavid Hunt 		global_n_host_cpus = (unsigned int)info.cpus;
979e0207366SDavid Hunt 	}
980f7f14fe3SYong Liu 
981e0207366SDavid Hunt 
982e8ae9b66SAlan Carew 
983751227a0SDavid Hunt 	if (global_n_host_cpus > RTE_MAX_LCORE) {
984e9f64db9SPablo de Lara 		RTE_LOG(WARNING, CHANNEL_MANAGER, "The number of host CPUs(%u) exceeds the "
985e9f64db9SPablo de Lara 				"maximum of %u. No cores over %u should be used.\n",
986751227a0SDavid Hunt 				global_n_host_cpus, RTE_MAX_LCORE,
987751227a0SDavid Hunt 				RTE_MAX_LCORE - 1);
988751227a0SDavid Hunt 		global_n_host_cpus = RTE_MAX_LCORE;
98967ff575eSMarvin Liu 	}
990e8ae9b66SAlan Carew 
991e8ae9b66SAlan Carew 	return 0;
992e8ae9b66SAlan Carew error:
993e0207366SDavid Hunt 	if (global_hypervisor_available)
994e8ae9b66SAlan Carew 		disconnect_hypervisor();
995e8ae9b66SAlan Carew 	return -1;
996e8ae9b66SAlan Carew }
997e8ae9b66SAlan Carew 
998e8ae9b66SAlan Carew void
999e8ae9b66SAlan Carew channel_manager_exit(void)
1000e8ae9b66SAlan Carew {
1001e8ae9b66SAlan Carew 	unsigned i;
1002751227a0SDavid Hunt 	char mask[RTE_MAX_LCORE];
1003e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info;
1004e8ae9b66SAlan Carew 
1005e8ae9b66SAlan Carew 	LIST_FOREACH(vm_info, &vm_list_head, vms_info) {
1006e8ae9b66SAlan Carew 
1007e8ae9b66SAlan Carew 		rte_spinlock_lock(&(vm_info->config_spinlock));
1008e8ae9b66SAlan Carew 
1009751227a0SDavid Hunt 		memcpy(mask, (char *)vm_info->channel_mask, RTE_MAX_LCORE);
1010751227a0SDavid Hunt 		for (i = 0; i < RTE_MAX_LCORE; i++) {
1011fd73630eSDavid Hunt 			if (mask[i] != 1)
1012fd73630eSDavid Hunt 				continue;
1013fd73630eSDavid Hunt 			remove_channel_from_monitor(
1014fd73630eSDavid Hunt 					vm_info->channels[i]);
1015e8ae9b66SAlan Carew 			close(vm_info->channels[i]->fd);
1016e8ae9b66SAlan Carew 			rte_free(vm_info->channels[i]);
1017e8ae9b66SAlan Carew 		}
1018e8ae9b66SAlan Carew 		rte_spinlock_unlock(&(vm_info->config_spinlock));
1019e8ae9b66SAlan Carew 
1020e8ae9b66SAlan Carew 		LIST_REMOVE(vm_info, vms_info);
1021e8ae9b66SAlan Carew 		rte_free(vm_info);
1022e8ae9b66SAlan Carew 	}
1023e8ae9b66SAlan Carew 
1024e0207366SDavid Hunt 	if (global_hypervisor_available) {
1025e0207366SDavid Hunt 		/* Only needed if hypervisor available */
1026e8ae9b66SAlan Carew 		rte_free(global_cpumaps);
1027e8ae9b66SAlan Carew 		rte_free(global_vircpuinfo);
1028e8ae9b66SAlan Carew 		disconnect_hypervisor();
1029e8ae9b66SAlan Carew 	}
1030e0207366SDavid Hunt }
1031