Blame usr/transport.c

Packit Service 646995
/*
Packit Service 646995
 * iSCSI transport
Packit Service 646995
 *
Packit Service 646995
 * Copyright (C) 2006 Mike Christie
Packit Service 646995
 * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
Packit Service 646995
 *
Packit Service 646995
 * This program is free software; you can redistribute it and/or modify
Packit Service 646995
 * it under the terms of the GNU General Public License as published
Packit Service 646995
 * by the Free Software Foundation; either version 2 of the License, or
Packit Service 646995
 * (at your option) any later version.
Packit Service 646995
 *
Packit Service 646995
 * This program is distributed in the hope that it will be useful, but
Packit Service 646995
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 646995
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Packit Service 646995
 * General Public License for more details.
Packit Service 646995
 */
Packit Service 646995
#include <stdlib.h>
Packit Service 646995
#include <string.h>
Packit Service 646995
#include <stdio.h>
Packit Service 646995
#include <unistd.h>
Packit Service 646995
#include <errno.h>
Packit Service 646995
#include <libkmod.h>
Packit Service 646995
#include <net/if.h>
Packit Service 646995
#include <sys/ioctl.h>
Packit Service 646995
#include <sys/socket.h>
Packit Service 646995
#include <sys/types.h>
Packit Service 646995
#include <sys/wait.h>
Packit Service 646995
Packit Service 646995
#include "sysdeps.h"
Packit Service 646995
#include "iscsi_err.h"
Packit Service 646995
#include "initiator.h"
Packit Service 646995
#include "transport.h"
Packit Service 646995
#include "log.h"
Packit Service 646995
#include "iscsi_util.h"
Packit Service 646995
#include "iscsi_sysfs.h"
Packit Service 646995
#include "uip_mgmt_ipc.h"
Packit Service 646995
#include "cxgbi.h"
Packit Service 646995
#include "be2iscsi.h"
Packit Service 646995
#include "iser.h"
Packit Service 646995
Packit Service 646995
struct iscsi_transport_template iscsi_tcp = {
Packit Service 646995
	.name		= "tcp",
Packit Service 646995
	.ep_connect	= iscsi_io_tcp_connect,
Packit Service 646995
	.ep_poll	= iscsi_io_tcp_poll,
Packit Service 646995
	.ep_disconnect	= iscsi_io_tcp_disconnect,
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
struct iscsi_transport_template iscsi_iser = {
Packit Service 646995
	.name		= "iser",
Packit Service 646995
	.rdma		= 1,
Packit Service 646995
	.ep_connect	= ktransport_ep_connect,
Packit Service 646995
	.ep_poll	= ktransport_ep_poll,
Packit Service 646995
	.ep_disconnect	= ktransport_ep_disconnect,
Packit Service 646995
	.create_conn	= iser_create_conn,
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
struct iscsi_transport_template cxgb3i = {
Packit Service 646995
	.name		= "cxgb3i",
Packit Service 646995
	.set_host_ip	= SET_HOST_IP_OPT,
Packit Service 646995
        .bind_ep_required = 1,
Packit Service 646995
	.ep_connect	= ktransport_ep_connect,
Packit Service 646995
	.ep_poll	= ktransport_ep_poll,
Packit Service 646995
	.ep_disconnect	= ktransport_ep_disconnect,
Packit Service 646995
	.create_conn	= cxgbi_create_conn,
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
struct iscsi_transport_template cxgb4i = {
Packit Service 646995
	.name		= "cxgb4i",
Packit Service 646995
	.set_host_ip	= SET_HOST_IP_NOT_REQ,
Packit Service 646995
        .bind_ep_required = 1,
Packit Service 646995
	.ep_connect	= ktransport_ep_connect,
Packit Service 646995
	.ep_poll	= ktransport_ep_poll,
Packit Service 646995
	.ep_disconnect	= ktransport_ep_disconnect,
Packit Service 646995
	.create_conn	= cxgbi_create_conn,
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
struct iscsi_transport_template bnx2i = {
Packit Service 646995
	.name		= "bnx2i",
Packit Service 646995
	.set_host_ip	= SET_HOST_IP_REQ,
Packit Service 646995
	.use_boot_info	= 1,
Packit Service 646995
        .bind_ep_required = 1,
Packit Service 646995
	.ep_connect	= ktransport_ep_connect,
Packit Service 646995
	.ep_poll	= ktransport_ep_poll,
Packit Service 646995
	.ep_disconnect	= ktransport_ep_disconnect,
Packit Service 646995
	.set_net_config = uip_broadcast_params,
Packit Service 646995
	.exec_ping	= uip_broadcast_ping_req,
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
struct iscsi_transport_template be2iscsi = {
Packit Service 646995
	.name		= "be2iscsi",
Packit Service 646995
        .bind_ep_required = 1,
Packit Service 646995
	.sync_vlan_settings = 1,
Packit Service 646995
	.create_conn	= be2iscsi_create_conn,
Packit Service 646995
	.ep_connect	= ktransport_ep_connect,
Packit Service 646995
	.ep_poll	= ktransport_ep_poll,
Packit Service 646995
	.ep_disconnect	= ktransport_ep_disconnect,
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
struct iscsi_transport_template qla4xxx = {
Packit Service 646995
	.name		= "qla4xxx",
Packit Service 646995
	.set_host_ip	= SET_HOST_IP_NOT_REQ,
Packit Service 646995
        .bind_ep_required = 1,
Packit Service 646995
	.ep_connect	= ktransport_ep_connect,
Packit Service 646995
	.ep_poll	= ktransport_ep_poll,
Packit Service 646995
	.ep_disconnect	= ktransport_ep_disconnect,
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
struct iscsi_transport_template ocs = {
Packit Service 646995
	.name		= "ocs",
Packit Service 646995
        .bind_ep_required = 1,
Packit Service 646995
	.ep_connect	= ktransport_ep_connect,
Packit Service 646995
	.ep_poll	= ktransport_ep_poll,
Packit Service 646995
	.ep_disconnect	= ktransport_ep_disconnect,
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
struct iscsi_transport_template qedi = {
Packit Service 646995
	.name		= "qedi",
Packit Service 646995
	.set_host_ip	= SET_HOST_IP_REQ,
Packit Service 646995
	.use_boot_info	= 1,
Packit Service 646995
	.bind_ep_required = 1,
Packit Service 646995
	.no_netdev = 1,
Packit Service 646995
	.ep_connect	= ktransport_ep_connect,
Packit Service 646995
	.ep_poll	= ktransport_ep_poll,
Packit Service 646995
	.ep_disconnect	= ktransport_ep_disconnect,
Packit Service 646995
	.set_net_config = uip_broadcast_params,
Packit Service 646995
	.exec_ping	= uip_broadcast_ping_req,
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
static struct iscsi_transport_template *iscsi_transport_templates[] = {
Packit Service 646995
	&iscsi_tcp,
Packit Service 646995
	&iscsi_iser,
Packit Service 646995
	&cxgb3i,
Packit Service 646995
	&cxgb4i,
Packit Service 646995
	&bnx2i,
Packit Service 646995
	&qla4xxx,
Packit Service 646995
	&be2iscsi,
Packit Service 646995
	&ocs,
Packit Service 646995
	&qedi,
Packit Service 646995
	NULL
Packit Service 646995
};
Packit Service 646995
Packit Service 646995
int transport_probe_for_offload(void)
Packit Service 646995
{
Packit Service 646995
	struct if_nameindex *ifni;
Packit Service 646995
	char transport_name[ISCSI_TRANSPORT_NAME_MAXLEN];
Packit Service 646995
	int i, sockfd;
Packit Service 646995
	struct ifreq if_hwaddr;
Packit Service 646995
Packit Service 646995
	ifni = if_nameindex();
Packit Service 646995
	if (!ifni) {
Packit Service 646995
		log_error("Could not search for transport modules: %s",
Packit Service 646995
			  strerror(errno));
Packit Service 646995
		return ISCSI_ERR_TRANS_NOT_FOUND;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
Packit Service 646995
	if (sockfd < 0) {
Packit Service 646995
		log_error("Could not open socket for ioctl: %s",
Packit Service 646995
			  strerror(errno));
Packit Service 646995
		goto free_ifni;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	for (i = 0; ifni[i].if_index && ifni[i].if_name; i++) {
Packit Service 646995
		struct if_nameindex *n = &ifni[i];
Packit Service 646995
Packit Service 646995
		log_debug(6, "kmod probe found %s", n->if_name);
Packit Service 646995
Packit Service 646995
		strlcpy(if_hwaddr.ifr_name, n->if_name, IFNAMSIZ);
Packit Service 646995
		if (ioctl(sockfd, SIOCGIFHWADDR, &if_hwaddr) < 0)
Packit Service 646995
			continue;
Packit Service 646995
Packit Service 646995
		/* check for ARPHRD_ETHER (ethernet) */
Packit Service 646995
		if (if_hwaddr.ifr_hwaddr.sa_family != 1)
Packit Service 646995
			continue;
Packit Service 646995
Packit Service 646995
		if (net_get_transport_name_from_netdev(n->if_name,
Packit Service 646995
						       transport_name))
Packit Service 646995
			continue;
Packit Service 646995
Packit Service 646995
		transport_load_kmod(transport_name);
Packit Service 646995
	}
Packit Service 646995
	close(sockfd);
Packit Service 646995
Packit Service 646995
free_ifni:
Packit Service 646995
	if_freenameindex(ifni);
Packit Service 646995
	return 0;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
/*
Packit Service 646995
 * Most distros still do not have wide libkmod use, so
Packit Service 646995
 * use modprobe for now
Packit Service 646995
 */
Packit Service 646995
int transport_load_kmod(char *transport_name)
Packit Service 646995
{
Packit Service 646995
	struct kmod_ctx *ctx;
Packit Service 646995
	struct kmod_module *mod;
Packit Service 646995
	int rc;
Packit Service 646995
Packit Service 646995
	ctx = kmod_new(NULL, NULL);
Packit Service 646995
	if (!ctx) {
Packit Service 646995
		log_error("Could not load transport module %s. Out of "
Packit Service 646995
			  "memory.", transport_name);
Packit Service 646995
		return ISCSI_ERR_NOMEM;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	kmod_load_resources(ctx);
Packit Service 646995
Packit Service 646995
	/*
Packit Service 646995
	 * dumb dumb dumb - named iscsi_tcp and ib_iser differently from
Packit Service 646995
	 * transport name
Packit Service 646995
	 */
Packit Service 646995
	if (!strcmp(transport_name, "tcp"))
Packit Service 646995
		rc = kmod_module_new_from_name(ctx, "iscsi_tcp", &mod);
Packit Service 646995
	else if (!strcmp(transport_name, "iser"))
Packit Service 646995
		rc = kmod_module_new_from_name(ctx, "ib_iser", &mod);
Packit Service 646995
	else
Packit Service 646995
		rc = kmod_module_new_from_name(ctx, transport_name, &mod);
Packit Service 646995
	if (rc) {
Packit Service 646995
		log_error("Failed to load module %s.", transport_name);
Packit Service 646995
		rc = ISCSI_ERR_TRANS_NOT_FOUND;
Packit Service 646995
		goto unref_mod;
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	rc = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST,
Packit Service 646995
					     NULL, NULL, NULL, NULL);
Packit Service 646995
	if (rc) {
Packit Service 646995
		log_error("Could not insert module %s. Kmod error %d",
Packit Service 646995
			  transport_name, rc);
Packit Service 646995
		rc = ISCSI_ERR_TRANS_NOT_FOUND;
Packit Service 646995
	}
Packit Service 646995
	kmod_module_unref(mod);
Packit Service 646995
Packit Service 646995
unref_mod:
Packit Service 646995
	kmod_unref(ctx);
Packit Service 646995
	return rc;
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int set_transport_template(struct iscsi_transport *t)
Packit Service 646995
{
Packit Service 646995
	struct iscsi_transport_template *tmpl;
Packit Service 646995
	int j;
Packit Service 646995
Packit Service 646995
	for (j = 0; iscsi_transport_templates[j] != NULL; j++) {
Packit Service 646995
		tmpl = iscsi_transport_templates[j];
Packit Service 646995
Packit Service 646995
		if (!strcmp(tmpl->name, t->name)) {
Packit Service 646995
			t->template = tmpl;
Packit Service 646995
			log_debug(3, "Matched transport %s", t->name);
Packit Service 646995
			return 0;
Packit Service 646995
		}
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	log_error("Could not find template for %s. An updated iscsiadm "
Packit Service 646995
		  "is probably needed.", t->name);
Packit Service 646995
	return ENOSYS;
Packit Service 646995
}