Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:12.2
open-fcoe
fcoe-utils-clifv2
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File fcoe-utils-clifv2 of Package open-fcoe
fcoe-utils: create socket interface in fcoe-utils From: Lucy Liu <lucy.liu@intel.com> In current fcoe utils, both fcoemon and fcoeadm could write to /sys/class/.. files by calling "create"/"destroy"/"reset" commands. Fcoemon has no way to manage those files after startup. Fcoeadm bypasses fcoemon and accesses those files. So this patch create socket interface between fcoemon and fcoeadm. Fcoemon as server provided an IPC interface for client applications(fcoeadm) to set create/reset/destroy device interface. fcoeadm doesn't write to those files anymore, instead, it connects to the client interface of fcoemon to perform those operations. The detail changes are as following: a. Create new files fcoe_clif.h/c as a library used by fcoemon and fcoeadm; b. 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; c. In fcoemon.c/h, create socket interface and resiger receive function using sa_loop_select; d. change Makefile.am for new files fcoe_clif.h/c e. fcnsq.c: a simple fix for compilation warning; Signed-off-by: Lucy Liu <lucy.liu@intel.com> --- Makefile.am | 4 - fcnsq.c | 2 fcoe_clif.c | 137 ++++++++++++++++++ fcoe_clif.h | 49 +++++++ fcoeadm.c | 312 +++++++++++++++++++++++++----------------- fcoeadm.h | 14 ++ fcoemon.c | 435 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- fcoemon.h | 20 +++ fcoeplumb.in | 39 ----- 9 files changed, 818 insertions(+), 194 deletions(-) create mode 100644 fcoe_clif.c create mode 100644 fcoe_clif.h -- Signed-off-by: Lucy Liu <lucy.liu@intel.com> diff --git a/Makefile.am b/Makefile.am index 3f8ac7f..0703449 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,7 +13,7 @@ AM_CFLAGS = -DSYSCONFDIR="\"${sysconfdir}\"" ## rules for building fcoeadm ## only listed sources get packaged, so must list all headers too fcoeadm_SOURCES = fcoeadm_display.c fcoeadm.c fcoeadm.h \ -include/fc_scsi.h include/fc_types.h include/net_types.h +include/fc_scsi.h include/fc_types.h include/net_types.h fcoe_clif.c fcoe_clif.h ## fcoeadm uses HBAAPI, so get the right flags for compiling and linking fcoeadm_CFLAGS = $(HBAAPI_CFLAGS) @@ -30,7 +30,7 @@ fcping_LDFLAGS = $(HBAAPI_LIBS) -lrt ## rules for building fcoemon ## only listed sources get packaged, so must list all headers too fcoemon_SOURCES = fcoemon_utils.c fcoemon.c fcoemon.h fcoemon_utils.h \ -include/fc_scsi.h include/fc_types.h include/net_types.h +include/fc_scsi.h include/fc_types.h include/net_types.h fcoe_clif.c fcoe_clif.h ## fcoemon needs headers from dcbd, get the right include path for them fcoemon_CFLAGS = $(DCBD_CFLAGS) diff --git a/fcnsq.c b/fcnsq.c index 1c78901..6f3ac0e 100644 --- a/fcnsq.c +++ b/fcnsq.c @@ -373,7 +373,7 @@ int main(int argc, char *argv[]) int bsg_dev; u32 port_id; u64 wwnn; - int rc; + int rc = 0; enum commands cmd = 0; char c; diff --git a/fcoe_clif.c b/fcoe_clif.c new file mode 100644 index 0000000..a64e15b --- /dev/null +++ b/fcoe_clif.c @@ -0,0 +1,137 @@ +/* + * Copyright(c) 2009 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <libgen.h> +#include <dirent.h> +#include <net/if.h> +#include <errno.h> +#include "fcoe_clif.h" + +static char *fcoeadm_read(const char *path) +{ + 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; +} + +static int fcoeadm_check_fchost(const char *ifname, const char *dname) +{ + char *buf; + char path[512]; + + if (!ifname) + return -EINVAL; + + if (!dname) + return -EINVAL; + + if (dname[0] == '.') + return -EINVAL; + + sprintf(path, "%s/%s/symbolic_name", SYSFS_FCHOST, dname); + buf = fcoeadm_read(path); + if (!buf) + return -EINVAL; + + if (!strstr(buf, ifname)) { + free(buf); + return -EINVAL; + } + free(buf); + return 0; +} + +static int fcoeadm_find_fchost(char *ifname, char *fchost, int len) +{ + int n, dname_len; + int found = 0; + struct dirent **namelist; + + if (!ifname) + 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]); + } + } + free(namelist[n]); + } + free(namelist); + } + + return found; +} + +/* + * Validate an existing instance for an FC interface + */ +int fcoeadm_validate_interface(char *ifname, char *fchost, int len) +{ + if (!fcoeadm_find_fchost(ifname, fchost, len)) { + fprintf(stderr, "No fc_host found for %s\n", ifname); + return -EINVAL; + } + + return 0; +} diff --git a/fcoe_clif.h b/fcoe_clif.h new file mode 100644 index 0000000..dedbe59 --- /dev/null +++ b/fcoe_clif.h @@ -0,0 +1,49 @@ +/* + * Copyright(c) 2009 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Maintained at www.Open-FCoE.org + */ + +#ifndef _FCOE_CLIF_H_ +#define _FCOE_CLIF_H_ + +#define FCM_SRV_DIR "/var/run/fcm" +#define CLIF_IFNAME "fcm_clif" +#define MAX_MSGBUF 512 +#define FCHOSTBUFLEN 64 +#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" + +enum clif_status { + CLI_SUCCESS = 0, + CLI_FAIL, + CLI_NO_ACTION +}; + +/* + * Description of fcoemon and fcoeadm socket data structure interface + */ +struct clif_data { + int cmd; + char ifname[IFNAMSIZ]; +}; + +int fcoeadm_validate_interface(char *ifname, char *fchost, int len); +#endif /* _FCOE_CLIF_H_ */ diff --git a/fcoeadm.c b/fcoeadm.c index c766921..742cc94 100644 --- a/fcoeadm.c +++ b/fcoeadm.c @@ -24,18 +24,12 @@ #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.9\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 +47,14 @@ static struct option fcoeadm_opts[] = { struct opt_info _opt_info, *opt_info = &_opt_info; char progname[20]; +struct clif *clif_conn; + +enum { /* Match the values in fcoemon */ + FCOEADM_CREATE = 1, + FCOEADM_DESTROY, + FCOEADM_RESET, +}; + static void fcoeadm_help(void) { printf("%s\n", fcoeadm_version); @@ -121,131 +123,216 @@ 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_print_response(char *rbuf, int rlen, + char *device_name, int cmd) { - FILE *fp = NULL; + fprintf(stdout, "Command :\t"); + switch (cmd) { + case FCOEADM_CREATE: + fprintf(stdout, "FCOEADM CREATE\n"); + break; + case FCOEADM_RESET: + fprintf(stdout, "FCOEADM RESET\n"); + break; + case FCOEADM_DESTROY: + fprintf(stdout, "FCOEADM DELETE\n"); + break; + default: + fprintf(stderr, "BAD COMMAND\n"); + } - if (!path) - return -EINVAL; + fprintf(stdout, "Port Name:\t%s\n", device_name); - if (!s) - return -EINVAL; + fprintf(stdout, "Status :\t%s\n", atoi(rbuf) ? "FAIL" : "SUCCESS"); - fp = fopen(path, "w"); - if (!fp) { - fprintf(stderr, - "%s: Failed to open %s\n", progname, path); - return -ENOENT; - } - if (EOF == fputs(s, fp)) - fprintf(stderr, - "%s: Failed to write %s to %s\n", progname, s, path); + return 0; +} - fclose(fp); +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 char *fcoeadm_read(const char *path) +static int fcoeadm_request(int cmd, char *s) { - FILE *fp; - char *buf; - int size = 512; + struct clif_data *data = NULL; + char rbuf[MAX_MSGBUF]; + size_t len; + int ret; - if (!path) - return NULL; + if (clif_conn == NULL) { + printf("Not connected to fcoemon.\n"); + return -EINVAL; + } - buf = malloc(size); - if (!buf) - return NULL; - memset(buf, 0, size); + data = (struct clif_data *)malloc(sizeof(struct clif_data)); + if (data == NULL) + return -EINVAL; - fp = fopen(path, "r"); - if (fp) { - if (fgets(buf, size, fp)) { - fclose(fp); - return buf; - } + 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; } - fclose(fp); - free(buf); - return NULL; + + rbuf[len] = '\0'; + ret = fcoeadm_print_response(rbuf, len, s, cmd); + free(data); + return ret; + +fail: + free(data); + return -EINVAL; } -static int fcoeadm_check_fchost(const char *ifname, const char *dname) +static void fcoeadm_close_cli(void) { - char *buf; - char path[512]; + if (clif_conn == NULL) + return; - if (!ifname) - return -EINVAL; + unlink(clif_conn->local.sun_path); + close(clif_conn->s); + free(clif_conn); + clif_conn = NULL; +} - if (!dname) - return -EINVAL; +/* + * Create fcoeadm client interface + */ +static struct clif *fcoeadm_open_cli(const char *ifname) +{ + char *fcmon_file = NULL; + int flen; + static int counter; - if (dname[0] == '.') - return -EINVAL; + if (ifname == NULL) + return NULL; - sprintf(path, "%s/%s/symbolic_name", SYSFS_FCHOST, dname); - buf = fcoeadm_read(path); - if (!buf) - return -EINVAL; + 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 (!strstr(buf, ifname)) { - free(buf); - 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; } - free(buf); - return 0; + + free(fcmon_file); + return clif_conn; + +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; - - if (!ifname) - return -EINVAL; + char *clif_ifname = NULL; + int ret = 0; - if ((!fchost) || (len <= 0)) + if (!device_name) 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 +345,7 @@ static int fcoeadm_create(char *ifname) progname, ifname); return -EINVAL; } - return fcoeadm_action(FCOE_CREATE, ifname); + return fcoeadm_action(FCOEADM_CREATE, ifname); } /* @@ -272,21 +359,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(FCOEADM_DESTROY, ifname); } /* @@ -294,14 +367,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(FCOEADM_RESET, ifname); } /* diff --git a/fcoeadm.h b/fcoeadm.h index 3064423..9937182 100644 --- a/fcoeadm.h +++ b/fcoeadm.h @@ -42,6 +42,7 @@ #include <getopt.h> #include <byteswap.h> #include <net/if.h> +#include <sys/un.h> #include "hbaapi.h" #include "net_types.h" @@ -67,6 +68,19 @@ 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 the fcmon and fcoeadm client interface + * libraryto 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[]; diff --git a/fcoemon.c b/fcoemon.c index 8e3980b..cfe6b3e 100644 --- a/fcoemon.c +++ b/fcoemon.c @@ -58,6 +58,7 @@ #include "fcoemon_utils.h" #include "fcoemon.h" +#include "fcoe_clif.h" #ifndef SYSCONFDIR #define SYSCONFDIR "/etc" @@ -86,6 +87,15 @@ static char *fcoemon_version = \ "fcoemon v1.0.8\n Copyright (c) 2009, Intel Corporation.\n"; +enum fcm_srv_status { + fcm_success = 0, + fcm_fail, + fcm_no_action +}; + +static struct fcm_srv_data *srv_data; + + /* * fcoe service configuration data * Note: These information are read in from the fcoe service @@ -105,6 +115,7 @@ struct fcoe_port { u_int32_t action; /* current state */ u_int32_t last_action; /* last action */ int last_msg_type; /* last rtnetlink msg type received on if name */ + struct sock_info *sock_reply; }; enum fcoeport_ifname { @@ -114,8 +125,6 @@ enum fcoeport_ifname { static u_int8_t fcm_def_qos_mask = FCM_DEFAULT_QOS_MASK; -struct clif; /* for dcbtool.h only */ - /* * Interact with DCB daemon. */ @@ -128,6 +137,7 @@ static void fcm_dcbd_event(char *, size_t); static void fcm_dcbd_cmd_resp(char *, cmd_status); static void fcm_netif_advance(struct fcm_netif *); static void fcm_fcoe_action(struct fcm_netif *, struct fcoe_port *); +static int fcm_fcoe_if_action(char *, char *); struct fcm_clif { int cl_fd; @@ -625,7 +635,6 @@ void fcm_process_link_msg(struct ifinfomsg *ip, int len, unsigned type) else p->action = FCP_CREATE_IF; } - } if (!p->fcoe_enable) p->action = FCP_DESTROY_IF; @@ -989,6 +998,8 @@ static void fcm_cleanup(void) struct fcm_netif *ff, *head; for (curr = fcoe_config.port; curr; curr = next) { + FCM_LOG_DBG("OP: DESTROY %s\n", curr->ifname); + fcm_fcoe_if_action(FCOE_DESTROY, curr->ifname); next = curr->next; free(curr); } @@ -1624,7 +1635,8 @@ static void fcm_dcbd_event(char *msg, size_t len) p = fcm_find_fcoe_port(ff->ifname, FCP_REAL_IFNAME); while (p) { - if (p->dcb_required && p->last_msg_type != RTM_DELLINK) + if (p->dcb_required && p->last_msg_type != RTM_DELLINK && + p->fcoe_enable) break; p = fcm_find_next_fcoe_port(p, ff->ifname); } @@ -1673,48 +1685,102 @@ static void fcm_dcbd_event(char *msg, size_t len) return; } +static void fcm_cli_reply(struct sock_info *r, int status) +{ + char rbuf[MAX_MSGBUF]; + snprintf(rbuf, MSG_RBUF, "%d", status); + sendto(r->sock, rbuf, MSG_RBUF, 0, (struct sockaddr *)&(r->from), + r->fromlen); +} + +static int fcm_fcoe_if_action(char *path, char *ifname) +{ + FILE *fp = NULL; + int ret = fcm_fail; + + fp = fopen(path, "w"); + if (!fp) { + FCM_LOG_ERR(errno, "%s: Failed to open path %s\n", + progname, path); + goto err_out; + } + + if (EOF == fputs(ifname, fp)) { + FCM_LOG_ERR(errno, "%s: Failed to write %s to path %s.\n", + progname, ifname, path); + goto out; + } + + ret = fcm_success; +out: + fclose(fp); +err_out: + return ret; +} + /* - * Run script to enable or disable the interface or print a message. * - * Input: enable = 0 Destroy the FCoE interface - * enable = 1 Create the FCoE interface - * enable = 2 Reset the interface + * Input: action = 1 Destroy the FCoE interface + * action = 2 Create the FCoE interface + * action = 3 Reset the interface */ static void fcm_fcoe_action(struct fcm_netif *ff, struct fcoe_port *p) { - char *op, *debug, *syslog = NULL; + char *debug, *syslog = NULL; char *qos_arg; char qos[64]; + char *ifname = p->ifname; + char fchost[FCHOSTBUFLEN]; + char path[256]; u_int32_t mask; int rc; int fd; + rc = fcm_success; qos_arg = "--qos-enable"; switch (p->action) { case FCP_CREATE_IF: if (p->last_action == FCP_CREATE_IF) - return; - op = "--create"; + break; + FCM_LOG_DBG("OP: CREATE\n"); + rc = fcm_fcoe_if_action(FCOE_CREATE, ifname); break; case FCP_DESTROY_IF: if (p->last_action == FCP_DESTROY_IF) - return; - op = "--destroy"; + break; qos_arg = "--qos-disable"; + FCM_LOG_DBG("OP: DESTROY\n"); + rc = fcm_fcoe_if_action(FCOE_DESTROY, ifname); break; case FCP_RESET_IF: - op = "--reset"; + FCM_LOG_DBG("OP: RESET\n"); + if (fcoeadm_validate_interface(ifname, fchost, FCHOSTBUFLEN)) { + fcm_cli_reply(p->sock_reply, CLI_FAIL); + return; + } + sprintf(path, "%s/%s/issue_lip", SYSFS_FCHOST, fchost); + rc = fcm_fcoe_if_action(path, "1"); break; default: return; break; } + + if (p->sock_reply) { + fcm_cli_reply(p->sock_reply, rc); + free(p->sock_reply); + p->sock_reply = NULL; + } + + if ((p->action != FCP_RESET_IF) && (p->last_action == p->action)) + return; + p->last_action = p->action; if (p->action && !ff->ff_qos_mask) return; if (fcm_dcbd_cmd == NULL) { - FCM_LOG_DEV_DBG(ff, "Should %s per op state", op); + FCM_LOG_DEV_DBG(ff, "Should call fcoeplumb per op state"); return; } @@ -1752,12 +1818,8 @@ static void fcm_fcoe_action(struct fcm_netif *ff, struct fcoe_port *p) if (fcoe_config.debug) { debug = "--debug"; - if (!p->action) - FCM_LOG_DEV_DBG(ff, "%s %s %s\n", fcm_dcbd_cmd, - op, syslog); - else - FCM_LOG_DEV_DBG(ff, "%s %s %s %s %s\n", - fcm_dcbd_cmd, op, qos_arg, qos, + FCM_LOG_DEV_DBG(ff, "%s %s %s %s\n", + fcm_dcbd_cmd, qos_arg, qos, syslog); } @@ -1766,7 +1828,7 @@ static void fcm_fcoe_action(struct fcm_netif *ff, struct fcoe_port *p) FCM_LOG_ERR(errno, "fork error"); else if (rc == 0) { /* child process */ execlp(fcm_dcbd_cmd, fcm_dcbd_cmd, p->ifname, - p->real_ifname, op, qos_arg, qos, debug, syslog, + p->real_ifname, qos_arg, qos, debug, syslog, (char *)NULL); } @@ -1894,7 +1956,6 @@ static void fcm_netif_advance(struct fcm_netif *ff) } } - /* * Run through these steps at the end of each select loop. * 1. Process list of network interfaces @@ -1922,8 +1983,16 @@ static void fcm_handle_changes() p = fcoe_config.port; while (p) { ff = fcm_netif_lookup(p->real_ifname); - if (!ff) + if (!ff) { + FCM_LOG_DBG("no fcoe_action.\n"); + if (p->sock_reply) { + fcm_cli_reply(p->sock_reply, CLI_FAIL); + free(p->sock_reply); + p->sock_reply = NULL; + p->action = FCP_WAIT; + } goto next_port; + } fcm_fcoe_action(ff, p); @@ -1937,7 +2006,6 @@ static void fcm_usage(void) { printf("%s\n", fcoemon_version); printf("Usage: %s\n" - "\t [-e|--exec <exec>]\n" "\t [-f|--foreground]\n" "\t [-d|--debug]\n" "\t [-s|--syslog]\n" @@ -1948,7 +2016,6 @@ static void fcm_usage(void) static void fcm_sig(int sig) { - fcm_dcbd_shutdown(); sa_select_exit(); } @@ -1980,6 +2047,317 @@ static void fcm_pidfile_create(void) } } +static int fcm_cli_create(char *ifname, int cmd, struct sock_info **r) +{ + struct fcoe_port *p; + struct fcoe_port *curr; + struct fcm_netif *ff; + + p = fcm_find_fcoe_port(ifname, FCP_CFG_IFNAME); + if (p) { + if (!p->fcoe_enable) { + p->fcoe_enable = 1; + p->action = cmd; + p->sock_reply = *r; + if (p->dcb_required) { + ff = fcm_netif_lookup(p->real_ifname); + if (!ff) + return fcm_success; + fcm_dcbd_state_set(ff, FCD_GET_DCB_STATE); + if (ff->ff_dcbd_state == FCD_GET_DCB_STATE) + p->action = FCP_WAIT; + } + return fcm_success; + } else { + /* no action needed */ + return CLI_NO_ACTION; + } + } + + p = (struct fcoe_port *) calloc(1, sizeof(struct fcoe_port)); + if (!p) { + FCM_LOG_ERR(errno, "fail to allocate fcoe_port %s", ifname); + return fcm_fail; + } + + snprintf(p->ifname, strlen(ifname)+1, "%s", ifname); + fcm_vlan_dev_real_dev(ifname, p->real_ifname); + if (!strlen(p->real_ifname)) + snprintf(p->real_ifname, sizeof(p->real_ifname), "%s", ifname); + p->fcoe_enable = 1; + p->dcb_required = 0; + p->action = cmd; + p->sock_reply = *r; + p->next = NULL; + + if (!fcoe_config.port) + fcoe_config.port = p; + else { + curr = fcoe_config.port; + while (curr->next) + curr = curr->next; + curr->next = p; + } + + /* check and add the real_ifname to the network interface list */ + ff = fcm_netif_lookup_create(p->real_ifname); + if (!ff) { + FCM_LOG_ERR(errno, "fail to allocate fcm_netif %s", ifname); + return fcm_fail; + } + + return fcm_success; +} + +static int fcm_cli_destroy(char *ifname, int cmd, struct sock_info **r) +{ + struct fcoe_port *p; + + p = fcm_find_fcoe_port(ifname, FCP_CFG_IFNAME); + if (p) { + if (p->fcoe_enable) { + p->fcoe_enable = 0; + p->action = cmd; + p->sock_reply = *r; + return fcm_success; + } else { + /* no action needed */ + return CLI_NO_ACTION; + } + } + + FCM_LOG_ERR(errno, "%s is not in port list.\n", ifname); + return fcm_fail; +} + +static int fcm_cli_reset(char *ifname, int cmd, struct sock_info **r) +{ + struct fcoe_port *p; + + p = fcm_find_fcoe_port(ifname, FCP_CFG_IFNAME); + if (p) { + p->action = cmd; + p->sock_reply = *r; + return fcm_success; + } + + FCM_LOG_ERR(errno, "%s is not in port list.\n", ifname); + return fcm_fail; +} + +int fcm_save_reply(struct sock_info **r, struct sockaddr_un *f, socklen_t flen, + int s) +{ + if (!*r) { + *r = (struct sock_info *)malloc(sizeof(struct sock_info)); + if (!*r) { + FCM_LOG_ERR(errno, "Failed in save reply info.\n"); + return fcm_fail; + } + (*r)->sock = s; + (*r)->from.sun_family = f->sun_family; + memcpy((*r)->from.sun_path, f->sun_path, strlen(f->sun_path)); + (*r)->fromlen = flen; + return fcm_success; + } + + return fcm_fail; +} + +/* + * receive function registered in sa_select_loop + */ +static void fcm_srv_receive(void *arg) +{ + struct fcm_srv_data *fcm_srv_rdata = arg; + struct clif_data *data; + struct sockaddr_un from; + socklen_t fromlen = sizeof(struct sockaddr_un); + struct sock_info *reply = NULL; + char buf[MAX_MSGBUF], rbuf[MAX_MSGBUF]; + char *ifname; + int res, cmd, snum; + + snum = fcm_srv_rdata->srv_sock; + res = recvfrom(snum, buf, sizeof(buf) - 1, + MSG_DONTWAIT, (struct sockaddr *)&from, &fromlen); + if (res < 0) { + FCM_LOG_ERR(errno, "Fail in fcm_srv_receive()"); + return; + } + + buf[res] = '\0'; + data = (struct clif_data *)buf; + + cmd = data->cmd; + ifname = strdup(data->ifname); + if (ifname == NULL) + goto err; + + switch (cmd) { + case FCP_CREATE_IF: + FCM_LOG_DBG("FCMON CREATE\n"); + if (fcm_save_reply(&reply, &from, fromlen, snum)) + goto err_out; + if (fcm_cli_create(ifname, FCP_CREATE_IF, &reply)) + goto err_out; + break; + case FCP_DESTROY_IF: + FCM_LOG_DBG("FCMON DESTROY\n"); + if (fcm_save_reply(&reply, &from, fromlen, snum)) + goto err_out; + if (fcm_cli_destroy(ifname, FCP_DESTROY_IF, &reply)) + goto err_out; + break; + case FCP_RESET_IF: + FCM_LOG_DBG("FCMON RESET\n"); + if (fcm_save_reply(&reply, &from, fromlen, snum)) + goto err_out; + if (fcm_cli_reset(ifname, FCP_RESET_IF, &reply)) + goto err_out; + break; + default: + fprintf(stderr, "BAD COMMAND\n"); + goto err_out; + } + + free(ifname); + return; + +err_out: + free(ifname); + free(reply); +err: + snprintf(rbuf, MSG_RBUF, "%d", CLI_FAIL); + sendto(snum, rbuf, MSG_RBUF, 0, (struct sockaddr *)&from, fromlen); + return; +} + +static int fcm_srv_create(struct fcm_srv_data *srv_data) +{ + struct sockaddr_un addr; + int s = -1; + char *fname = NULL; + int retry; + size_t len; + + srv_data->srv_sock = -1; + + if (srv_data->srv_interface == NULL) + return -1; + + if (mkdir(srv_data->srv_interface, S_IRWXU | S_IRWXG) < 0) { + if (errno == EEXIST) { + FCM_LOG_DBG("fcm_srv_create: directory existed."); + } else { + FCM_LOG_ERR(errno, "fcm_srv_create: mkdir[interface]"); + goto fail; + } + } + + if (srv_data->srv_if_gid_set && + chown(srv_data->srv_interface, 0, + srv_data->srv_if_gid) < 0) { + FCM_LOG_ERR(errno, "fcm_srv_create: chown[srv_interface]"); + goto fail; + } + + if (strlen(srv_data->srv_interface) + 1 + strlen(srv_data->iface) + >= sizeof(addr.sun_path)) + goto fail; + + s = socket(PF_UNIX, SOCK_DGRAM, 0); + if (s < 0) { + FCM_LOG_ERR(errno, "socket(PF_UNIX)"); + goto fail; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + + len = strlen(srv_data->srv_interface) + strlen(srv_data->iface) + 2; + fname = malloc(len); + memset(fname, 0, len); + if (fname == NULL) + goto fail; + + snprintf(fname, len, "%s/%s", + srv_data->srv_interface, srv_data->iface); + fname[len - 1] = '\0'; + + strncpy(addr.sun_path, fname, sizeof(addr.sun_path)); + for (retry = 0; retry < 2; retry++) { + if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + if (errno == EADDRINUSE) + unlink(fname); + } else { + break; + } + } + if (retry == 2) { + FCM_LOG_ERR(errno, "bind(PF_UNIX)"); + goto fail; + } + + if (srv_data->srv_if_gid_set && + chown(fname, 0, srv_data->srv_if_gid) < 0) { + FCM_LOG_ERR(errno, "chown[srv_interface/ifname]"); + goto fail; + } + + if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { + FCM_LOG_ERR(errno, "chmod[srv_interface/ifname]"); + goto fail; + } + free(fname); + + srv_data->srv_sock = s; + FCM_LOG_DBG("fcm_srv_create: created"); + sa_select_add_fd(s, fcm_srv_receive, NULL, NULL, srv_data); + + return 0; + +fail: + if (s >= 0) + close(s); + if (fname) { + unlink(fname); + free(fname); + } + return -1; +} + +/* + * Create fcoemon server interface + */ +static void fcm_srv_init(void) +{ + if (!srv_data) { + srv_data = malloc(sizeof(struct fcm_srv_data)); + if (srv_data == NULL) { + FCM_LOG_ERR(errno, "srv_data malloc error\n"); + exit(EXIT_FAILURE); + } + } + + srv_data->srv_interface = (char *)FCM_SRV_DIR; + strncpy(srv_data->iface, CLIF_IFNAME, sizeof(CLIF_IFNAME)+1); + srv_data->srv_if_gid_set = 0; + srv_data->srv_if_gid = 0; + + if (fcm_srv_create(srv_data)) + FCM_LOG_ERR(errno, "fcm_srv_init : fcm_srv_create() failed"); + +} + +static void fcm_srv_shutdown(void) +{ + FCM_LOG_DBG("Shutdown fcmon server"); + close(srv_data->srv_sock); + free(srv_data); + return; +} + int main(int argc, char **argv) { struct sigaction sig; @@ -2006,9 +2384,6 @@ int main(int argc, char **argv) fcoe_config.use_syslog = 1; enable_syslog(1); break; - case 'e': - fcm_dcbd_cmd = optarg; - break; case 'v': printf("%s\n", fcoemon_version); return 0; @@ -2067,6 +2442,7 @@ int main(int argc, char **argv) fcm_fcoe_init(); fcm_link_init(); /* NETLINK_ROUTE protocol */ fcm_dcbd_init(); + fcm_srv_init(); sa_select_set_callback(fcm_handle_changes); rc = sa_select_loop(); @@ -2075,6 +2451,7 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } fcm_dcbd_shutdown(); + fcm_srv_shutdown(); fcm_cleanup(); return 0; } diff --git a/fcoemon.h b/fcoemon.h index ad71838..4f21634 100644 --- a/fcoemon.h +++ b/fcoemon.h @@ -73,6 +73,13 @@ enum fcm_dcbd_state { FCD_ERROR, /* DCB error or port unknown by DCB */ }; +#define MSG_RBUF sizeof(int) +struct sock_info { + int sock; + struct sockaddr_un from; + socklen_t fromlen; +}; + /* * Action codes for FCoE ports */ @@ -131,6 +138,17 @@ struct fcm_netif { struct sa_timer dcbd_retry_timer; /* dcbd retry timer */ }; +/* + * Description of fcoe socket server interface + */ +struct fcm_srv_data { + char iface[IFNAMSIZ+1]; + char *srv_interface; + gid_t srv_if_gid; + int srv_if_gid_set; + int srv_sock; +}; + TAILQ_HEAD(fcm_netif_head, fcm_netif); struct fcm_netif_head fcm_netif_head; @@ -139,6 +157,8 @@ extern char build_date[]; static void fcm_dcbd_init(void); static void fcm_dcbd_shutdown(void); static void fcm_fcoe_init(void); +static void fcm_srv_init(void); +static void fcm_srv_shutdown(void); static struct fcm_netif *fcm_netif_lookup(char *); static struct fcm_netif *fcm_netif_lookup_create(char *); static int fcm_link_init(void); diff --git a/fcoeplumb.in b/fcoeplumb.in index 1721b60..d5c4e68 100755 --- a/fcoeplumb.in +++ b/fcoeplumb.in @@ -49,8 +49,6 @@ sbindir=@sbindir@ sysconfdir=@sysconfdir@ # make sure there's a sane path to find basic commands and system tools (tc) PATH=$PATH:/sbin:/usr/sbin:/bin:/usr/bin -FCOEADM=${sbindir}/fcoeadm # command to create/destroy FCoE instances -CONFIG_DIR=${sysconfdir}/fcoe LOGGER= DEBUG_LOGGING= @@ -192,36 +190,6 @@ replace_skbedit_filter() action skbedit queue_mapping $queue } -remove_fcoe_interface() -{ - ifname=$1 - - STATUS=`$FCOEADM -i $ifname 2>&1 | \ - awk '/Symbolic Name:/ && /'$ifname'$/{print $6}'` - if [ "$STATUS" == "$ifname" ]; then - [ ${DEBUG_LOGGING} ] && $LOGGER "$FCOEADM -d $ifname" - $FCOEADM -d $ifname - else - [ ${DEBUG_LOGGING} ] && $LOGGER \ - "FCoE interface $ifname doesn't exist" - fi -} - -create_fcoe_interface() -{ - ifname=$1 - - STATUS=`$FCOEADM -i $ifname 2>&1 | \ - awk '/Symbolic Name:/ && /'$ifname'$/{print $6}'` - if [ -z "$STATUS" ]; then - [ ${DEBUG_LOGGING} ] && $LOGGER "$FCOEADM -c $ifname" - $FCOEADM -c $ifname - else - [ ${DEBUG_LOGGING} ] && $LOGGER \ - "FCoE interface $ifname already created" - fi -} - config_logging() { if [ $DEBUG_LOGGING ] ; then @@ -287,13 +255,6 @@ done fcoe_filter_id=`get_filter_id $real_ifname $FCOE_FILTER_KEY` fip_filter_id=`get_filter_id $real_ifname $FIP_FILTER_KEY` -if [ "$cmd" == "destroy" ]; then - remove_fcoe_interface $ifname - -elif [ "$cmd" == "create" ]; then - create_fcoe_interface $ifname -fi - if [ "$qos_list" == "disable" ]; then # Remove the FCoE filters find_skbedit_filter $real_ifname $FCOE_ETHERTYPE $fcoe_filter_id
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor