Add socket server interface into fcoemon. In fcoemon.c/h, create socket
interface and receive function using sa_loop_select. 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 |  349 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 fcoemon.h |   20 +++
 2 files changed, 363 insertions(+), 6 deletions(-)

diff --git a/fcoemon.c b/fcoemon.c
index aff2e5e..0b7b161 100644
--- a/fcoemon.c
+++ b/fcoemon.c
@@ -75,7 +75,6 @@
 #define VLAN_DIR                "/proc/net/vlan"
 
 #define CLIF_NAME_PATH          _PATH_VARRUN "dcbd/clif"
-#define CLIF_PID_FILE           _PATH_VARRUN "fcoemon.pid"
 #define CLIF_LOCAL_SUN_PATH     _PATH_TMP "fcoemon.dcbd.%d"
 #define DCBD_CONNECT_TIMEOUT    (10 * 1000 * 1000)     /* 10 seconds */
 #define DCBD_CONNECT_RETRY_TIMEOUT   (1 * 1000 * 1000) /* 1 seconds */
@@ -96,6 +95,8 @@ enum fcm_srv_status {
        fcm_no_action
 };
 
+static struct fcm_srv_data *srv_data;
+
 /*
  * fcoe service configuration data
  * Note: These information are read in from the fcoe service
@@ -115,6 +116,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 {
@@ -124,8 +126,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.
  */
@@ -1615,6 +1615,7 @@ static void fcm_dcbd_event(char *msg, size_t len)
                        break;
                p = fcm_find_next_fcoe_port(p, ff->ifname);
        }
+
        /*
         * dcb is not required or link was removed, ignore dcbd event
        */
@@ -1659,6 +1660,14 @@ 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;
@@ -1720,8 +1729,10 @@ static void fcm_fcoe_action(struct fcm_netif *ff, struct 
fcoe_port *p)
                break;
        case FCP_RESET_IF:
                FCM_LOG_DBG("OP: RESET\n");
-               if (fcoeclif_validate_interface(ifname, fchost, FCHOSTBUFLEN))
+               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;
@@ -1730,6 +1741,12 @@ static void fcm_fcoe_action(struct fcm_netif *ff, struct 
fcoe_port *p)
                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;
 
@@ -1913,7 +1930,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
@@ -1941,8 +1957,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);
 
@@ -1998,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;
@@ -2092,6 +2427,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();
@@ -2100,6 +2436,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