Blame plugin/cpseudo.md

Packit 534379
### OPAE API Data Structures ###
Packit 534379
`fpga_token` and `fpga_handle` are opaque types. This allows them to be
Packit 534379
easily wrapped at any level of the plugin stack.
Packit 534379
Packit 534379
```c
Packit 534379
#ifndef __OPAE_TYPES_H__
Packit 534379
#define __OPAE_TYPES_H__
Packit 534379
Packit 534379
typedef void *fpga_token;
Packit 534379
typedef void *fpga_handle;
Packit 534379
Packit 534379
#endif
Packit 534379
```
Packit 534379
Packit 534379
### Plugin Manager ###
Packit 534379
The plugin manager tracks each loaded plugin in its list of OPAE
Packit 534379
API adpater tables.
Packit 534379
Packit 534379
```c
Packit 534379
#ifndef __OPAE_PLUGIN_MGR_H__
Packit 534379
#define __OPAE_PLUGIN_MGR_H__
Packit 534379
Packit 534379
int opae_plugin_mgr_initialize(const char *cfg_file)
Packit 534379
{
Packit 534379
	opae_plugin_mgr_parse_config(json_open(cfg_file));
Packit 534379
}
Packit 534379
Packit 534379
int opae_plugin_mgr_parse_config(json_object *jobj)
Packit 534379
{
Packit 534379
	(parse jobj to plugins section of config file)
Packit 534379
Packit 534379
	return opae_plugin_ldr_load_plugins(jobj);
Packit 534379
}
Packit 534379
Packit 534379
int opae_plugin_mgr_register_adapter(opae_api_adapter_table *adapter)
Packit 534379
{
Packit 534379
	(add adapter to plugin mgr's adapter table list)
Packit 534379
}
Packit 534379
Packit 534379
#endif
Packit 534379
```
Packit 534379
Packit 534379
### Plugin Loader ###
Packit 534379
The plugin loader provides the basic facilities for locating and
Packit 534379
loading OPAE plugins, given a description of the desired plugins
Packit 534379
in a formatted configuration file (JSON). The loader registers
Packit 534379
each loaded plugin with the plugin manager.
Packit 534379
Packit 534379
Packit 534379
```c
Packit 534379
#ifndef __OPAE_PLUGIN_LDR_H__
Packit 534379
#define __OPAE_PLUGIN_LDR_H__
Packit 534379
Packit 534379
typedef struct _opae_plugin {
Packit 534379
	char *path;     // location on file system
Packit 534379
	void *dlhandle; // handle to the loaded library instance
Packit 534379
} opae_plugin;
Packit 534379
Packit 534379
typedef struct _opae_api_adapter_table {
Packit 534379
	opae_plugin plugin;
Packit 534379
Packit 534379
	fpga_result (*fpgaEnumerate)(const fpga_properties *filters,
Packit 534379
				     uint32_t num_filters,
Packit 534379
				     fpga_token *tokens,
Packit 534379
				     uint32_t max_tokens,
Packit 534379
				     uint32_t *num_matches);
Packit 534379
Packit 534379
	fpga_result (*fpgaOpen)(fpga_token token,
Packit 534379
				fpga_handle *handle,
Packit 534379
				int flags);
Packit 534379
Packit 534379
        ...
Packit 534379
Packit 534379
Packit 534379
	// configuration functions
Packit 534379
	int (*initialize)(void);
Packit 534379
	int (*finalize)(void);
Packit 534379
Packit 534379
	// first-level query
Packit 534379
	bool (*supports_device(const char *device_type);
Packit 534379
	bool (*supports_host)(const char *hostname);
Packit 534379
} opae_api_adapter_table;
Packit 534379
Packit 534379
typedef struct _opae_wrapped_token {
Packit 534379
	fpga_token opae_token;
Packit 534379
	opae_api_adapter_table *adapter_table;
Packit 534379
} opae_wrapped_token;
Packit 534379
Packit 534379
typedef struct _opae_wrapped_handle {
Packit 534379
	opae_wrapped_token *wtok;
Packit 534379
	fpga_handle opae_handle;
Packit 534379
	opae_api_adapter_table *adapter_table;
Packit 534379
} opae_wrapped_handle;
Packit 534379
Packit 534379
int opae_plugin_ldr_load_plugins(json_object *jobj)
Packit 534379
{
Packit 534379
	opae_plugin pl;
Packit 534379
	opae_api_adapter_table *adapter;
Packit 534379
Packit 534379
	for (each plugin pl described in jobj) {
Packit 534379
Packit 534379
		jobj_for_pl = (plugin section of jobj describing
Packit 534379
                               the current plugin, pl)
Packit 534379
Packit 534379
		(open pl)
Packit 534379
Packit 534379
		(load function pointer for 'opae_plugin_configure')
Packit 534379
Packit 534379
		(allocate and init adapter to 0)
Packit 534379
Packit 534379
		if (!opae_plugin_configure(adapter, serialize(jobj_for_pl))) {
Packit 534379
Packit 534379
			if (adapter->initialize) {
Packit 534379
				if (adapter->initialize()) {
Packit 534379
					(fail the current plugin)
Packit 534379
					continue;
Packit 534379
				}
Packit 534379
			}
Packit 534379
Packit 534379
			opae_plugin_mgr_register_adapter(adapter);
Packit 534379
Packit 534379
		}
Packit 534379
Packit 534379
	}
Packit 534379
}
Packit 534379
Packit 534379
#endif
Packit 534379
```
Packit 534379
Packit 534379
### OPAE Stack ###
Packit 534379
The OPAE API consists of the plugin manager, the plugin loader,
Packit 534379
and 'shell' implementations of the superset of library calls.
Packit 534379
Each 'shell' library call uses the adapter table(s) to call through
Packit 534379
to the appropriate plugin implementation.
Packit 534379
Packit 534379
```c
Packit 534379
#ifndef __OPAE_API_H__
Packit 534379
#define __OPAE_API_H__
Packit 534379
Packit 534379
fpga_result fpgaEnumerate(const fpga_properties *filters,
Packit 534379
			  uint32_t num_filters,
Packit 534379
			  fpga_token *tokens,
Packit 534379
			  uint32_t max_tokens,
Packit 534379
			  uint32_t *num_matches)
Packit 534379
{
Packit 534379
	*num_matches = 0;
Packit 534379
	fpga_token *pl_tokens = NULL;
Packit 534379
Packit 534379
	if (tokens) {
Packit 534379
		pl_tokens = (allocate local tokens array)
Packit 534379
	}
Packit 534379
Packit 534379
	for (each adapter in plugin_mgr adapter list) {
Packit 534379
		uint32_t pl_matches = 0;
Packit 534379
Packit 534379
		if (adapter->supports_device) {
Packit 534379
			(use adapter->supports_device to accept/reject
Packit 534379
			adapter, based on filters)
Packit 534379
Packit 534379
			if (device not supported)
Packit 534379
				continue;
Packit 534379
		}
Packit 534379
Packit 534379
		if (adapter->supports_host) {
Packit 534379
			(use adapter->supports_host to accept/reject
Packit 534379
			adapter, based on filters)
Packit 534379
Packit 534379
			if (host not supported)
Packit 534379
				continue;
Packit 534379
		}
Packit 534379
Packit 534379
		adapter->fpgaEnumerate(filters, num_filters,
Packit 534379
					pl_tokens, max_tokens - *num_matches,
Packit 534379
					&pl_matches);
Packit 534379
Packit 534379
		*num_matches += pl_matches;
Packit 534379
Packit 534379
		if (!pl_tokens) { // request for num_matches only
Packit 534379
			continue;
Packit 534379
		}
Packit 534379
Packit 534379
		for (each fpga_token tok in pl_tokens) {
Packit 534379
Packit 534379
			opae_wrapped_token *wtok = alloc_wrapped_token();
Packit 534379
Packit 534379
			wtok->opae_token = tok;
Packit 534379
			wtok->adapter_table = adapter; (map wtok to plugin)
Packit 534379
Packit 534379
			tokens[i] = wtok;
Packit 534379
		}
Packit 534379
Packit 534379
		if (*num_matches == max_tokens) {
Packit 534379
			break;
Packit 534379
		}
Packit 534379
	}
Packit 534379
	
Packit 534379
	free(pl_tokens);
Packit 534379
}
Packit 534379
Packit 534379
fpga_result fpgaOpen(fpga_token token,
Packit 534379
		     fpga_handle *handle,
Packit 534379
		     int flags)
Packit 534379
{
Packit 534379
	fpga_handle h;
Packit 534379
	opae_wrapped_token *wtok = (opae_wrapped_token *) token;
Packit 534379
Packit 534379
	wtok->adapter_table->fpgaOpen(wtok->opae_token, &h, flags);
Packit 534379
Packit 534379
	opae_wrapped_handle *whandle = alloc_wrapped_handle();
Packit 534379
Packit 534379
	whandle->wtok = wtok;
Packit 534379
	whandle->opae_handle = h;
Packit 534379
	whandle->adapter_table = wtok->adapter_table;
Packit 534379
	
Packit 534379
	*handle = whandle;
Packit 534379
}
Packit 534379
Packit 534379
#endif
Packit 534379
```
Packit 534379
### Proxy Plugins ###
Packit 534379
A TCP/IP OPAE plugin uses network sockets to implement the control
Packit 534379
protocol exchange, but may utilize facilities such as RDMA for data
Packit 534379
exchange.
Packit 534379
Packit 534379
```c
Packit 534379
#ifndef __MY_TCP_IP_PLUGIN_H__
Packit 534379
#define __MY_TCP_IP_PLUGIN_H__
Packit 534379
Packit 534379
typedef struct _my_tcp_ip_plugin_host_list {
Packit 534379
	char *hostname;
Packit 534379
	int port;
Packit 534379
	struct addrinfo *addr_info;
Packit 534379
	int conn_socket;
Packit 534379
	struct _my_tcp_ip_plugin_host_list *next;
Packit 534379
} my_tcp_ip_plugin_host_list;
Packit 534379
Packit 534379
static my_tcp_ip_plugin_host_list *host_list = NULL;
Packit 534379
Packit 534379
typedef struct _my_tcp_ip_enumerate_response {
Packit 534379
	...
Packit 534379
} my_tcp_ip_enumerate_response;
Packit 534379
Packit 534379
typedef struct _my_tcp_ip_plugin_token {
Packit 534379
	my_tcp_ip_enumerate_response *response_token;
Packit 534379
	my_tcp_ip_plugin_host_list *host;
Packit 534379
} my_tcp_ip_plugin_token;
Packit 534379
Packit 534379
typedef struct _my_tcp_ip_open_response {
Packit 534379
	...
Packit 534379
} my_tcp_ip_open_response;
Packit 534379
Packit 534379
typedef struct _my_tcp_ip_plugin_handle {
Packit 534379
	my_tcp_ip_plugin_token *token;
Packit 534379
	my_tcp_ip_plugin_host_list *host;
Packit 534379
	my_tcp_ip_open_response *response_handle;
Packit 534379
} my_tcp_ip_plugin_handle;
Packit 534379
Packit 534379
int opae_plugin_configure(opae_api_adapter_table *table, const char *jsonConfig)
Packit 534379
{
Packit 534379
	json_object *jobj;
Packit 534379
Packit 534379
	jobj = deserialize(jsonConfig);
Packit 534379
Packit 534379
	for (each host in jobj) {
Packit 534379
Packit 534379
		add_list(&host_list, alloc_host_entry(host.name, host.port));
Packit 534379
Packit 534379
	}
Packit 534379
Packit 534379
	for (each OPAE api in this plugin) {
Packit 534379
Packit 534379
		(add api to table)
Packit 534379
Packit 534379
	}
Packit 534379
Packit 534379
	table->initialize = my_tcp_ip_plugin_initialize;
Packit 534379
	table->finalize = my_tcp_ip_plugin_finalize;
Packit 534379
Packit 534379
	table->supports_host = my_tcp_ip_plugin_supports_host;
Packit 534379
}
Packit 534379
Packit 534379
int my_tcp_ip_plugin_initialize(void)
Packit 534379
{
Packit 534379
	for (each host in host_list) {
Packit 534379
Packit 534379
		connect_host(host);
Packit 534379
Packit 534379
	}
Packit 534379
}
Packit 534379
Packit 534379
int my_tcp_ip_plugin_finalize(void)
Packit 534379
{
Packit 534379
	for (each host in host_list) {
Packit 534379
Packit 534379
		disconnect_host(host);
Packit 534379
		free(host);
Packit 534379
	
Packit 534379
	}
Packit 534379
}
Packit 534379
Packit 534379
bool my_tcp_ip_plugin_supports_host(const char *hostname)
Packit 534379
{
Packit 534379
	for (each host in host_list) {
Packit 534379
Packit 534379
		if (this plugin supports hostname)
Packit 534379
			return true;
Packit 534379
Packit 534379
	}
Packit 534379
	return false;
Packit 534379
}
Packit 534379
Packit 534379
fpga_result fpgaEnumerate(const fpga_properties *filters,
Packit 534379
			  uint32_t num_filters,
Packit 534379
			  fpga_token *tokens,
Packit 534379
			  uint32_t max_tokens,
Packit 534379
			  uint32_t *num_matches)
Packit 534379
{
Packit 534379
	my_tcp_ip_enumerate_response *response_tokens;
Packit 534379
	uint32_t num_responses = 0;
Packit 534379
Packit 534379
	for (each host in host_list) {
Packit 534379
Packit 534379
		send_enumerate_request(host, filters, ...);
Packit 534379
Packit 534379
		recv_enumerate_response(&response_tokens, &num_responses);
Packit 534379
Packit 534379
		for (each resp in response_tokens) {
Packit 534379
Packit 534379
			my_tcp_ip_plugin_token *tok = my_tcp_ip_alloc_token();
Packit 534379
Packit 534379
			tok->response_token = resp;
Packit 534379
			tok->host = host;
Packit 534379
Packit 534379
			tokens[i] = tok;
Packit 534379
		}
Packit 534379
	}
Packit 534379
}
Packit 534379
Packit 534379
fpga_result fpgaOpen(fpga_token token,
Packit 534379
		     fpga_handle *handle,
Packit 534379
		     int flags)
Packit 534379
{
Packit 534379
	my_tcp_ip_plugin_token *plugin_token = (my_tcp_ip_plugin_token *) token;
Packit 534379
	my_tcp_ip_open_response *open_response;
Packit 534379
Packit 534379
	send_open_request(plugin_token->host, plugin_token->response_token, flags);
Packit 534379
Packit 534379
	open_response = recv_open_response(plugin_token->host);
Packit 534379
Packit 534379
	my_tcp_ip_plugin_handle *plugin_handle = my_tcp_ip_alloc_handle();
Packit 534379
Packit 534379
	plugin_handle->token = plugin_token;
Packit 534379
	plugin_handle->host = plugin_token->host;
Packit 534379
	plugin_handle->response_handle = open_response;
Packit 534379
Packit 534379
	*handle = plugin_handle;
Packit 534379
}
Packit 534379
Packit 534379
#endif
Packit 534379
```
Packit 534379
Packit 534379
An RDMA OPAE plugin uses RDMA for both control protocol and
Packit 534379
data exchange.
Packit 534379
Packit 534379
```c
Packit 534379
#ifndef __MY_RDMA_PLUGIN_H__
Packit 534379
#define __MY_RDMA_PLUGIN_H__
Packit 534379
Packit 534379
typedef struct _my_rdma_plugin_host_list {
Packit 534379
	enum rdma_conn_type conn_type;
Packit 534379
Packit 534379
	struct ibv_context *ctx;
Packit 534379
	struct ibv_pd *pd;
Packit 534379
Packit 534379
	...
Packit 534379
Packit 534379
	struct _my_rdma_plugin_host_list *next;
Packit 534379
} my_rdma_plugin_host_list;
Packit 534379
Packit 534379
static my_rdma_plugin_host_list *host_list = NULL;
Packit 534379
Packit 534379
typedef struct _my_rdma_enumerate_response {
Packit 534379
	...
Packit 534379
} my_rdma_enumerate_response;
Packit 534379
Packit 534379
typedef struct _my_rdma_plugin_token {
Packit 534379
	my_rdma_enumerate_response *response_token;
Packit 534379
	my_rdma_plugin_host_list *host;
Packit 534379
} my_rdma_plugin_token;
Packit 534379
Packit 534379
typedef struct _my_rdma_open_response {
Packit 534379
	...
Packit 534379
} my_rdma_open_response;
Packit 534379
Packit 534379
typedef struct _my_rdma_plugin_handle {
Packit 534379
	my_rdma_plugin_token *token;
Packit 534379
	my_rdma_plugin_host_list *host;
Packit 534379
	my_rdma_open_response *response_handle;
Packit 534379
} my_rdma_plugin_handle;
Packit 534379
Packit 534379
int opae_plugin_configure(opae_api_adapter_table *table, const char *jsonConfig)
Packit 534379
{
Packit 534379
	json_object *jobj;
Packit 534379
Packit 534379
	jobj = deserialize(jsonConfig);
Packit 534379
Packit 534379
	for (each host in jobj) {
Packit 534379
Packit 534379
		add_list(&host_list, alloc_host_entry(host.name, host.port));
Packit 534379
Packit 534379
	}
Packit 534379
Packit 534379
	for (each OPAE api in this plugin) {
Packit 534379
Packit 534379
		(add api to table)
Packit 534379
Packit 534379
	}
Packit 534379
Packit 534379
	table->initialize = my_rdma_plugin_initialize;
Packit 534379
	table->finalize = my_rdma_plugin_finalize;
Packit 534379
Packit 534379
	table->supports_host = my_rdma_plugin_supports_host;
Packit 534379
}
Packit 534379
Packit 534379
int my_rdma_plugin_initialize(void)
Packit 534379
{
Packit 534379
	for (each host in host_list) {
Packit 534379
Packit 534379
		init_host_rdma(host);
Packit 534379
Packit 534379
	}
Packit 534379
}
Packit 534379
Packit 534379
int my_rdma_plugin_finalize(void)
Packit 534379
{
Packit 534379
	for (each host in host_list) {
Packit 534379
Packit 534379
		deinit_host_rdma(host);
Packit 534379
		free(host);
Packit 534379
	
Packit 534379
	}
Packit 534379
}
Packit 534379
Packit 534379
bool my_rdma_plugin_supports_host(const char *hostname)
Packit 534379
{
Packit 534379
	for (each host in host_list) {
Packit 534379
Packit 534379
		if (this plugin supports hostname)
Packit 534379
			return true;
Packit 534379
Packit 534379
	}
Packit 534379
	return false;
Packit 534379
}
Packit 534379
Packit 534379
fpga_result fpgaEnumerate(const fpga_properties *filters,
Packit 534379
			  uint32_t num_filters,
Packit 534379
			  fpga_token *tokens,
Packit 534379
			  uint32_t max_tokens,
Packit 534379
			  uint32_t *num_matches)
Packit 534379
{
Packit 534379
	my_rdma_enumerate_response *response_tokens;
Packit 534379
	uint32_t num_responses = 0;
Packit 534379
Packit 534379
	for (each host in host_list) {
Packit 534379
Packit 534379
		send_rdma_enumerate_request(host, filters, ...);
Packit 534379
Packit 534379
		recv_rdma_enumerate_response(&response_tokens, &num_responses);
Packit 534379
Packit 534379
		for (each resp in response_tokens) {
Packit 534379
Packit 534379
			my_rdma_plugin_token *tok = my_rdma_alloc_token();
Packit 534379
Packit 534379
			tok->response_token = resp;
Packit 534379
			tok->host = host;
Packit 534379
Packit 534379
			tokens[i] = tok;
Packit 534379
		}
Packit 534379
	}
Packit 534379
}
Packit 534379
Packit 534379
fpga_result fpgaOpen(fpga_token token,
Packit 534379
		     fpga_handle *handle,
Packit 534379
		     int flags)
Packit 534379
{
Packit 534379
	my_rdma_plugin_token *plugin_token = (my_rdma_plugin_token *) token;
Packit 534379
	my_rdma_open_response *open_response;
Packit 534379
Packit 534379
	send_rdma_open_request(plugin_token->host, plugin_token->response_token);
Packit 534379
Packit 534379
	open_response = recv_rdma_open_response(plugin_token->host);
Packit 534379
Packit 534379
	my_rdma_plugin_handle *plugin_handle = my_rdma_alloc_handle();
Packit 534379
Packit 534379
	plugin_handle->token = plugin_token;
Packit 534379
	plugin_handle->host = plugin_token->host;
Packit 534379
	plugin_handle->response_handle = open_response;
Packit 534379
Packit 534379
	*handle = plugin_handle;
Packit 534379
}
Packit 534379
Packit 534379
#endif
Packit 534379
```
Packit 534379
Packit 534379
The 'local' OPAE plugin communicates with the kernel device driver
Packit 534379
via memory-mapped IO and sysfs attributes.
Packit 534379
Packit 534379
```c
Packit 534379
#ifndef __MY_LOCAL_PLUGIN_H__
Packit 534379
#define __MY_LOCAL_PLUGIN_H__
Packit 534379
Packit 534379
int opae_plugin_configure(opae_api_adapter_table *table, const char *jsonConfig)
Packit 534379
{
Packit 534379
	json_object *jobj;
Packit 534379
Packit 534379
	jobj = deserialize(jsonConfig);
Packit 534379
Packit 534379
	(configure the plugin, based on jobj)
Packit 534379
Packit 534379
	for (each OPAE api in this plugin) {
Packit 534379
Packit 534379
		(add api to table)
Packit 534379
Packit 534379
	}
Packit 534379
Packit 534379
	table->supports_device = my_local_plugin_supports_device;
Packit 534379
}
Packit 534379
Packit 534379
bool my_local_plugin_supports_device(const char *device_type)
Packit 534379
{
Packit 534379
	if (this plugin supports device_type)
Packit 534379
		return true;
Packit 534379
Packit 534379
	return false;
Packit 534379
}
Packit 534379
Packit 534379
fpga_result fpgaEnumerate(const fpga_properties *filters,
Packit 534379
			  uint32_t num_filters,
Packit 534379
			  fpga_token *tokens,
Packit 534379
			  uint32_t max_tokens,
Packit 534379
			  uint32_t *num_matches)
Packit 534379
{
Packit 534379
	(traditional enumerate searches local sysfs)
Packit 534379
}
Packit 534379
Packit 534379
fpga_result fpgaOpen(fpga_token token,
Packit 534379
		     fpga_handle *handle,
Packit 534379
		     int flags)
Packit 534379
{
Packit 534379
	struct _fpga_token *_tok = (struct _fpga_token *) token;
Packit 534379
	struct _fpga_handle *_handle;
Packit 534379
Packit 534379
	(traditional open uses character device node from _tok)
Packit 534379
Packit 534379
	_handle = malloc(sizeof(struct _fpga_handle));
Packit 534379
Packit 534379
	...
Packit 534379
Packit 534379
	_handle->fddev = open(_tok.dev_path ...);
Packit 534379
Packit 534379
	...
Packit 534379
Packit 534379
	*handle = _handle;
Packit 534379
}
Packit 534379
Packit 534379
#endif
Packit 534379
```
Packit 534379
Packit 534379
Other plugins:
Packit 534379
* AFU Simulation Environment (ASE)
Packit 534379
* virtio-vsock (pool of accelerators assigned to VM's)
Packit 534379
* RSD