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
