[Open-FCoE] [PATCH v1 4/4]fcoe-utils: Add socket client interface in fcoeadm

Lucy Liu lucy.liu at intel.com
Thu Dec 17 23:49:30 UTC 2009


Add socket client interface into fcoeadmin. In fcoeadm.c/h, remove the code
of access sysfs files, create socket to connect to fcoemon, send request,
parse and print out the response;

Signed-off-by: Lucy Liu <lucy.liu at intel.com>

---

 fcoeadm.c |  301 +++++++++++++++++++++++++++++++++----------------------------
 fcoeadm.h |   16 +++
 2 files changed, 178 insertions(+), 139 deletions(-)

diff --git a/fcoeadm.c b/fcoeadm.c
index c766921..6b7f188 100644
--- a/fcoeadm.c
+++ b/fcoeadm.c
@@ -17,25 +17,17 @@
  * Maintained at www.Open-FCoE.org
  */
 
-#include <stdio.h>
-#include <stdlib.h>
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
 #include <libgen.h>
-#include <errno.h>
-#include <getopt.h>
-#include <dirent.h>
 #include "fcoeadm.h"
+#include "fcoe_clif.h"
 
 static char *fcoeadm_version =						\
-	"fcoeadm v1.0.7\n Copyright (c) 2009, Intel Corporation.\n";
+	"fcoeadm v1.0.8\n Copyright (c) 2009, Intel Corporation.\n";
 
