xref: /dpdk/examples/vm_power_manager/channel_manager.c (revision 9c20d0fdc536df2a320cb1ae6cce49c2c7a02ebb)
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 <fcntl.h>
8e8ae9b66SAlan Carew #include <unistd.h>
9e8ae9b66SAlan Carew #include <inttypes.h>
10e8ae9b66SAlan Carew #include <dirent.h>
11e8ae9b66SAlan Carew #include <errno.h>
12e8ae9b66SAlan Carew 
13e8ae9b66SAlan Carew #include <sys/queue.h>
14e8ae9b66SAlan Carew #include <sys/types.h>
153618326fSDavid Hunt #include <sys/stat.h>
16e8ae9b66SAlan Carew #include <sys/socket.h>
17e8ae9b66SAlan Carew #include <sys/select.h>
18e8ae9b66SAlan Carew 
196723c0fcSBruce Richardson #include <rte_string_fns.h>
20e8ae9b66SAlan Carew #include <rte_malloc.h>
21e8ae9b66SAlan Carew #include <rte_memory.h>
22e8ae9b66SAlan Carew #include <rte_mempool.h>
23e8ae9b66SAlan Carew #include <rte_log.h>
24e8ae9b66SAlan Carew #include <rte_spinlock.h>
25*9c20d0fdSHamza Khan #include <rte_tailq.h>
26e8ae9b66SAlan Carew 
27e8ae9b66SAlan Carew #include <libvirt/libvirt.h>
28e8ae9b66SAlan Carew 
29e8ae9b66SAlan Carew #include "channel_manager.h"
30e8ae9b66SAlan Carew #include "channel_monitor.h"
31fd73630eSDavid Hunt #include "power_manager.h"
32e8ae9b66SAlan Carew 
33e8ae9b66SAlan Carew 
34e8ae9b66SAlan Carew #define RTE_LOGTYPE_CHANNEL_MANAGER RTE_LOGTYPE_USER1
35e8ae9b66SAlan Carew 
3696d3d532SThomas Monjalon struct libvirt_vm_info lvm_info[MAX_CLIENTS];
3796d3d532SThomas Monjalon 
38e8ae9b66SAlan Carew /* Global pointer to libvirt connection */
39e8ae9b66SAlan Carew static virConnectPtr global_vir_conn_ptr;
40e8ae9b66SAlan Carew 
41e8ae9b66SAlan Carew static unsigned char *global_cpumaps;
42e8ae9b66SAlan Carew static virVcpuInfo *global_vircpuinfo;
43e8ae9b66SAlan Carew static size_t global_maplen;
44e8ae9b66SAlan Carew 
45e0207366SDavid Hunt static unsigned int global_n_host_cpus;
46e0207366SDavid Hunt static bool global_hypervisor_available;
47e8ae9b66SAlan Carew 
48e8ae9b66SAlan Carew /*
49e8ae9b66SAlan Carew  * Represents a single Virtual Machine
50e8ae9b66SAlan Carew  */
51e8ae9b66SAlan Carew struct virtual_machine_info {
52e8ae9b66SAlan Carew 	char name[CHANNEL_MGR_MAX_NAME_LEN];
53751227a0SDavid Hunt 	uint16_t pcpu_map[RTE_MAX_LCORE];
54751227a0SDavid Hunt 	struct channel_info *channels[RTE_MAX_LCORE];
55751227a0SDavid Hunt 	char channel_mask[RTE_MAX_LCORE];
56e8ae9b66SAlan Carew 	uint8_t num_channels;
57e8ae9b66SAlan Carew 	enum vm_status status;
58e8ae9b66SAlan Carew 	virDomainPtr domainPtr;
59e8ae9b66SAlan Carew 	virDomainInfo info;
60e8ae9b66SAlan Carew 	rte_spinlock_t config_spinlock;
611deb502eSMarcin Hajkowski 	int allow_query;
62*9c20d0fdSHamza Khan 	RTE_TAILQ_ENTRY(virtual_machine_info) vms_info;
63e8ae9b66SAlan Carew };
64e8ae9b66SAlan Carew 
65*9c20d0fdSHamza Khan RTE_TAILQ_HEAD(, virtual_machine_info) vm_list_head;
66e8ae9b66SAlan Carew 
67e8ae9b66SAlan Carew static struct virtual_machine_info *
find_domain_by_name(const char * name)68e8ae9b66SAlan Carew find_domain_by_name(const char *name)
69e8ae9b66SAlan Carew {
70e8ae9b66SAlan Carew 	struct virtual_machine_info *info;
71*9c20d0fdSHamza Khan 	RTE_TAILQ_FOREACH(info, &vm_list_head, vms_info) {
72e8ae9b66SAlan Carew 		if (!strncmp(info->name, name, CHANNEL_MGR_MAX_NAME_LEN-1))
73e8ae9b66SAlan Carew 			return info;
74e8ae9b66SAlan Carew 	}
75e8ae9b66SAlan Carew 	return NULL;
76e8ae9b66SAlan Carew }
77e8ae9b66SAlan Carew 
78e8ae9b66SAlan Carew static int
update_pcpus_mask(struct virtual_machine_info * vm_info)79e8ae9b66SAlan Carew update_pcpus_mask(struct virtual_machine_info *vm_info)
80e8ae9b66SAlan Carew {
81e8ae9b66SAlan Carew 	virVcpuInfoPtr cpuinfo;
82e8ae9b66SAlan Carew 	unsigned i, j;
83e8ae9b66SAlan Carew 	int n_vcpus;
84e8ae9b66SAlan Carew 
85751227a0SDavid Hunt 	memset(global_cpumaps, 0, RTE_MAX_LCORE*global_maplen);
86e8ae9b66SAlan Carew 
87e8ae9b66SAlan Carew 	if (!virDomainIsActive(vm_info->domainPtr)) {
88e8ae9b66SAlan Carew 		n_vcpus = virDomainGetVcpuPinInfo(vm_info->domainPtr,
89e8ae9b66SAlan Carew 				vm_info->info.nrVirtCpu, global_cpumaps, global_maplen,
90e8ae9b66SAlan Carew 				VIR_DOMAIN_AFFECT_CONFIG);
91e8ae9b66SAlan Carew 		if (n_vcpus < 0) {
92e8ae9b66SAlan Carew 			RTE_LOG(ERR, CHANNEL_MANAGER, "Error getting vCPU info for "
93e8ae9b66SAlan Carew 					"in-active VM '%s'\n", vm_info->name);
94e8ae9b66SAlan Carew 			return -1;
95e8ae9b66SAlan Carew 		}
96e8ae9b66SAlan Carew 		goto update_pcpus;
97e8ae9b66SAlan Carew 	}
98e8ae9b66SAlan Carew 
99e8ae9b66SAlan Carew 	memset(global_vircpuinfo, 0, sizeof(*global_vircpuinfo)*
100751227a0SDavid Hunt 			RTE_MAX_LCORE);
101e8ae9b66SAlan Carew 
102e8ae9b66SAlan Carew 	cpuinfo = global_vircpuinfo;
103e8ae9b66SAlan Carew 
104e8ae9b66SAlan Carew 	n_vcpus = virDomainGetVcpus(vm_info->domainPtr, cpuinfo,
105751227a0SDavid Hunt 			RTE_MAX_LCORE, global_cpumaps, global_maplen);
106e8ae9b66SAlan Carew 	if (n_vcpus < 0) {
107e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error getting vCPU info for "
108e8ae9b66SAlan Carew 				"active VM '%s'\n", vm_info->name);
109e8ae9b66SAlan Carew 		return -1;
110e8ae9b66SAlan Carew 	}
111e8ae9b66SAlan Carew update_pcpus:
112751227a0SDavid Hunt 	if (n_vcpus >= RTE_MAX_LCORE) {
113e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Number of vCPUS(%u) is out of range "
114751227a0SDavid Hunt 				"0...%d\n", n_vcpus, RTE_MAX_LCORE-1);
115e8ae9b66SAlan Carew 		return -1;
116e8ae9b66SAlan Carew 	}
117e8ae9b66SAlan Carew 	if (n_vcpus != vm_info->info.nrVirtCpu) {
118e8ae9b66SAlan Carew 		RTE_LOG(INFO, CHANNEL_MANAGER, "Updating the number of vCPUs for VM '%s"
119e8ae9b66SAlan Carew 				" from %d -> %d\n", vm_info->name, vm_info->info.nrVirtCpu,
120e8ae9b66SAlan Carew 				n_vcpus);
121e8ae9b66SAlan Carew 		vm_info->info.nrVirtCpu = n_vcpus;
122e8ae9b66SAlan Carew 	}
1235776b7a3SDavid Hunt 	rte_spinlock_lock(&(vm_info->config_spinlock));
124e8ae9b66SAlan Carew 	for (i = 0; i < vm_info->info.nrVirtCpu; i++) {
125e8ae9b66SAlan Carew 		for (j = 0; j < global_n_host_cpus; j++) {
1265776b7a3SDavid Hunt 			if (VIR_CPU_USABLE(global_cpumaps,
1275776b7a3SDavid Hunt 					global_maplen, i, j) <= 0)
1285776b7a3SDavid Hunt 				continue;
1295776b7a3SDavid Hunt 			vm_info->pcpu_map[i] = j;
130e8ae9b66SAlan Carew 		}
131e8ae9b66SAlan Carew 	}
1325776b7a3SDavid Hunt 	rte_spinlock_unlock(&(vm_info->config_spinlock));
133e8ae9b66SAlan Carew 	return 0;
134e8ae9b66SAlan Carew }
135e8ae9b66SAlan Carew 
136e8ae9b66SAlan Carew int
set_pcpu(char * vm_name,unsigned int vcpu,unsigned int pcpu)1375776b7a3SDavid Hunt set_pcpu(char *vm_name, unsigned int vcpu, unsigned int pcpu)
138e8ae9b66SAlan Carew {
139e8ae9b66SAlan Carew 	int flags = VIR_DOMAIN_AFFECT_LIVE|VIR_DOMAIN_AFFECT_CONFIG;
140e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info;
141e8ae9b66SAlan Carew 
142751227a0SDavid Hunt 	if (vcpu >= RTE_MAX_LCORE) {
143e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "vCPU(%u) exceeds max allowable(%d)\n",
144751227a0SDavid Hunt 				vcpu, RTE_MAX_LCORE-1);
145e8ae9b66SAlan Carew 		return -1;
146e8ae9b66SAlan Carew 	}
147e8ae9b66SAlan Carew 
148e8ae9b66SAlan Carew 	vm_info = find_domain_by_name(vm_name);
149e8ae9b66SAlan Carew 	if (vm_info == NULL) {
150e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "VM '%s' not found\n", vm_name);
151e8ae9b66SAlan Carew 		return -1;
152e8ae9b66SAlan Carew 	}
153e8ae9b66SAlan Carew 
154e8ae9b66SAlan Carew 	if (!virDomainIsActive(vm_info->domainPtr)) {
155e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to set vCPU(%u) to pCPU "
156fd73630eSDavid Hunt 				" for VM '%s', VM is not active\n",
157fd73630eSDavid Hunt 				vcpu, vm_info->name);
158e8ae9b66SAlan Carew 		return -1;
159e8ae9b66SAlan Carew 	}
160e8ae9b66SAlan Carew 
161e8ae9b66SAlan Carew 	if (vcpu >= vm_info->info.nrVirtCpu) {
162e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "vCPU(%u) exceeds the assigned number of "
163e8ae9b66SAlan Carew 				"vCPUs(%u)\n", vcpu, vm_info->info.nrVirtCpu);
164e8ae9b66SAlan Carew 		return -1;
165e8ae9b66SAlan Carew 	}
166751227a0SDavid Hunt 	memset(global_cpumaps, 0, RTE_MAX_LCORE * global_maplen);
1675776b7a3SDavid Hunt 
1685776b7a3SDavid Hunt 	VIR_USE_CPU(global_cpumaps, pcpu);
1695776b7a3SDavid Hunt 
1705776b7a3SDavid Hunt 	if (pcpu >= global_n_host_cpus) {
171e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "CPU(%u) exceeds the available "
172fd73630eSDavid Hunt 				"number of CPUs(%u)\n",
1735776b7a3SDavid Hunt 				pcpu, global_n_host_cpus);
174e8ae9b66SAlan Carew 		return -1;
175e8ae9b66SAlan Carew 	}
1765776b7a3SDavid Hunt 
177e8ae9b66SAlan Carew 	if (virDomainPinVcpuFlags(vm_info->domainPtr, vcpu, global_cpumaps,
178e8ae9b66SAlan Carew 			global_maplen, flags) < 0) {
179e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to set vCPU(%u) to pCPU "
180fd73630eSDavid Hunt 				" for VM '%s'\n", vcpu,
181e8ae9b66SAlan Carew 				vm_info->name);
182e8ae9b66SAlan Carew 		return -1;
183e8ae9b66SAlan Carew 	}
184fd73630eSDavid Hunt 	rte_spinlock_lock(&(vm_info->config_spinlock));
1855776b7a3SDavid Hunt 	vm_info->pcpu_map[vcpu] = pcpu;
186fd73630eSDavid Hunt 	rte_spinlock_unlock(&(vm_info->config_spinlock));
187e8ae9b66SAlan Carew 	return 0;
188e8ae9b66SAlan Carew }
189e8ae9b66SAlan Carew 
1905776b7a3SDavid Hunt uint16_t
get_pcpu(struct channel_info * chan_info,unsigned int vcpu)1915776b7a3SDavid Hunt get_pcpu(struct channel_info *chan_info, unsigned int vcpu)
192e8ae9b66SAlan Carew {
193e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info =
194e8ae9b66SAlan Carew 			(struct virtual_machine_info *)chan_info->priv_info;
195e0207366SDavid Hunt 
1965776b7a3SDavid Hunt 	if (global_hypervisor_available && (vm_info != NULL)) {
1975776b7a3SDavid Hunt 		uint16_t pcpu;
1985776b7a3SDavid Hunt 		rte_spinlock_lock(&(vm_info->config_spinlock));
1995776b7a3SDavid Hunt 		pcpu = vm_info->pcpu_map[vcpu];
2005776b7a3SDavid Hunt 		rte_spinlock_unlock(&(vm_info->config_spinlock));
2015776b7a3SDavid Hunt 		return pcpu;
2025776b7a3SDavid Hunt 	} else
203e0207366SDavid Hunt 		return 0;
204e8ae9b66SAlan Carew }
205e8ae9b66SAlan Carew 
206e8ae9b66SAlan Carew static inline int
channel_exists(struct virtual_machine_info * vm_info,unsigned channel_num)207e8ae9b66SAlan Carew channel_exists(struct virtual_machine_info *vm_info, unsigned channel_num)
208e8ae9b66SAlan Carew {
209e8ae9b66SAlan Carew 	rte_spinlock_lock(&(vm_info->config_spinlock));
210fd73630eSDavid Hunt 	if (vm_info->channel_mask[channel_num] == 1) {
211e8ae9b66SAlan Carew 		rte_spinlock_unlock(&(vm_info->config_spinlock));
212e8ae9b66SAlan Carew 		return 1;
213e8ae9b66SAlan Carew 	}
214e8ae9b66SAlan Carew 	rte_spinlock_unlock(&(vm_info->config_spinlock));
215e8ae9b66SAlan Carew 	return 0;
216e8ae9b66SAlan Carew }
217e8ae9b66SAlan Carew 
218e8ae9b66SAlan Carew 
219e8ae9b66SAlan Carew 
220e8ae9b66SAlan Carew static int
open_non_blocking_channel(struct channel_info * info)221e8ae9b66SAlan Carew open_non_blocking_channel(struct channel_info *info)
222e8ae9b66SAlan Carew {
223e8ae9b66SAlan Carew 	int ret, flags;
224e8ae9b66SAlan Carew 	struct sockaddr_un sock_addr;
225e8ae9b66SAlan Carew 	fd_set soc_fd_set;
226e8ae9b66SAlan Carew 	struct timeval tv;
227e8ae9b66SAlan Carew 
228e8ae9b66SAlan Carew 	info->fd = socket(AF_UNIX, SOCK_STREAM, 0);
2291b897991SLukasz Krakowiak 	if (info->fd < 0) {
230e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error(%s) creating socket for '%s'\n",
231e8ae9b66SAlan Carew 				strerror(errno),
232e8ae9b66SAlan Carew 				info->channel_path);
233e8ae9b66SAlan Carew 		return -1;
234e8ae9b66SAlan Carew 	}
235e8ae9b66SAlan Carew 	sock_addr.sun_family = AF_UNIX;
236e8ae9b66SAlan Carew 	memcpy(&sock_addr.sun_path, info->channel_path,
237e8ae9b66SAlan Carew 			strlen(info->channel_path)+1);
238e8ae9b66SAlan Carew 
239e8ae9b66SAlan Carew 	/* Get current flags */
240e8ae9b66SAlan Carew 	flags = fcntl(info->fd, F_GETFL, 0);
241e8ae9b66SAlan Carew 	if (flags < 0) {
242e8ae9b66SAlan Carew 		RTE_LOG(WARNING, CHANNEL_MANAGER, "Error(%s) fcntl get flags socket for"
243e8ae9b66SAlan Carew 				"'%s'\n", strerror(errno), info->channel_path);
244e8ae9b66SAlan Carew 		return 1;
245e8ae9b66SAlan Carew 	}
246e8ae9b66SAlan Carew 	/* Set to Non Blocking */
247e8ae9b66SAlan Carew 	flags |= O_NONBLOCK;
248e8ae9b66SAlan Carew 	if (fcntl(info->fd, F_SETFL, flags) < 0) {
249e8ae9b66SAlan Carew 		RTE_LOG(WARNING, CHANNEL_MANAGER, "Error(%s) setting non-blocking "
250e8ae9b66SAlan Carew 				"socket for '%s'\n", strerror(errno), info->channel_path);
251e8ae9b66SAlan Carew 		return -1;
252e8ae9b66SAlan Carew 	}
253e8ae9b66SAlan Carew 	ret = connect(info->fd, (struct sockaddr *)&sock_addr,
254e8ae9b66SAlan Carew 			sizeof(sock_addr));
255e8ae9b66SAlan Carew 	if (ret < 0) {
256e8ae9b66SAlan Carew 		/* ECONNREFUSED error is given when VM is not active */
257e8ae9b66SAlan Carew 		if (errno == ECONNREFUSED) {
258e8ae9b66SAlan Carew 			RTE_LOG(WARNING, CHANNEL_MANAGER, "VM is not active or has not "
259e8ae9b66SAlan Carew 					"activated its endpoint to channel %s\n",
260e8ae9b66SAlan Carew 					info->channel_path);
261e8ae9b66SAlan Carew 			return -1;
262e8ae9b66SAlan Carew 		}
263e8ae9b66SAlan Carew 		/* Wait for tv_sec if in progress */
264e8ae9b66SAlan Carew 		else if (errno == EINPROGRESS) {
265e8ae9b66SAlan Carew 			tv.tv_sec = 2;
266e8ae9b66SAlan Carew 			tv.tv_usec = 0;
267e8ae9b66SAlan Carew 			FD_ZERO(&soc_fd_set);
268e8ae9b66SAlan Carew 			FD_SET(info->fd, &soc_fd_set);
269e8ae9b66SAlan Carew 			if (select(info->fd+1, NULL, &soc_fd_set, NULL, &tv) > 0) {
270e8ae9b66SAlan Carew 				RTE_LOG(WARNING, CHANNEL_MANAGER, "Timeout or error on channel "
271e8ae9b66SAlan Carew 						"'%s'\n", info->channel_path);
272e8ae9b66SAlan Carew 				return -1;
273e8ae9b66SAlan Carew 			}
274e8ae9b66SAlan Carew 		} else {
275e8ae9b66SAlan Carew 			/* Any other error */
276e8ae9b66SAlan Carew 			RTE_LOG(WARNING, CHANNEL_MANAGER, "Error(%s) connecting socket"
277e8ae9b66SAlan Carew 					" for '%s'\n", strerror(errno), info->channel_path);
278e8ae9b66SAlan Carew 			return -1;
279e8ae9b66SAlan Carew 		}
280e8ae9b66SAlan Carew 	}
281e8ae9b66SAlan Carew 	return 0;
282e8ae9b66SAlan Carew }
283e8ae9b66SAlan Carew 
284e8ae9b66SAlan Carew static int
open_host_channel(struct channel_info * info)2853618326fSDavid Hunt open_host_channel(struct channel_info *info)
2863618326fSDavid Hunt {
2873618326fSDavid Hunt 	int flags;
2883618326fSDavid Hunt 
2893618326fSDavid Hunt 	info->fd = open(info->channel_path, O_RDWR | O_RSYNC);
2901b897991SLukasz Krakowiak 	if (info->fd < 0) {
2913618326fSDavid Hunt 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error(%s) opening fifo for '%s'\n",
2923618326fSDavid Hunt 				strerror(errno),
2933618326fSDavid Hunt 				info->channel_path);
2943618326fSDavid Hunt 		return -1;
2953618326fSDavid Hunt 	}
2963618326fSDavid Hunt 
2973618326fSDavid Hunt 	/* Get current flags */
2983618326fSDavid Hunt 	flags = fcntl(info->fd, F_GETFL, 0);
2993618326fSDavid Hunt 	if (flags < 0) {
3003618326fSDavid Hunt 		RTE_LOG(WARNING, CHANNEL_MANAGER, "Error(%s) fcntl get flags socket for"
3013618326fSDavid Hunt 				"'%s'\n", strerror(errno), info->channel_path);
3023618326fSDavid Hunt 		return 1;
3033618326fSDavid Hunt 	}
3043618326fSDavid Hunt 	/* Set to Non Blocking */
3053618326fSDavid Hunt 	flags |= O_NONBLOCK;
3063618326fSDavid Hunt 	if (fcntl(info->fd, F_SETFL, flags) < 0) {
3073618326fSDavid Hunt 		RTE_LOG(WARNING, CHANNEL_MANAGER,
3083618326fSDavid Hunt 				"Error(%s) setting non-blocking "
3093618326fSDavid Hunt 				"socket for '%s'\n",
3103618326fSDavid Hunt 				strerror(errno), info->channel_path);
3113618326fSDavid Hunt 		return -1;
3123618326fSDavid Hunt 	}
3133618326fSDavid Hunt 	return 0;
3143618326fSDavid Hunt }
3153618326fSDavid Hunt 
3163618326fSDavid Hunt static int
setup_channel_info(struct virtual_machine_info ** vm_info_dptr,struct channel_info ** chan_info_dptr,unsigned channel_num)317e8ae9b66SAlan Carew setup_channel_info(struct virtual_machine_info **vm_info_dptr,
318e8ae9b66SAlan Carew 		struct channel_info **chan_info_dptr, unsigned channel_num)
319e8ae9b66SAlan Carew {
320e8ae9b66SAlan Carew 	struct channel_info *chan_info = *chan_info_dptr;
321e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info = *vm_info_dptr;
322e8ae9b66SAlan Carew 
323e8ae9b66SAlan Carew 	chan_info->channel_num = channel_num;
324e8ae9b66SAlan Carew 	chan_info->priv_info = (void *)vm_info;
325e8ae9b66SAlan Carew 	chan_info->status = CHANNEL_MGR_CHANNEL_DISCONNECTED;
3263618326fSDavid Hunt 	chan_info->type = CHANNEL_TYPE_BINARY;
327e8ae9b66SAlan Carew 	if (open_non_blocking_channel(chan_info) < 0) {
328e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Could not open channel: "
329e8ae9b66SAlan Carew 				"'%s' for VM '%s'\n",
330e8ae9b66SAlan Carew 				chan_info->channel_path, vm_info->name);
331e8ae9b66SAlan Carew 		return -1;
332e8ae9b66SAlan Carew 	}
333e8ae9b66SAlan Carew 	if (add_channel_to_monitor(&chan_info) < 0) {
334e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Could add channel: "
335e8ae9b66SAlan Carew 				"'%s' to epoll ctl for VM '%s'\n",
336e8ae9b66SAlan Carew 				chan_info->channel_path, vm_info->name);
337e8ae9b66SAlan Carew 		return -1;
338e8ae9b66SAlan Carew 
339e8ae9b66SAlan Carew 	}
340e8ae9b66SAlan Carew 	rte_spinlock_lock(&(vm_info->config_spinlock));
341e8ae9b66SAlan Carew 	vm_info->num_channels++;
342fd73630eSDavid Hunt 	vm_info->channel_mask[channel_num] = 1;
343e8ae9b66SAlan Carew 	vm_info->channels[channel_num] = chan_info;
344e8ae9b66SAlan Carew 	chan_info->status = CHANNEL_MGR_CHANNEL_CONNECTED;
345e8ae9b66SAlan Carew 	rte_spinlock_unlock(&(vm_info->config_spinlock));
346e8ae9b66SAlan Carew 	return 0;
347e8ae9b66SAlan Carew }
348e8ae9b66SAlan Carew 
349221e7026SMarcin Hajkowski static int
fifo_path(char * dst,unsigned int len,unsigned int id)350221e7026SMarcin Hajkowski fifo_path(char *dst, unsigned int len, unsigned int id)
3513618326fSDavid Hunt {
352221e7026SMarcin Hajkowski 	int cnt;
353221e7026SMarcin Hajkowski 
354221e7026SMarcin Hajkowski 	cnt = snprintf(dst, len, "%s%s%d", CHANNEL_MGR_SOCKET_PATH,
355221e7026SMarcin Hajkowski 			CHANNEL_MGR_FIFO_PATTERN_NAME, id);
356221e7026SMarcin Hajkowski 
357221e7026SMarcin Hajkowski 	if ((cnt < 0) || (cnt > (int)len - 1)) {
358221e7026SMarcin Hajkowski 		RTE_LOG(ERR, CHANNEL_MANAGER, "Could not create proper "
359221e7026SMarcin Hajkowski 			"string for fifo path\n");
360221e7026SMarcin Hajkowski 
361221e7026SMarcin Hajkowski 		return -1;
362221e7026SMarcin Hajkowski 	}
363221e7026SMarcin Hajkowski 
364221e7026SMarcin Hajkowski 	return 0;
3653618326fSDavid Hunt }
3663618326fSDavid Hunt 
3673618326fSDavid Hunt static int
setup_host_channel_info(struct channel_info ** chan_info_dptr,unsigned int channel_num)3683618326fSDavid Hunt setup_host_channel_info(struct channel_info **chan_info_dptr,
3693618326fSDavid Hunt 		unsigned int channel_num)
3703618326fSDavid Hunt {
3713618326fSDavid Hunt 	struct channel_info *chan_info = *chan_info_dptr;
3723618326fSDavid Hunt 
3733618326fSDavid Hunt 	chan_info->channel_num = channel_num;
3743618326fSDavid Hunt 	chan_info->priv_info = (void *)NULL;
3753618326fSDavid Hunt 	chan_info->status = CHANNEL_MGR_CHANNEL_DISCONNECTED;
3763618326fSDavid Hunt 	chan_info->type = CHANNEL_TYPE_JSON;
3773618326fSDavid Hunt 
3783618326fSDavid Hunt 	if (open_host_channel(chan_info) < 0) {
3793618326fSDavid Hunt 		RTE_LOG(ERR, CHANNEL_MANAGER, "Could not open host channel: "
3803618326fSDavid Hunt 				"'%s'\n",
3813618326fSDavid Hunt 				chan_info->channel_path);
3823618326fSDavid Hunt 		return -1;
3833618326fSDavid Hunt 	}
3843618326fSDavid Hunt 	if (add_channel_to_monitor(&chan_info) < 0) {
3853618326fSDavid Hunt 		RTE_LOG(ERR, CHANNEL_MANAGER, "Could add channel: "
3863618326fSDavid Hunt 				"'%s' to epoll ctl\n",
3873618326fSDavid Hunt 				chan_info->channel_path);
3883618326fSDavid Hunt 		return -1;
3893618326fSDavid Hunt 
3903618326fSDavid Hunt 	}
3913618326fSDavid Hunt 	chan_info->status = CHANNEL_MGR_CHANNEL_CONNECTED;
3923618326fSDavid Hunt 	return 0;
3933618326fSDavid Hunt }
3943618326fSDavid Hunt 
395e8ae9b66SAlan Carew int
add_all_channels(const char * vm_name)396e8ae9b66SAlan Carew add_all_channels(const char *vm_name)
397e8ae9b66SAlan Carew {
398e8ae9b66SAlan Carew 	DIR *d;
399e8ae9b66SAlan Carew 	struct dirent *dir;
400e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info;
401e8ae9b66SAlan Carew 	struct channel_info *chan_info;
402e8ae9b66SAlan Carew 	char *token, *remaining, *tail_ptr;
403e8ae9b66SAlan Carew 	char socket_name[PATH_MAX];
404e8ae9b66SAlan Carew 	unsigned channel_num;
405e8ae9b66SAlan Carew 	int num_channels_enabled = 0;
406e8ae9b66SAlan Carew 
407e8ae9b66SAlan Carew 	/* verify VM exists */
408e8ae9b66SAlan Carew 	vm_info = find_domain_by_name(vm_name);
409e8ae9b66SAlan Carew 	if (vm_info == NULL) {
410e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "VM: '%s' not found"
411e8ae9b66SAlan Carew 				" during channel discovery\n", vm_name);
412e8ae9b66SAlan Carew 		return 0;
413e8ae9b66SAlan Carew 	}
414e8ae9b66SAlan Carew 	if (!virDomainIsActive(vm_info->domainPtr)) {
415e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "VM: '%s' is not active\n", vm_name);
416e8ae9b66SAlan Carew 		vm_info->status = CHANNEL_MGR_VM_INACTIVE;
417e8ae9b66SAlan Carew 		return 0;
418e8ae9b66SAlan Carew 	}
419e8ae9b66SAlan Carew 	d = opendir(CHANNEL_MGR_SOCKET_PATH);
420e8ae9b66SAlan Carew 	if (d == NULL) {
421e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error opening directory '%s': %s\n",
422e8ae9b66SAlan Carew 				CHANNEL_MGR_SOCKET_PATH, strerror(errno));
423e8ae9b66SAlan Carew 		return -1;
424e8ae9b66SAlan Carew 	}
425e8ae9b66SAlan Carew 	while ((dir = readdir(d)) != NULL) {
426e8ae9b66SAlan Carew 		if (!strncmp(dir->d_name, ".", 1) ||
427e8ae9b66SAlan Carew 				!strncmp(dir->d_name, "..", 2))
428e8ae9b66SAlan Carew 			continue;
429e8ae9b66SAlan Carew 
4306723c0fcSBruce Richardson 		strlcpy(socket_name, dir->d_name, sizeof(socket_name));
431e8ae9b66SAlan Carew 		remaining = socket_name;
432e8ae9b66SAlan Carew 		/* Extract vm_name from "<vm_name>.<channel_num>" */
433e8ae9b66SAlan Carew 		token = strsep(&remaining, ".");
434e8ae9b66SAlan Carew 		if (remaining == NULL)
435e8ae9b66SAlan Carew 			continue;
436e8ae9b66SAlan Carew 		if (strncmp(vm_name, token, CHANNEL_MGR_MAX_NAME_LEN))
437e8ae9b66SAlan Carew 			continue;
438e8ae9b66SAlan Carew 
439e8ae9b66SAlan Carew 		/* remaining should contain only <channel_num> */
440e8ae9b66SAlan Carew 		errno = 0;
441e8ae9b66SAlan Carew 		channel_num = (unsigned)strtol(remaining, &tail_ptr, 0);
442e8ae9b66SAlan Carew 		if ((errno != 0) || (remaining[0] == '\0') ||
4435b628fe1SBruce Richardson 				tail_ptr == NULL || (*tail_ptr != '\0')) {
444e8ae9b66SAlan Carew 			RTE_LOG(WARNING, CHANNEL_MANAGER, "Malformed channel name"
445e8ae9b66SAlan Carew 					"'%s' found it should be in the form of "
446e8ae9b66SAlan Carew 					"'<guest_name>.<channel_num>(decimal)'\n",
447e8ae9b66SAlan Carew 					dir->d_name);
448e8ae9b66SAlan Carew 			continue;
449e8ae9b66SAlan Carew 		}
450751227a0SDavid Hunt 		if (channel_num >= RTE_MAX_LCORE) {
451e8ae9b66SAlan Carew 			RTE_LOG(WARNING, CHANNEL_MANAGER, "Channel number(%u) is "
452e8ae9b66SAlan Carew 					"greater than max allowable: %d, skipping '%s%s'\n",
453751227a0SDavid Hunt 					channel_num, RTE_MAX_LCORE-1,
454e8ae9b66SAlan Carew 					CHANNEL_MGR_SOCKET_PATH, dir->d_name);
455e8ae9b66SAlan Carew 			continue;
456e8ae9b66SAlan Carew 		}
457e8ae9b66SAlan Carew 		/* if channel has not been added previously */
458e8ae9b66SAlan Carew 		if (channel_exists(vm_info, channel_num))
459e8ae9b66SAlan Carew 			continue;
460e8ae9b66SAlan Carew 
461e8ae9b66SAlan Carew 		chan_info = rte_malloc(NULL, sizeof(*chan_info),
462fdf20fa7SSergio Gonzalez Monroy 				RTE_CACHE_LINE_SIZE);
463e8ae9b66SAlan Carew 		if (chan_info == NULL) {
464e8ae9b66SAlan Carew 			RTE_LOG(ERR, CHANNEL_MANAGER, "Error allocating memory for "
465e8ae9b66SAlan Carew 				"channel '%s%s'\n", CHANNEL_MGR_SOCKET_PATH, dir->d_name);
466e8ae9b66SAlan Carew 			continue;
467e8ae9b66SAlan Carew 		}
468e8ae9b66SAlan Carew 
469a9f57cfcSBruce Richardson 		if ((size_t)snprintf(chan_info->channel_path,
470e8ae9b66SAlan Carew 				sizeof(chan_info->channel_path), "%s%s",
471a9f57cfcSBruce Richardson 				CHANNEL_MGR_SOCKET_PATH, dir->d_name)
472a9f57cfcSBruce Richardson 					>= sizeof(chan_info->channel_path)) {
473a9f57cfcSBruce Richardson 			RTE_LOG(ERR, CHANNEL_MANAGER, "Pathname too long for channel '%s%s'\n",
474e8ae9b66SAlan Carew 					CHANNEL_MGR_SOCKET_PATH, dir->d_name);
475a9f57cfcSBruce Richardson 			rte_free(chan_info);
476a9f57cfcSBruce Richardson 			continue;
477a9f57cfcSBruce Richardson 		}
478e8ae9b66SAlan Carew 
479e8ae9b66SAlan Carew 		if (setup_channel_info(&vm_info, &chan_info, channel_num) < 0) {
480e8ae9b66SAlan Carew 			rte_free(chan_info);
481e8ae9b66SAlan Carew 			continue;
482e8ae9b66SAlan Carew 		}
483e8ae9b66SAlan Carew 
484e8ae9b66SAlan Carew 		num_channels_enabled++;
485e8ae9b66SAlan Carew 	}
486e8ae9b66SAlan Carew 	closedir(d);
487e8ae9b66SAlan Carew 	return num_channels_enabled;
488e8ae9b66SAlan Carew }
489e8ae9b66SAlan Carew 
490e8ae9b66SAlan Carew int
add_channels(const char * vm_name,unsigned * channel_list,unsigned len_channel_list)491e8ae9b66SAlan Carew add_channels(const char *vm_name, unsigned *channel_list,
492e8ae9b66SAlan Carew 		unsigned len_channel_list)
493e8ae9b66SAlan Carew {
494e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info;
495e8ae9b66SAlan Carew 	struct channel_info *chan_info;
496e8ae9b66SAlan Carew 	char socket_path[PATH_MAX];
497e8ae9b66SAlan Carew 	unsigned i;
498e8ae9b66SAlan Carew 	int num_channels_enabled = 0;
499e8ae9b66SAlan Carew 
500e8ae9b66SAlan Carew 	vm_info = find_domain_by_name(vm_name);
501e8ae9b66SAlan Carew 	if (vm_info == NULL) {
502e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to add channels: VM '%s' "
503e8ae9b66SAlan Carew 				"not found\n", vm_name);
504e8ae9b66SAlan Carew 		return 0;
505e8ae9b66SAlan Carew 	}
506e8ae9b66SAlan Carew 
507e8ae9b66SAlan Carew 	if (!virDomainIsActive(vm_info->domainPtr)) {
508e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "VM: '%s' is not active\n", vm_name);
509e8ae9b66SAlan Carew 		vm_info->status = CHANNEL_MGR_VM_INACTIVE;
510e8ae9b66SAlan Carew 		return 0;
511e8ae9b66SAlan Carew 	}
512e8ae9b66SAlan Carew 
513e8ae9b66SAlan Carew 	for (i = 0; i < len_channel_list; i++) {
514751227a0SDavid Hunt 		if (channel_list[i] >= RTE_MAX_LCORE) {
515e8ae9b66SAlan Carew 			RTE_LOG(INFO, CHANNEL_MANAGER, "Channel(%u) is out of range "
516e8ae9b66SAlan Carew 							"0...%d\n", channel_list[i],
517751227a0SDavid Hunt 							RTE_MAX_LCORE-1);
518e8ae9b66SAlan Carew 			continue;
519e8ae9b66SAlan Carew 		}
520e8ae9b66SAlan Carew 		if (channel_exists(vm_info, channel_list[i])) {
521e8ae9b66SAlan Carew 			RTE_LOG(INFO, CHANNEL_MANAGER, "Channel already exists, skipping  "
522e8ae9b66SAlan Carew 					"'%s.%u'\n", vm_name, i);
523e8ae9b66SAlan Carew 			continue;
524e8ae9b66SAlan Carew 		}
525e8ae9b66SAlan Carew 
526e8ae9b66SAlan Carew 		snprintf(socket_path, sizeof(socket_path), "%s%s.%u",
527e8ae9b66SAlan Carew 				CHANNEL_MGR_SOCKET_PATH, vm_name, channel_list[i]);
528e8ae9b66SAlan Carew 		errno = 0;
529e8ae9b66SAlan Carew 		if (access(socket_path, F_OK) < 0) {
530e8ae9b66SAlan Carew 			RTE_LOG(ERR, CHANNEL_MANAGER, "Channel path '%s' error: "
531e8ae9b66SAlan Carew 					"%s\n", socket_path, strerror(errno));
532e8ae9b66SAlan Carew 			continue;
533e8ae9b66SAlan Carew 		}
534e8ae9b66SAlan Carew 		chan_info = rte_malloc(NULL, sizeof(*chan_info),
535fdf20fa7SSergio Gonzalez Monroy 				RTE_CACHE_LINE_SIZE);
536e8ae9b66SAlan Carew 		if (chan_info == NULL) {
537e8ae9b66SAlan Carew 			RTE_LOG(ERR, CHANNEL_MANAGER, "Error allocating memory for "
538e8ae9b66SAlan Carew 					"channel '%s'\n", socket_path);
539e8ae9b66SAlan Carew 			continue;
540e8ae9b66SAlan Carew 		}
541e8ae9b66SAlan Carew 		snprintf(chan_info->channel_path,
542e8ae9b66SAlan Carew 				sizeof(chan_info->channel_path), "%s%s.%u",
543e8ae9b66SAlan Carew 				CHANNEL_MGR_SOCKET_PATH, vm_name, channel_list[i]);
544e8ae9b66SAlan Carew 		if (setup_channel_info(&vm_info, &chan_info, channel_list[i]) < 0) {
545e8ae9b66SAlan Carew 			rte_free(chan_info);
546e8ae9b66SAlan Carew 			continue;
547e8ae9b66SAlan Carew 		}
548e8ae9b66SAlan Carew 		num_channels_enabled++;
549e8ae9b66SAlan Carew 
550e8ae9b66SAlan Carew 	}
551e8ae9b66SAlan Carew 	return num_channels_enabled;
552e8ae9b66SAlan Carew }
553e8ae9b66SAlan Carew 
554e8ae9b66SAlan Carew int
add_host_channels(void)555221e7026SMarcin Hajkowski add_host_channels(void)
5563618326fSDavid Hunt {
5573618326fSDavid Hunt 	struct channel_info *chan_info;
5583618326fSDavid Hunt 	char socket_path[PATH_MAX];
5593618326fSDavid Hunt 	int num_channels_enabled = 0;
5603618326fSDavid Hunt 	int ret;
561221e7026SMarcin Hajkowski 	struct core_info *ci;
562221e7026SMarcin Hajkowski 	struct channel_info *chan_infos[RTE_MAX_LCORE];
563221e7026SMarcin Hajkowski 	int i;
5643618326fSDavid Hunt 
565221e7026SMarcin Hajkowski 	for (i = 0; i < RTE_MAX_LCORE; i++)
566221e7026SMarcin Hajkowski 		chan_infos[i] = NULL;
5673618326fSDavid Hunt 
568221e7026SMarcin Hajkowski 	ci = get_core_info();
569221e7026SMarcin Hajkowski 	if (ci == NULL) {
570221e7026SMarcin Hajkowski 		RTE_LOG(ERR, CHANNEL_MANAGER, "Cannot allocate memory for core_info\n");
5713618326fSDavid Hunt 		return 0;
5723618326fSDavid Hunt 	}
5733618326fSDavid Hunt 
574221e7026SMarcin Hajkowski 	for (i = 0; i < ci->core_count; i++) {
575b49c677aSDavid Hunt 		if (rte_lcore_index(i) == -1)
576b49c677aSDavid Hunt 			continue;
577b49c677aSDavid Hunt 
578221e7026SMarcin Hajkowski 		if (ci->cd[i].global_enabled_cpus == 0)
579221e7026SMarcin Hajkowski 			continue;
580221e7026SMarcin Hajkowski 
581221e7026SMarcin Hajkowski 		ret = fifo_path(socket_path, sizeof(socket_path), i);
582221e7026SMarcin Hajkowski 		if (ret < 0)
583221e7026SMarcin Hajkowski 			goto error;
584221e7026SMarcin Hajkowski 
585221e7026SMarcin Hajkowski 		ret = mkfifo(socket_path, 0660);
586221e7026SMarcin Hajkowski 		RTE_LOG(DEBUG, CHANNEL_MANAGER, "TRY CREATE fifo '%s'\n",
587221e7026SMarcin Hajkowski 			socket_path);
588221e7026SMarcin Hajkowski 		if ((errno != EEXIST) && (ret < 0)) {
589221e7026SMarcin Hajkowski 			RTE_LOG(ERR, CHANNEL_MANAGER, "Cannot create fifo '%s' error: "
5903618326fSDavid Hunt 					"%s\n", socket_path, strerror(errno));
591221e7026SMarcin Hajkowski 			goto error;
5923618326fSDavid Hunt 		}
5933618326fSDavid Hunt 		chan_info = rte_malloc(NULL, sizeof(*chan_info), 0);
5943618326fSDavid Hunt 		if (chan_info == NULL) {
5953618326fSDavid Hunt 			RTE_LOG(ERR, CHANNEL_MANAGER, "Error allocating memory for "
5963618326fSDavid Hunt 					"channel '%s'\n", socket_path);
597221e7026SMarcin Hajkowski 			goto error;
5983618326fSDavid Hunt 		}
599221e7026SMarcin Hajkowski 		chan_infos[i] = chan_info;
600135393d4SDavid Hunt 		strlcpy(chan_info->channel_path, socket_path,
601221e7026SMarcin Hajkowski 				sizeof(chan_info->channel_path));
60260dea75fSLukasz Krakowiak 
603221e7026SMarcin Hajkowski 		if (setup_host_channel_info(&chan_info, i) < 0) {
6043618326fSDavid Hunt 			rte_free(chan_info);
605221e7026SMarcin Hajkowski 			chan_infos[i] = NULL;
606221e7026SMarcin Hajkowski 			goto error;
6073618326fSDavid Hunt 		}
6083618326fSDavid Hunt 		num_channels_enabled++;
609221e7026SMarcin Hajkowski 	}
6103618326fSDavid Hunt 
6113618326fSDavid Hunt 	return num_channels_enabled;
612221e7026SMarcin Hajkowski error:
613221e7026SMarcin Hajkowski 	/* Clean up the channels opened before we hit an error. */
614221e7026SMarcin Hajkowski 	for (i = 0; i < ci->core_count; i++) {
615221e7026SMarcin Hajkowski 		if (chan_infos[i] != NULL) {
616221e7026SMarcin Hajkowski 			remove_channel_from_monitor(chan_infos[i]);
617221e7026SMarcin Hajkowski 			close(chan_infos[i]->fd);
618221e7026SMarcin Hajkowski 			rte_free(chan_infos[i]);
619221e7026SMarcin Hajkowski 		}
620221e7026SMarcin Hajkowski 	}
621221e7026SMarcin Hajkowski 	return 0;
6223618326fSDavid Hunt }
6233618326fSDavid Hunt 
6243618326fSDavid Hunt int
remove_channel(struct channel_info ** chan_info_dptr)625e8ae9b66SAlan Carew remove_channel(struct channel_info **chan_info_dptr)
626e8ae9b66SAlan Carew {
627e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info;
628e8ae9b66SAlan Carew 	struct channel_info *chan_info = *chan_info_dptr;
629e8ae9b66SAlan Carew 
630e8ae9b66SAlan Carew 	close(chan_info->fd);
631e8ae9b66SAlan Carew 
632e8ae9b66SAlan Carew 	vm_info = (struct virtual_machine_info *)chan_info->priv_info;
633e8ae9b66SAlan Carew 
634e8ae9b66SAlan Carew 	rte_spinlock_lock(&(vm_info->config_spinlock));
635fd73630eSDavid Hunt 	vm_info->channel_mask[chan_info->channel_num] = 0;
636e8ae9b66SAlan Carew 	vm_info->num_channels--;
637e8ae9b66SAlan Carew 	rte_spinlock_unlock(&(vm_info->config_spinlock));
638e8ae9b66SAlan Carew 
639e8ae9b66SAlan Carew 	rte_free(chan_info);
640e8ae9b66SAlan Carew 	return 0;
641e8ae9b66SAlan Carew }
642e8ae9b66SAlan Carew 
643e8ae9b66SAlan Carew int
set_channel_status_all(const char * vm_name,enum channel_status status)644e8ae9b66SAlan Carew set_channel_status_all(const char *vm_name, enum channel_status status)
645e8ae9b66SAlan Carew {
646e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info;
647e8ae9b66SAlan Carew 	unsigned i;
648751227a0SDavid Hunt 	char mask[RTE_MAX_LCORE];
649e8ae9b66SAlan Carew 	int num_channels_changed = 0;
650e8ae9b66SAlan Carew 
651e8ae9b66SAlan Carew 	if (!(status == CHANNEL_MGR_CHANNEL_CONNECTED ||
652e8ae9b66SAlan Carew 			status == CHANNEL_MGR_CHANNEL_DISABLED)) {
653e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Channels can only be enabled or "
654e8ae9b66SAlan Carew 				"disabled: Unable to change status for VM '%s'\n", vm_name);
655e8ae9b66SAlan Carew 	}
656e8ae9b66SAlan Carew 	vm_info = find_domain_by_name(vm_name);
657e8ae9b66SAlan Carew 	if (vm_info == NULL) {
658e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to disable channels: VM '%s' "
659e8ae9b66SAlan Carew 				"not found\n", vm_name);
660e8ae9b66SAlan Carew 		return 0;
661e8ae9b66SAlan Carew 	}
662e8ae9b66SAlan Carew 
663e8ae9b66SAlan Carew 	rte_spinlock_lock(&(vm_info->config_spinlock));
664751227a0SDavid Hunt 	memcpy(mask, (char *)vm_info->channel_mask, RTE_MAX_LCORE);
665751227a0SDavid Hunt 	for (i = 0; i < RTE_MAX_LCORE; i++) {
666fd73630eSDavid Hunt 		if (mask[i] != 1)
667fd73630eSDavid Hunt 			continue;
668e8ae9b66SAlan Carew 		vm_info->channels[i]->status = status;
669e8ae9b66SAlan Carew 		num_channels_changed++;
670e8ae9b66SAlan Carew 	}
671e8ae9b66SAlan Carew 	rte_spinlock_unlock(&(vm_info->config_spinlock));
672e8ae9b66SAlan Carew 	return num_channels_changed;
673e8ae9b66SAlan Carew 
674e8ae9b66SAlan Carew }
675e8ae9b66SAlan Carew 
676e8ae9b66SAlan Carew int
set_channel_status(const char * vm_name,unsigned * channel_list,unsigned len_channel_list,enum channel_status status)677e8ae9b66SAlan Carew set_channel_status(const char *vm_name, unsigned *channel_list,
678e8ae9b66SAlan Carew 		unsigned len_channel_list, enum channel_status status)
679e8ae9b66SAlan Carew {
680e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info;
681e8ae9b66SAlan Carew 	unsigned i;
682e8ae9b66SAlan Carew 	int num_channels_changed = 0;
683e8ae9b66SAlan Carew 
684e8ae9b66SAlan Carew 	if (!(status == CHANNEL_MGR_CHANNEL_CONNECTED ||
685e8ae9b66SAlan Carew 			status == CHANNEL_MGR_CHANNEL_DISABLED)) {
686e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Channels can only be enabled or "
687e8ae9b66SAlan Carew 				"disabled: Unable to change status for VM '%s'\n", vm_name);
688e8ae9b66SAlan Carew 	}
689e8ae9b66SAlan Carew 	vm_info = find_domain_by_name(vm_name);
690e8ae9b66SAlan Carew 	if (vm_info == NULL) {
691e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to add channels: VM '%s' "
692e8ae9b66SAlan Carew 				"not found\n", vm_name);
693e8ae9b66SAlan Carew 		return 0;
694e8ae9b66SAlan Carew 	}
695e8ae9b66SAlan Carew 	for (i = 0; i < len_channel_list; i++) {
696e8ae9b66SAlan Carew 		if (channel_exists(vm_info, channel_list[i])) {
697e8ae9b66SAlan Carew 			rte_spinlock_lock(&(vm_info->config_spinlock));
698e8ae9b66SAlan Carew 			vm_info->channels[channel_list[i]]->status = status;
699e8ae9b66SAlan Carew 			rte_spinlock_unlock(&(vm_info->config_spinlock));
700e8ae9b66SAlan Carew 			num_channels_changed++;
701e8ae9b66SAlan Carew 		}
702e8ae9b66SAlan Carew 	}
703e8ae9b66SAlan Carew 	return num_channels_changed;
704e8ae9b66SAlan Carew }
705e8ae9b66SAlan Carew 
706dff22404SDavid Hunt void
get_all_vm(int * num_vm,int * num_vcpu)707dff22404SDavid Hunt get_all_vm(int *num_vm, int *num_vcpu)
708dff22404SDavid Hunt {
709dff22404SDavid Hunt 
710dff22404SDavid Hunt 	virNodeInfo node_info;
711dff22404SDavid Hunt 	virDomainPtr *domptr;
712fd73630eSDavid Hunt 	int i, ii, numVcpus[MAX_VCPUS], n_vcpus;
713dff22404SDavid Hunt 	unsigned int jj;
714dff22404SDavid Hunt 	const char *vm_name;
715dff22404SDavid Hunt 	unsigned int domain_flags = VIR_CONNECT_LIST_DOMAINS_RUNNING |
716dff22404SDavid Hunt 				VIR_CONNECT_LIST_DOMAINS_PERSISTENT;
717dff22404SDavid Hunt 	unsigned int domain_flag = VIR_DOMAIN_VCPU_CONFIG;
718dff22404SDavid Hunt 
719e0207366SDavid Hunt 	if (!global_hypervisor_available)
720e0207366SDavid Hunt 		return;
721dff22404SDavid Hunt 
722751227a0SDavid Hunt 	memset(global_cpumaps, 0, RTE_MAX_LCORE*global_maplen);
723dff22404SDavid Hunt 	if (virNodeGetInfo(global_vir_conn_ptr, &node_info)) {
724dff22404SDavid Hunt 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to retrieve node Info\n");
725dff22404SDavid Hunt 		return;
726dff22404SDavid Hunt 	}
727dff22404SDavid Hunt 
728dff22404SDavid Hunt 	/* Returns number of pcpus */
729dff22404SDavid Hunt 	global_n_host_cpus = (unsigned int)node_info.cpus;
730dff22404SDavid Hunt 
731dff22404SDavid Hunt 	/* Returns number of active domains */
732dff22404SDavid Hunt 	*num_vm = virConnectListAllDomains(global_vir_conn_ptr, &domptr,
733dff22404SDavid Hunt 					domain_flags);
734dff22404SDavid Hunt 	if (*num_vm <= 0) {
735dff22404SDavid Hunt 		RTE_LOG(ERR, CHANNEL_MANAGER, "No Active Domains Running\n");
736dff22404SDavid Hunt 		return;
737dff22404SDavid Hunt 	}
738dff22404SDavid Hunt 
739dff22404SDavid Hunt 	for (i = 0; i < *num_vm; i++) {
740dff22404SDavid Hunt 
741dff22404SDavid Hunt 		/* Get Domain Names */
742dff22404SDavid Hunt 		vm_name = virDomainGetName(domptr[i]);
743dff22404SDavid Hunt 		lvm_info[i].vm_name = vm_name;
744dff22404SDavid Hunt 
745dff22404SDavid Hunt 		/* Get Number of Vcpus */
746dff22404SDavid Hunt 		numVcpus[i] = virDomainGetVcpusFlags(domptr[i], domain_flag);
747dff22404SDavid Hunt 
748dff22404SDavid Hunt 		/* Get Number of VCpus & VcpuPinInfo */
749dff22404SDavid Hunt 		n_vcpus = virDomainGetVcpuPinInfo(domptr[i],
750dff22404SDavid Hunt 				numVcpus[i], global_cpumaps,
751dff22404SDavid Hunt 				global_maplen, domain_flag);
752dff22404SDavid Hunt 
753dff22404SDavid Hunt 		if ((int)n_vcpus > 0) {
754dff22404SDavid Hunt 			*num_vcpu = n_vcpus;
755dff22404SDavid Hunt 			lvm_info[i].num_cpus = n_vcpus;
756dff22404SDavid Hunt 		}
757dff22404SDavid Hunt 
758dff22404SDavid Hunt 		/* Save pcpu in use by libvirt VMs */
759dff22404SDavid Hunt 		for (ii = 0; ii < n_vcpus; ii++) {
760dff22404SDavid Hunt 			for (jj = 0; jj < global_n_host_cpus; jj++) {
761dff22404SDavid Hunt 				if (VIR_CPU_USABLE(global_cpumaps,
762dff22404SDavid Hunt 						global_maplen, ii, jj) > 0) {
763fd73630eSDavid Hunt 					lvm_info[i].pcpus[ii] = jj;
764dff22404SDavid Hunt 				}
765dff22404SDavid Hunt 			}
766dff22404SDavid Hunt 		}
767dff22404SDavid Hunt 	}
768dff22404SDavid Hunt }
769dff22404SDavid Hunt 
770e8ae9b66SAlan Carew int
get_info_vm(const char * vm_name,struct vm_info * info)771e8ae9b66SAlan Carew get_info_vm(const char *vm_name, struct vm_info *info)
772e8ae9b66SAlan Carew {
773e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info;
774e8ae9b66SAlan Carew 	unsigned i, channel_num = 0;
775751227a0SDavid Hunt 	char mask[RTE_MAX_LCORE];
776e8ae9b66SAlan Carew 
777e8ae9b66SAlan Carew 	vm_info = find_domain_by_name(vm_name);
778e8ae9b66SAlan Carew 	if (vm_info == NULL) {
779e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "VM '%s' not found\n", vm_name);
780e8ae9b66SAlan Carew 		return -1;
781e8ae9b66SAlan Carew 	}
782e8ae9b66SAlan Carew 	info->status = CHANNEL_MGR_VM_ACTIVE;
783e8ae9b66SAlan Carew 	if (!virDomainIsActive(vm_info->domainPtr))
784e8ae9b66SAlan Carew 		info->status = CHANNEL_MGR_VM_INACTIVE;
785e8ae9b66SAlan Carew 
786e8ae9b66SAlan Carew 	rte_spinlock_lock(&(vm_info->config_spinlock));
787e8ae9b66SAlan Carew 
788751227a0SDavid Hunt 	memcpy(mask, (char *)vm_info->channel_mask, RTE_MAX_LCORE);
789751227a0SDavid Hunt 	for (i = 0; i < RTE_MAX_LCORE; i++) {
790fd73630eSDavid Hunt 		if (mask[i] != 1)
791fd73630eSDavid Hunt 			continue;
792e8ae9b66SAlan Carew 		info->channels[channel_num].channel_num = i;
793e8ae9b66SAlan Carew 		memcpy(info->channels[channel_num].channel_path,
794fd73630eSDavid Hunt 				vm_info->channels[i]->channel_path,
795fd73630eSDavid Hunt 				UNIX_PATH_MAX);
796fd73630eSDavid Hunt 		info->channels[channel_num].status =
797fd73630eSDavid Hunt 				vm_info->channels[i]->status;
798fd73630eSDavid Hunt 		info->channels[channel_num].fd =
799fd73630eSDavid Hunt 				vm_info->channels[i]->fd;
800e8ae9b66SAlan Carew 		channel_num++;
801e8ae9b66SAlan Carew 	}
802e8ae9b66SAlan Carew 
8031deb502eSMarcin Hajkowski 	info->allow_query = vm_info->allow_query;
804e8ae9b66SAlan Carew 	info->num_channels = channel_num;
805e8ae9b66SAlan Carew 	info->num_vcpus = vm_info->info.nrVirtCpu;
806e8ae9b66SAlan Carew 	rte_spinlock_unlock(&(vm_info->config_spinlock));
807e8ae9b66SAlan Carew 
808e8ae9b66SAlan Carew 	memcpy(info->name, vm_info->name, sizeof(vm_info->name));
8095776b7a3SDavid Hunt 	rte_spinlock_lock(&(vm_info->config_spinlock));
810e8ae9b66SAlan Carew 	for (i = 0; i < info->num_vcpus; i++) {
8115776b7a3SDavid Hunt 		info->pcpu_map[i] = vm_info->pcpu_map[i];
812e8ae9b66SAlan Carew 	}
8135776b7a3SDavid Hunt 	rte_spinlock_unlock(&(vm_info->config_spinlock));
814e8ae9b66SAlan Carew 	return 0;
815e8ae9b66SAlan Carew }
816e8ae9b66SAlan Carew 
817e8ae9b66SAlan Carew int
add_vm(const char * vm_name)818e8ae9b66SAlan Carew add_vm(const char *vm_name)
819e8ae9b66SAlan Carew {
820e8ae9b66SAlan Carew 	struct virtual_machine_info *new_domain;
821e8ae9b66SAlan Carew 	virDomainPtr dom_ptr;
822e8ae9b66SAlan Carew 	int i;
823e8ae9b66SAlan Carew 
824e8ae9b66SAlan Carew 	if (find_domain_by_name(vm_name) != NULL) {
825e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to add VM: VM '%s' "
826e8ae9b66SAlan Carew 				"already exists\n", vm_name);
827e8ae9b66SAlan Carew 		return -1;
828e8ae9b66SAlan Carew 	}
829e8ae9b66SAlan Carew 
830e8ae9b66SAlan Carew 	if (global_vir_conn_ptr == NULL) {
831e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "No connection to hypervisor exists\n");
832e8ae9b66SAlan Carew 		return -1;
833e8ae9b66SAlan Carew 	}
834e8ae9b66SAlan Carew 	dom_ptr = virDomainLookupByName(global_vir_conn_ptr, vm_name);
835e8ae9b66SAlan Carew 	if (dom_ptr == NULL) {
836e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error on VM lookup with libvirt: "
837e8ae9b66SAlan Carew 				"VM '%s' not found\n", vm_name);
838e8ae9b66SAlan Carew 		return -1;
839e8ae9b66SAlan Carew 	}
840e8ae9b66SAlan Carew 
841e8ae9b66SAlan Carew 	new_domain = rte_malloc("virtual_machine_info", sizeof(*new_domain),
842fdf20fa7SSergio Gonzalez Monroy 			RTE_CACHE_LINE_SIZE);
843e8ae9b66SAlan Carew 	if (new_domain == NULL) {
844e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to allocate memory for VM "
845e8ae9b66SAlan Carew 				"info\n");
846e8ae9b66SAlan Carew 		return -1;
847e8ae9b66SAlan Carew 	}
848e8ae9b66SAlan Carew 	new_domain->domainPtr = dom_ptr;
849e8ae9b66SAlan Carew 	if (virDomainGetInfo(new_domain->domainPtr, &new_domain->info) != 0) {
850e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to get libvirt VM info\n");
851e8ae9b66SAlan Carew 		rte_free(new_domain);
852e8ae9b66SAlan Carew 		return -1;
853e8ae9b66SAlan Carew 	}
854751227a0SDavid Hunt 	if (new_domain->info.nrVirtCpu > RTE_MAX_LCORE) {
855e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error the number of virtual CPUs(%u) is "
856e8ae9b66SAlan Carew 				"greater than allowable(%d)\n", new_domain->info.nrVirtCpu,
857751227a0SDavid Hunt 				RTE_MAX_LCORE);
858e8ae9b66SAlan Carew 		rte_free(new_domain);
859e8ae9b66SAlan Carew 		return -1;
860e8ae9b66SAlan Carew 	}
861e8ae9b66SAlan Carew 
862751227a0SDavid Hunt 	for (i = 0; i < RTE_MAX_LCORE; i++)
8635776b7a3SDavid Hunt 		new_domain->pcpu_map[i] = 0;
864751227a0SDavid Hunt 
865e8ae9b66SAlan Carew 	if (update_pcpus_mask(new_domain) < 0) {
866e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error getting physical CPU pinning\n");
867e8ae9b66SAlan Carew 		rte_free(new_domain);
868e8ae9b66SAlan Carew 		return -1;
869e8ae9b66SAlan Carew 	}
870e8ae9b66SAlan Carew 	strncpy(new_domain->name, vm_name, sizeof(new_domain->name));
87142b3f505SDaniel Mrzyglod 	new_domain->name[sizeof(new_domain->name) - 1] = '\0';
872751227a0SDavid Hunt 	memset(new_domain->channel_mask, 0, RTE_MAX_LCORE);
873e8ae9b66SAlan Carew 	new_domain->num_channels = 0;
874e8ae9b66SAlan Carew 
875e8ae9b66SAlan Carew 	if (!virDomainIsActive(dom_ptr))
876e8ae9b66SAlan Carew 		new_domain->status = CHANNEL_MGR_VM_INACTIVE;
877e8ae9b66SAlan Carew 	else
878e8ae9b66SAlan Carew 		new_domain->status = CHANNEL_MGR_VM_ACTIVE;
879e8ae9b66SAlan Carew 
8801deb502eSMarcin Hajkowski 	new_domain->allow_query = 0;
881e8ae9b66SAlan Carew 	rte_spinlock_init(&(new_domain->config_spinlock));
882*9c20d0fdSHamza Khan 	TAILQ_INSERT_HEAD(&vm_list_head, new_domain, vms_info);
883e8ae9b66SAlan Carew 	return 0;
884e8ae9b66SAlan Carew }
885e8ae9b66SAlan Carew 
886e8ae9b66SAlan Carew int
remove_vm(const char * vm_name)887e8ae9b66SAlan Carew remove_vm(const char *vm_name)
888e8ae9b66SAlan Carew {
889e8ae9b66SAlan Carew 	struct virtual_machine_info *vm_info = find_domain_by_name(vm_name);
890e8ae9b66SAlan Carew 
891e8ae9b66SAlan Carew 	if (vm_info == NULL) {
892e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to remove VM: VM '%s' "
893e8ae9b66SAlan Carew 				"not found\n", vm_name);
894e8ae9b66SAlan Carew 		return -1;
895e8ae9b66SAlan Carew 	}
896e8ae9b66SAlan Carew 	rte_spinlock_lock(&vm_info->config_spinlock);
897e8ae9b66SAlan Carew 	if (vm_info->num_channels != 0) {
898e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to remove VM '%s', there are "
899e8ae9b66SAlan Carew 				"%"PRId8" channels still active\n",
900e8ae9b66SAlan Carew 				vm_name, vm_info->num_channels);
901e8ae9b66SAlan Carew 		rte_spinlock_unlock(&vm_info->config_spinlock);
902e8ae9b66SAlan Carew 		return -1;
903e8ae9b66SAlan Carew 	}
904*9c20d0fdSHamza Khan 	TAILQ_REMOVE(&vm_list_head, vm_info, vms_info);
905e8ae9b66SAlan Carew 	rte_spinlock_unlock(&vm_info->config_spinlock);
906e8ae9b66SAlan Carew 	rte_free(vm_info);
907e8ae9b66SAlan Carew 	return 0;
908e8ae9b66SAlan Carew }
909e8ae9b66SAlan Carew 
9101deb502eSMarcin Hajkowski int
set_query_status(char * vm_name,bool allow_query)9111deb502eSMarcin Hajkowski set_query_status(char *vm_name,
9121deb502eSMarcin Hajkowski 		bool allow_query)
9131deb502eSMarcin Hajkowski {
9141deb502eSMarcin Hajkowski 	struct virtual_machine_info *vm_info;
9151deb502eSMarcin Hajkowski 
9161deb502eSMarcin Hajkowski 	vm_info = find_domain_by_name(vm_name);
9171deb502eSMarcin Hajkowski 	if (vm_info == NULL) {
9181deb502eSMarcin Hajkowski 		RTE_LOG(ERR, CHANNEL_MANAGER, "VM '%s' not found\n", vm_name);
9191deb502eSMarcin Hajkowski 		return -1;
9201deb502eSMarcin Hajkowski 	}
9211deb502eSMarcin Hajkowski 	rte_spinlock_lock(&(vm_info->config_spinlock));
9221deb502eSMarcin Hajkowski 	vm_info->allow_query = allow_query ? 1 : 0;
9231deb502eSMarcin Hajkowski 	rte_spinlock_unlock(&(vm_info->config_spinlock));
9241deb502eSMarcin Hajkowski 	return 0;
9251deb502eSMarcin Hajkowski }
9261deb502eSMarcin Hajkowski 
927e8ae9b66SAlan Carew static void
disconnect_hypervisor(void)928e8ae9b66SAlan Carew disconnect_hypervisor(void)
929e8ae9b66SAlan Carew {
930e8ae9b66SAlan Carew 	if (global_vir_conn_ptr != NULL) {
931e8ae9b66SAlan Carew 		virConnectClose(global_vir_conn_ptr);
932e8ae9b66SAlan Carew 		global_vir_conn_ptr = NULL;
933e8ae9b66SAlan Carew 	}
934e8ae9b66SAlan Carew }
935e8ae9b66SAlan Carew 
936e8ae9b66SAlan Carew static int
connect_hypervisor(const char * path)937e8ae9b66SAlan Carew connect_hypervisor(const char *path)
938e8ae9b66SAlan Carew {
939e8ae9b66SAlan Carew 	if (global_vir_conn_ptr != NULL) {
940e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error connecting to %s, connection "
941e8ae9b66SAlan Carew 				"already established\n", path);
942e8ae9b66SAlan Carew 		return -1;
943e8ae9b66SAlan Carew 	}
944e8ae9b66SAlan Carew 	global_vir_conn_ptr = virConnectOpen(path);
945e8ae9b66SAlan Carew 	if (global_vir_conn_ptr == NULL) {
946e8ae9b66SAlan Carew 		RTE_LOG(ERR, CHANNEL_MANAGER, "Error failed to open connection to "
947e8ae9b66SAlan Carew 				"Hypervisor '%s'\n", path);
948e8ae9b66SAlan Carew 		return -1;
949e8ae9b66SAlan Carew 	}
950e8ae9b66SAlan Carew 	return 0;
951e8ae9b66SAlan Carew }
952e8ae9b66SAlan Carew int
channel_manager_init(const char * path __rte_unused)953e0207366SDavid Hunt channel_manager_init(const char *path __rte_unused)
954e8ae9b66SAlan Carew {
955f7f14fe3SYong Liu 	virNodeInfo info;
956e8ae9b66SAlan Carew 
957*9c20d0fdSHamza Khan 	TAILQ_INIT(&vm_list_head);
958e8ae9b66SAlan Carew 	if (connect_hypervisor(path) < 0) {
959e0207366SDavid Hunt 		global_n_host_cpus = 64;
960e0207366SDavid Hunt 		global_hypervisor_available = 0;
961e0207366SDavid Hunt 		RTE_LOG(INFO, CHANNEL_MANAGER, "Unable to initialize channel manager\n");
962e0207366SDavid Hunt 	} else {
963e0207366SDavid Hunt 		global_hypervisor_available = 1;
964e8ae9b66SAlan Carew 
965751227a0SDavid Hunt 		global_maplen = VIR_CPU_MAPLEN(RTE_MAX_LCORE);
966e8ae9b66SAlan Carew 
967e0207366SDavid Hunt 		global_vircpuinfo = rte_zmalloc(NULL,
968e0207366SDavid Hunt 				sizeof(*global_vircpuinfo) *
969751227a0SDavid Hunt 				RTE_MAX_LCORE, RTE_CACHE_LINE_SIZE);
970e8ae9b66SAlan Carew 		if (global_vircpuinfo == NULL) {
971e8ae9b66SAlan Carew 			RTE_LOG(ERR, CHANNEL_MANAGER, "Error allocating memory for CPU Info\n");
972e8ae9b66SAlan Carew 			goto error;
973e8ae9b66SAlan Carew 		}
974e0207366SDavid Hunt 		global_cpumaps = rte_zmalloc(NULL,
975751227a0SDavid Hunt 				RTE_MAX_LCORE * global_maplen,
976fdf20fa7SSergio Gonzalez Monroy 				RTE_CACHE_LINE_SIZE);
977e0207366SDavid Hunt 		if (global_cpumaps == NULL)
978e8ae9b66SAlan Carew 			goto error;
979e8ae9b66SAlan Carew 
980f7f14fe3SYong Liu 		if (virNodeGetInfo(global_vir_conn_ptr, &info)) {
981f7f14fe3SYong Liu 			RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to retrieve node Info\n");
982e8ae9b66SAlan Carew 			goto error;
983e8ae9b66SAlan Carew 		}
984e0207366SDavid Hunt 		global_n_host_cpus = (unsigned int)info.cpus;
985e0207366SDavid Hunt 	}
986f7f14fe3SYong Liu 
987e0207366SDavid Hunt 
988e8ae9b66SAlan Carew 
989751227a0SDavid Hunt 	if (global_n_host_cpus > RTE_MAX_LCORE) {
990e9f64db9SPablo de Lara 		RTE_LOG(WARNING, CHANNEL_MANAGER, "The number of host CPUs(%u) exceeds the "
991e9f64db9SPablo de Lara 				"maximum of %u. No cores over %u should be used.\n",
992751227a0SDavid Hunt 				global_n_host_cpus, RTE_MAX_LCORE,
993751227a0SDavid Hunt 				RTE_MAX_LCORE - 1);
994751227a0SDavid Hunt 		global_n_host_cpus = RTE_MAX_LCORE;
99567ff575eSMarvin Liu 	}
996e8ae9b66SAlan Carew 
997e8ae9b66SAlan Carew 	return 0;
998e8ae9b66SAlan Carew error:
999e0207366SDavid Hunt 	if (global_hypervisor_available)
1000e8ae9b66SAlan Carew 		disconnect_hypervisor();
1001e8ae9b66SAlan Carew 	return -1;
1002e8ae9b66SAlan Carew }
1003e8ae9b66SAlan Carew 
1004e8ae9b66SAlan Carew void
channel_manager_exit(void)1005e8ae9b66SAlan Carew channel_manager_exit(void)
1006e8ae9b66SAlan Carew {
1007e8ae9b66SAlan Carew 	unsigned i;
1008751227a0SDavid Hunt 	char mask[RTE_MAX_LCORE];
1009*9c20d0fdSHamza Khan 	struct virtual_machine_info *vm_info, *tmp;
1010e8ae9b66SAlan Carew 
1011*9c20d0fdSHamza Khan 	RTE_TAILQ_FOREACH_SAFE(vm_info, &vm_list_head, vms_info, tmp) {
1012e8ae9b66SAlan Carew 
1013e8ae9b66SAlan Carew 		rte_spinlock_lock(&(vm_info->config_spinlock));
1014e8ae9b66SAlan Carew 
1015751227a0SDavid Hunt 		memcpy(mask, (char *)vm_info->channel_mask, RTE_MAX_LCORE);
1016751227a0SDavid Hunt 		for (i = 0; i < RTE_MAX_LCORE; i++) {
1017fd73630eSDavid Hunt 			if (mask[i] != 1)
1018fd73630eSDavid Hunt 				continue;
1019fd73630eSDavid Hunt 			remove_channel_from_monitor(
1020fd73630eSDavid Hunt 					vm_info->channels[i]);
1021e8ae9b66SAlan Carew 			close(vm_info->channels[i]->fd);
1022e8ae9b66SAlan Carew 			rte_free(vm_info->channels[i]);
1023e8ae9b66SAlan Carew 		}
1024e8ae9b66SAlan Carew 		rte_spinlock_unlock(&(vm_info->config_spinlock));
1025e8ae9b66SAlan Carew 
1026*9c20d0fdSHamza Khan 		TAILQ_REMOVE(&vm_list_head, vm_info, vms_info);
1027e8ae9b66SAlan Carew 		rte_free(vm_info);
1028e8ae9b66SAlan Carew 	}
1029e8ae9b66SAlan Carew 
1030e0207366SDavid Hunt 	if (global_hypervisor_available) {
1031e0207366SDavid Hunt 		/* Only needed if hypervisor available */
1032e8ae9b66SAlan Carew 		rte_free(global_cpumaps);
1033e8ae9b66SAlan Carew 		rte_free(global_vircpuinfo);
1034e8ae9b66SAlan Carew 		disconnect_hypervisor();
1035e8ae9b66SAlan Carew 	}
1036e0207366SDavid Hunt }
1037