Add socket server interface into fcoemon. In fcoemon.c/h, create socket
interface and resiger receive function using sa_loop_select. The code has
merged with fcoemon redesign. In fcoe_port struct, add a new member as
socket reply information. Fcoemon will save the socket reply info and wait
to reply to fcoeadm at the end of select loop after the "action".

Signed-off-by: Lucy Liu <[email protected]>

---

 fcoemon.c |  437 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 fcoemon.h |   20 +++
 2 files changed, 428 insertions(+), 29 deletions(-)

diff --git a/fcoemon.c b/fcoemon.c
index a3a09b1..6e9f863 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"
@@ -83,9 +84,20 @@
 #define FCM_PING_REQ_LEN       1 /* byte-length of dcbd PING request */
 #define FCM_PING_RSP_LEN       8 /* byte-length of dcbd PING response */
 
+#define FCOE_CREATE    SYSFS_FCOE "/create"
+#define FCOE_DESTROY   SYSFS_FCOE "/destroy"
+
 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 +117,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 +127,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 +139,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;
@@ -973,6 +985,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);
        }
@@ -1597,7 +1611,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);
        }
@@ -1646,48 +1661,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 (fcoeclif_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;
        }
 
@@ -1725,12 +1794,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);
                }
 
@@ -1738,8 +1803,7 @@ static void fcm_fcoe_action(struct fcm_netif *ff, struct 
fcoe_port *p)
                if (rc < 0)
                        FCM_LOG_ERR(errno, "fork error");
                else if (rc == 0) {     /* child process */
-                       execlp(fcm_dcbd_cmd, fcm_dcbd_cmd, "--fcoeif",
-                              p->ifname, op, "--netif", p->real_ifname,
+                       execlp(fcm_dcbd_cmd, fcm_dcbd_cmd, p->real_ifname,
                               qos_arg, qos, debug, syslog, (char *)NULL);
                }
 
@@ -1867,7 +1931,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
@@ -1895,8 +1958,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);
 
@@ -1910,7 +1981,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"
@@ -1921,7 +1991,6 @@ static void fcm_usage(void)
 
 static void fcm_sig(int sig)
 {
-       fcm_dcbd_shutdown();
        sa_select_exit();
 }
 
@@ -1953,6 +2022,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;
@@ -1979,9 +2359,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;
@@ -2040,6 +2417,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();
@@ -2048,6 +2426,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);

-- 
Signature: Lucy Liu <[email protected]>
_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel

Reply via email to