-#define SYSFS_MOUNT	"/sys"
-#define SYSFS_NET	SYSFS_MOUNT "/class/net"
-#define SYSFS_FCHOST	SYSFS_MOUNT "/class/fc_host"
-#define SYSFS_FCOE	SYSFS_MOUNT "/module/fcoe/parameters"
-#define FCOE_CREATE	SYSFS_FCOE "/create"
-#define FCOE_DESTROY	SYSFS_FCOE "/destroy"
-
-#define FCHOSTBUFLEN		64
+#define CMD_RESPONSE_TIMEOUT 5
 
 static struct option fcoeadm_opts[] = {
 	{"create", 1, 0, 'c'},
@@ -53,6 +45,8 @@ static struct option fcoeadm_opts[] = {
 struct opt_info _opt_info, *opt_info = &_opt_info;
 char progname[20];
 
+struct clif *clif_conn;
+
 static void fcoeadm_help(void)
 {
 	printf("%s\n", fcoeadm_version);
@@ -121,131 +115,187 @@ static int fcoeadm_check(char *ifname)
 	return 0;
 }
 
-/*
- * TODO - for now, this just writes to path
- */
-static int fcoeadm_action(char *path, char *s)
+static int fcoeadm_clif_request(const struct clif_data *cmd, size_t cmd_len,
+					char *reply, size_t *reply_len)
+{
+	struct timeval tv;
+	int ret;
+	fd_set rfds;
+
+	if (send(clif_conn->s, cmd, cmd_len, 0) < 0)
+		return -1;
+
+	for (;;) {
+		tv.tv_sec = CMD_RESPONSE_TIMEOUT;
+		tv.tv_usec = 0;
+		FD_ZERO(&rfds);
+		FD_SET(clif_conn->s, &rfds);
+		ret = select(clif_conn->s + 1, &rfds, NULL, NULL, &tv);
+		if (FD_ISSET(clif_conn->s, &rfds)) {
+			ret = recv(clif_conn->s, reply, *reply_len, 0);
+			if (ret < 0) {
+				fprintf(stderr, "less then zero\n");
+				return ret;
+			}
+			*reply_len = ret;
+			break;
+		} else {
+			fprintf(stderr, "timeout\n");
+			return -2;
+		}
+	}
+
+	return 0;
+}
+
+static int fcoeadm_request(int cmd, char *s)
 {
-	FILE *fp = NULL;
+	struct clif_data *data = NULL;
+	char rbuf[MAX_MSGBUF];
+	size_t len;
+	int ret;
 
-	if (!path)
+	if (clif_conn == NULL) {
+		printf("Not connected to fcoemon.\n");
 		return -EINVAL;
+	}
 
-	if (!s)
+	data = (struct clif_data *)malloc(sizeof(struct clif_data));
+	if (data == NULL)
 		return -EINVAL;
 
-	fp = fopen(path, "w");
-	if (!fp) {
-		fprintf(stderr,
-			"%s: Failed to open %s\n", progname, path);
-		return -ENOENT;
+	memset(data, 0, sizeof(data));
+	data->cmd = cmd;
+	strcpy(data->ifname, s);
+
+	len = sizeof(rbuf)-1;
+
+	ret = fcoeadm_clif_request(data, sizeof(struct clif_data), rbuf, &len);
+	if (ret == -2) {
+		printf("%d command timed out.\n", cmd);
+		goto fail;
+	} else if (ret < 0) {
+		printf("%d command failed.\n", cmd);
+		goto fail;
 	}
-	if (EOF == fputs(s, fp))
-		fprintf(stderr,
-			"%s: Failed to write %s to %s\n", progname, s, path);
 
-	fclose(fp);
+	rbuf[len] = '\0';
+	free(data);
+	return ret;
 
-	return 0;
+fail:
+	free(data);
+	return -EINVAL;
 }
 
-static char *fcoeadm_read(const char *path)
+static void fcoeadm_close_cli(void)
 {
-	FILE *fp;
-	char *buf;
-	int size = 512;
-
-	if (!path)
-		return NULL;
-
-	buf = malloc(size);
-	if (!buf)
-		return NULL;
-	memset(buf, 0, size);
-
-	fp = fopen(path, "r");
-	if (fp) {
-		if (fgets(buf, size, fp)) {
-			fclose(fp);
-			return buf;
-		}
-	}
-	fclose(fp);
-	free(buf);
-	return NULL;
+	if (clif_conn == NULL)
+		return;
+
+	unlink(clif_conn->local.sun_path);
+	close(clif_conn->s);
+	free(clif_conn);
+	clif_conn = NULL;
 }
 
-static int fcoeadm_check_fchost(const char *ifname, const char *dname)
+/*
+ * Create fcoeadm client interface
+ */
+static struct clif *fcoeadm_open_cli(const char *ifname)
 {
-	char *buf;
-	char path[512];
-
-	if (!ifname)
-		return -EINVAL;
-
-	if (!dname)
-		return -EINVAL;
+	char *fcmon_file = NULL;
+	int flen;
+	static int counter;
+
+	flen = strlen(FCM_SRV_DIR) + strlen(ifname) + 2;
+	fcmon_file = malloc(flen);
+	if (fcmon_file == NULL)
+		goto fail;
+	snprintf(fcmon_file, flen, "%s/%s", FCM_SRV_DIR, ifname);
+
+	clif_conn = malloc(sizeof(*clif_conn));
+	if (clif_conn == NULL)
+		goto fail;
+	memset(clif_conn, 0, sizeof(*clif_conn));
+
+	clif_conn->s = socket(PF_UNIX, SOCK_DGRAM, 0);
+	if (clif_conn->s < 0)
+		goto fail;
+
+	clif_conn->local.sun_family = AF_UNIX;
+	snprintf(clif_conn->local.sun_path, sizeof(clif_conn->local.sun_path),
+		    "/tmp/fcadm_clif_%d-%d", getpid(), counter++);
+	if (bind(clif_conn->s, (struct sockaddr *) &clif_conn->local,
+		    sizeof(clif_conn->local)) < 0) {
+		close(clif_conn->s);
+		goto fail;
+	}
 
-	if (dname[0] == '.')
-		return -EINVAL;
+	clif_conn->dest.sun_family = AF_UNIX;
+	snprintf(clif_conn->dest.sun_path, sizeof(clif_conn->dest.sun_path),
+			"%s", fcmon_file);
+	if (connect(clif_conn->s, (struct sockaddr *) &clif_conn->dest,
+		    sizeof(clif_conn->dest)) < 0) {
+		close(clif_conn->s);
+		unlink(clif_conn->local.sun_path);
+		goto fail;
+	}
 
-	sprintf(path, "%s/%s/symbolic_name", SYSFS_FCHOST, dname);
-	buf = fcoeadm_read(path);
-	if (!buf)
-		return -EINVAL;
+	free(fcmon_file);
+	return clif_conn;
 
-	if (!strstr(buf, ifname)) {
-		free(buf);
-		return -EINVAL;
-	}
-	free(buf);
-	return 0;
+fail:
+	free(fcmon_file);
+	free(clif_conn);
+	return NULL;
 }
 
-static int fcoeadm_find_fchost(char *ifname, char *fchost, int len)
+/*
+ * Send request to fcoemon
+ */
+static int fcoeadm_action(int cmd, char *device_name)
 {
-	int n, dname_len;
-	int found = 0;
-	struct dirent **namelist;
+	char *clif_ifname = NULL;
+	int ret = 0;
 
-	if (!ifname)
+	if (!device_name)
 		return -EINVAL;
 
-	if ((!fchost) || (len <= 0))
-		return -EINVAL;
-
-	memset(fchost, 0, len);
-	n = scandir(SYSFS_FCHOST, &namelist, 0, alphasort);
-	if (n > 0) {
-		while (n--) {
-			/* check symbolic name */
-			if (!fcoeadm_check_fchost(ifname,
-						  namelist[n]->d_name)) {
-				dname_len = strnlen(namelist[n]->d_name, len);
-				if (dname_len != len) {
-					/*
-					 * This assumes that d_name is always
-					 * NULL terminated.
-					 */
-					strncpy(fchost, namelist[n]->d_name,
-						dname_len + 1);
-					found = 1;
-				} else {
-					fprintf(stderr, "scsi_host (%s) is "
-						"too large for a buffer that "
-						"is only %d bytes large\n",
-						namelist[n]->d_name, dname_len);
-					free(namelist[n]);
+	for (;;) {
+		if (clif_ifname == NULL) {
+			struct dirent *dent;
+			DIR *dir = opendir(FCM_SRV_DIR);
+			if (dir) {
+				while ((dent = readdir(dir))) {
+					if (strcmp(dent->d_name, ".") == 0 ||
+						strcmp(dent->d_name, "..") == 0)
+						continue;
+					clif_ifname = strdup(dent->d_name);
+					break;
 				}
+			closedir(dir);
 			}
-			free(namelist[n]);
 		}
-		free(namelist);
+
+		clif_conn = fcoeadm_open_cli(clif_ifname);
+		if (clif_conn) {
+			fprintf(stdout, "Connection established.\n");
+			break;
+		} else {
+			fprintf(stderr, "Failed to connect to fcoemon.\n");
+			free(clif_ifname);
+			return -1;
+		}
 	}
 
-	return found;
-}
+	ret = fcoeadm_request(cmd, device_name);
+
+	free(clif_ifname);
+	fcoeadm_close_cli();
 
+	return ret;
+}
 
 /*
  * Create FCoE instance for this ifname
@@ -258,7 +308,7 @@ static int fcoeadm_create(char *ifname)
 			progname, ifname);
 		return -EINVAL;
 	}
-	return fcoeadm_action(FCOE_CREATE, ifname);
+	return fcoeadm_action(FCOE_CREATE_CMD, ifname);
 }
 
 /*
@@ -272,21 +322,7 @@ static int fcoeadm_destroy(char *ifname)
 			progname, ifname);
 		return -EINVAL;
 	}
-	return fcoeadm_action(FCOE_DESTROY, ifname);
-}
-
-/*
- * Validate an existing instance for an FC interface
- */
-static int fcoeadm_validate_interface(char *ifname, char *fchost, int len)
-{
-	if (!fcoeadm_find_fchost(ifname, fchost, len)) {
-		fprintf(stderr, "%s: No fc_host found for %s\n",
-			progname, ifname);
-		return -EINVAL;
-	}
-
-	return 0;
+	return fcoeadm_action(FCOE_DESTROY_CMD, ifname);
 }
 
 /*
@@ -294,14 +330,7 @@ static int fcoeadm_validate_interface(char *ifname, char *fchost, int len)
  */
 static int fcoeadm_reset(char *ifname)
 {
-	char fchost[FCHOSTBUFLEN];
-	char path[256];
-
-	if (fcoeadm_validate_interface(ifname, fchost, FCHOSTBUFLEN))
-		return -EINVAL;
-
-	sprintf(path, "%s/%s/issue_lip", SYSFS_FCHOST, fchost);
-	return fcoeadm_action(path, "1");
+	return fcoeadm_action(FCOE_RESET_CMD, ifname);
 }
 
 /*
@@ -474,7 +503,7 @@ int main(int argc, char *argv[])
 					sizeof(opt_info->ifname));
 			}
 			if (strnlen(opt_info->ifname, IFNAMSIZ - 1)) {
-				if (fcoeadm_validate_interface(
+				if (fcoeclif_validate_interface(
 					    opt_info->ifname,
 					    fchost, FCHOSTBUFLEN))
 					goto done;
@@ -504,7 +533,7 @@ int main(int argc, char *argv[])
 					sizeof(opt_info->ifname));
 			}
 			if (strnlen(opt_info->ifname, IFNAMSIZ - 1)) {
-				if (fcoeadm_validate_interface(
+				if (fcoeclif_validate_interface(
 					    opt_info->ifname,
 					    fchost, FCHOSTBUFLEN))
 					goto done;
@@ -535,7 +564,7 @@ int main(int argc, char *argv[])
 				strncpy(opt_info->ifname, optarg,
 					sizeof(opt_info->ifname));
 			if (strnlen(opt_info->ifname, IFNAMSIZ - 1)) {
-				if (fcoeadm_validate_interface(
+				if (fcoeclif_validate_interface(
 					    opt_info->ifname,
 					    fchost, FCHOSTBUFLEN))
 					goto done;
diff --git a/fcoeadm.h b/fcoeadm.h
index 3064423..fdda13a 100644
--- a/fcoeadm.h
+++ b/fcoeadm.h
@@ -42,15 +42,13 @@
 #include <getopt.h>
 #include <byteswap.h>
 #include <net/if.h>
+#include <sys/un.h>
 
 #include "hbaapi.h"
 #include "net_types.h"
 #include "fc_types.h"
 #include "fc_scsi.h"
 
-#define __USE_GNU
-#include <string.h>
-
 #define FCOE_MAX_LUN	255
 
 struct opt_info {
@@ -67,6 +65,18 @@ struct opt_info {
 	#define DEFAULT_STATS_INTERVAL	1
 	int n_interval;		/* seconds */
 };
+
+/**
+ * struct clif - Internal structure for client interface library
+ *
+ * This structure is used by fcoeadm client interface to store internal data.
+ */
+struct clif {
+	int s;
+	struct sockaddr_un local;
+	struct sockaddr_un dest;
+};
+
 extern struct opt_info *opt_info;
 extern char build_date[];
 

-- 
Signature: Lucy Liu <lucy.liu at intel.com>



More information about the devel mailing list