commit 9e808edcbdb6c8915c9cbaaaa32678081b3867d2 Author: Chris Leech Date: Fri Aug 13 16:19:10 2010 -0700 fcoe-utils: FIP VLAN discovery doesn't work on cable swap to switch This patch pulls in a number of patches from the fcoe-utils project at open-fcoe.org to fix the re-discovery of the correct VLAN interface in the case where a cable is swapped and the new switch port is advertising a new VLAN ID for FCoE traffic. This patch combines the following patches from openfc/fcoe-utils: - fcoemon: 0 is a valid file descriptor number 7a6bbdcb685a9c6f4e82cd9894398b6efe8e77e8 - fcoemon: close fip socket and cancel timers when stopping VLAN discovery 6ccccda68c7c9175a1c623993fcc27bba059bfac - fcoemon: don't clear DCB query setting on VLAN link up ee0688c60858b3ba5e9d9032b01bd32f833f7c57 - fcoemon: behavior of auto VLAN interfaces on link events 759be4cda78bfe7feb255aca634ffc36c4149b5a - fcoemon: disable interface on DCB error, without waiting for retry bbd86b94a819bcbc1419517f19747828743cccec - fcoe-utils: fix swapped defines for ALL_FCF_MACS and ALL_ENODE_MACS 94608934568bd2389da39863ab58c56b24cf4daf - fcoe-utils: fix broken error logging (no decode of errno) 225e81b31ac4d9a43b9df888a0921085a0ef8e00 - fcoeadm: remove check for running fcoemon 80287ee72ab37a973c2b14a5379b7d5e09cbbe2f - fcoeadm: don't check so much before sending a command to fcoemon aa45138620bcfda4d12455fd48c7559a5a441b25 - fcoemon: saner behavior when mixing VLAN discovery and fcoeadm commands f204823045b913f895f8520ceb713b2d68aa983d - fcoe-utils: replace "dcbd" with "lldpad" in log message 6bb20e05a3bebb125dd0e37baca50fa77a2cb7d5 - fcoe-utils: make a clear error log message to indicate failure reason 10b19b3cef2ceabee70ff1ae50567913bfa6e935 - fcoemon: use daemon(3) 5487b59205d72e0ad6b692718311047a4ea91eb1 diff --git a/fcoeadm.c b/fcoeadm.c index 0498e27..779b8d1 100644 --- a/fcoeadm.c +++ b/fcoeadm.c @@ -65,19 +65,6 @@ static void fcoeadm_help(void) "\t [-h|--help]\n\n", progname); } -static enum fcoe_err fcoeadm_check_fcoemon() -{ - int fd; - - fd = open(CLIF_PID_FILE, O_RDWR, S_IRUSR | S_IWUSR); - if (fd < 0) - return ENOMONCONN; - - close(fd); - - return NOERR; -} - static enum fcoe_err fcoeadm_clif_request(struct clif_sock_info *clif_info, const struct clif_data *cmd, size_t cmd_len, char *reply, @@ -237,11 +224,6 @@ int main(int argc, char *argv[]) goto err; } - /* Check if fcoemon is running */ - rc = fcoeadm_check_fcoemon(); - if (rc) - goto err; - opt = getopt_long(argc, argv, optstring, fcoeadm_opts, NULL); if (opt != -1) { switch (opt) { @@ -263,17 +245,7 @@ int main(int argc, char *argv[]) } ifname = optarg; - - if (opt == 'c') { - rc = fcoe_validate_interface(ifname); - if (!rc && - !fcoe_validate_fcoe_conn(ifname)) - rc = EFCOECONN; - } else - rc = fcoe_validate_fcoe_conn(ifname); - - if (!rc) - rc = fcoeadm_action(cmd, ifname); + rc = fcoeadm_action(cmd, ifname); break; case 'i': diff --git a/fcoeadm_display.c b/fcoeadm_display.c index 3d80082..cd06f95 100644 --- a/fcoeadm_display.c +++ b/fcoeadm_display.c @@ -503,7 +503,7 @@ get_device_capacity_v2(HBA_HANDLE hba_handle, &slen); if ((status == HBA_STATUS_OK) && (sstat == SCSI_ST_GOOD)) return HBA_STATUS_OK; - if ((sstat == SCSI_ST_CHECK) && (sense[2] == 0x06)) + if (sstat == SCSI_ST_CHECK) continue; fprintf(stderr, "%s: HBA_ScsiReadCapacityV2 failed, " @@ -1368,6 +1368,10 @@ enum fcoe_err display_target_info(const char *ifname, &hba_table[i].hba_attrs, &rport_attrs); + if (hba_table[i].port_attrs.PortState != + HBA_PORTSTATE_ONLINE) + continue; + /* * This will print the LUN table * under the target. diff --git a/fcoemon.c b/fcoemon.c index 42ad99e..8170651 100644 --- a/fcoemon.c +++ b/fcoemon.c @@ -119,6 +119,7 @@ struct fcoe_port { int fcoe_enable; int dcb_required; int auto_vlan; + int auto_created; /* following track data required to manage FCoE interface state */ enum fcp_action action; /* current state */ @@ -295,6 +296,7 @@ static struct fcoe_port *alloc_fcoe_port(char *ifname) * that the interface is not created yet. */ p->last_action = FCP_DESTROY_IF; + p->fip_socket = -1; sa_timer_init(&p->vlan_disc_timer, fcm_vlan_disc_timeout, p); } @@ -497,10 +499,11 @@ static int fcm_link_init(void) static struct fcoe_port *fcm_port_create(char *ifname, int cmd); -void fcm_new_vlan(int ifindex, int vid) +struct fcoe_port *fcm_new_vlan(int ifindex, int vid) { char real_name[IFNAMSIZ]; char vlan_name[IFNAMSIZ]; + struct fcoe_port *p; FCM_LOG_DBG("Auto VLAN Found FCF on VID %d\n", vid); @@ -510,7 +513,12 @@ void fcm_new_vlan(int ifindex, int vid) vlan_create(ifindex, vid, vlan_name); } rtnl_set_iff_up(0, vlan_name); - fcm_port_create(vlan_name, FCP_CREATE_IF); + p = fcm_find_fcoe_port(vlan_name, FCP_CFG_IFNAME); + if (p && !p->fcoe_enable) + return p; + p = fcm_port_create(vlan_name, FCP_ACTIVATE_IF); + p->auto_created = 1; + return p; } @@ -520,8 +528,8 @@ int fcm_vlan_disc_handler(struct fiphdr *fh, struct sockaddr_ll *sa, void *arg) unsigned char mac[ETHER_ADDR_LEN]; int len = ntohs(fh->fip_desc_len); struct fip_tlv_hdr *tlv = (struct fip_tlv_hdr *)(fh + 1); - char ifname[IFNAMSIZ]; - struct fcoe_port *p; + struct fcoe_port *p = arg; + struct fcoe_port *vp; if (ntohs(fh->fip_proto) != FIP_PROTO_VLAN) return -1; @@ -530,10 +538,6 @@ int fcm_vlan_disc_handler(struct fiphdr *fh, struct sockaddr_ll *sa, void *arg) return -1; /* cancel the retry timer, response received */ - rtnl_get_linkname(sa->sll_ifindex, ifname); - p = fcm_find_fcoe_port(ifname, FCP_CFG_IFNAME); - if (!p) - return -ENODEV; sa_timer_cancel(&p->vlan_disc_timer); while (len > 0) { @@ -552,7 +556,8 @@ int fcm_vlan_disc_handler(struct fiphdr *fh, struct sockaddr_ll *sa, void *arg) break; } vid = ntohs(((struct fip_tlv_vlan *)tlv)->vlan); - fcm_new_vlan(sa->sll_ifindex, vid); + vp = fcm_new_vlan(sa->sll_ifindex, vid); + vp->dcb_required = p->dcb_required; break; default: /* unexpected or unrecognized descriptor */ @@ -568,7 +573,7 @@ int fcm_vlan_disc_handler(struct fiphdr *fh, struct sockaddr_ll *sa, void *arg) static void fcm_fip_recv(void *arg) { struct fcoe_port *p = arg; - fip_recv(p->fip_socket, fcm_vlan_disc_handler, NULL); + fip_recv(p->fip_socket, fcm_vlan_disc_handler, p); } static int fcm_vlan_disc_socket(struct fcoe_port *p) @@ -748,7 +753,7 @@ static void fcp_set_next_action(struct fcoe_port *p, enum fcp_action action) switch (action) { case FCP_ACTIVATE_IF: if (p->auto_vlan) - p->action = FCP_WAIT; + p->action = FCP_VLAN_DISC; else p->action = FCP_CREATE_IF; break; @@ -756,6 +761,12 @@ static void fcp_set_next_action(struct fcoe_port *p, enum fcp_action action) case FCP_DISABLE_IF: case FCP_RESET_IF: case FCP_SCAN_IF: + if (p->fip_socket >= 0) { + sa_timer_cancel(&p->vlan_disc_timer); + sa_select_rem_fd(p->fip_socket); + close(p->fip_socket); + p->fip_socket = -1; + } p->action = action; break; default: @@ -775,8 +786,22 @@ static void fcp_action_set(char *ifname, enum fcp_action action) p = fcm_find_fcoe_port(ifname, FCP_REAL_IFNAME); while (p) { - if (p->fcoe_enable) - fcp_set_next_action(p, action); + if (p->fcoe_enable) { + switch (action) { + case FCP_ACTIVATE_IF: + /* + * let the VLAN discovery code + * enabled auto-VLANs + */ + if (!p->auto_created) + fcp_set_next_action(p, FCP_ACTIVATE_IF); + else + fcp_set_next_action(p, FCP_WAIT); + break; + default: + fcp_set_next_action(p, action); + } + } p = fcm_find_next_fcoe_port(p, ifname); } } @@ -813,7 +838,7 @@ static void fcm_dcbd_state_set(struct fcm_netif *ff, if (new_state == FCD_ERROR) { ff->dcbd_retry_cnt++; - FCM_LOG_DEV_DBG(ff, "%s: SETTING dcbd RETRY TIMER = %d\n", + FCM_LOG_DEV_DBG(ff, "%s: SETTING lldpad RETRY TIMER = %d\n", ff->ifname, ff->dcbd_retry_cnt * DCBD_REQ_RETRY_TIMEOUT); sa_timer_set(&ff->dcbd_retry_timer, @@ -859,16 +884,20 @@ static void update_fcoe_port_state(struct fcoe_port *p, unsigned int type, * called for a real interface and the FCoE * interface is configured on a VLAN. */ - if ((t == FCP_REAL_IFNAME) && + if (!((t == FCP_REAL_IFNAME) && strncmp(p->ifname, p->real_ifname, - IFNAMSIZ)) - fcm_dcbd_state_set(ff, FCD_INIT); - else + IFNAMSIZ))) fcm_dcbd_state_set(ff, FCD_GET_DCB_STATE); } else { - fcp_set_next_action(p, FCP_CREATE_IF); + /* hold off on auto-created VLAN ports until + * VLAN discovery can validate that the setup + * has not changed */ + if (!p->auto_created) + fcp_set_next_action(p, FCP_ACTIVATE_IF); } + } else { + fcp_set_next_action(p, FCP_DISABLE_IF); } } else { fcp_set_next_action(p, FCP_DESTROY_IF); @@ -1186,14 +1215,14 @@ static int fcm_dcbd_connect(void) LLDP_CLIF_SOCK); rc = connect(fd, (struct sockaddr *)&dest, sizeof(dest)); if (rc < 0) { - FCM_LOG_ERR(errno, "clif connect failed"); + FCM_LOG_ERR(errno, "Failed to connect to lldpad"); unlink(lp->sun_path); close(fd); return 0; } fcm_clif->cl_fd = fd; sa_select_add_fd(fd, fcm_dcbd_rx, NULL, NULL, fcm_clif); - FCM_LOG_DBG("connected to dcbd"); + FCM_LOG_DBG("connected to lldpad"); return 1; } @@ -1219,7 +1248,7 @@ static void fcm_dcbd_retry_timeout(void *arg) struct fcm_netif *ff = (struct fcm_netif *)arg; ASSERT(ff); - FCM_LOG_DBG("%s: dcbd retry TIMEOUT occurred [%d]", + FCM_LOG_DBG("%s: lldpad retry TIMEOUT occurred [%d]", ff->ifname, ff->dcbd_retry_cnt); fcm_dcbd_state_set(ff, FCD_GET_DCB_STATE); @@ -1236,13 +1265,13 @@ static void fcm_dcbd_disconnect(void) fcm_clif->cl_fd = -1; /* mark as disconnected */ fcm_clif->cl_busy = 0; fcm_clif->cl_ping_pending = 0; - FCM_LOG_DBG("Disconnected from dcbd"); + FCM_LOG_DBG("Disconnected from lldpad"); } } static void fcm_dcbd_shutdown(void) { - FCM_LOG_DBG("Shutdown dcbd connection\n"); + FCM_LOG_DBG("Shutdown lldpad connection\n"); fcm_dcbd_request("D"); /* DETACH_CMD */ fcm_dcbd_disconnect(); unlink(fcm_pidfile); @@ -1315,11 +1344,11 @@ static void fcm_dcbd_rx(void *arg) st = fcm_get_hex(buf + CLIF_STAT_OFF, CLIF_STAT_LEN, &ep); if (ep != NULL) - FCM_LOG("unexpected response code from dcbd: " + FCM_LOG("unexpected response code from lldpad: " "len %d buf %s rc %d", len, buf, rc); else if (st != cmd_success && st != cmd_device_not_found) { - FCM_LOG("error response from dcbd: " + FCM_LOG("error response from lldpad: " "error %d len %d %s", st, len, buf); } @@ -1341,7 +1370,7 @@ static void fcm_dcbd_rx(void *arg) break; default: FCM_LOG("Unexpected cmd in response " - "from dcbd: len %d %s", + "from lldpad: len %d %s", len, buf); break; } @@ -1351,7 +1380,7 @@ static void fcm_dcbd_rx(void *arg) fcm_dcbd_event(buf, len); break; default: - FCM_LOG("Unexpected message from dcbd: len %d buf %s", + FCM_LOG("Unexpected message from lldpad: len %d buf %s", len, buf); break; } @@ -1982,7 +2011,7 @@ void fcm_vlan_disc_timeout(void *arg) int fcm_start_vlan_disc(struct fcoe_port *p) { int s; - if (!p->fip_socket) { + if (p->fip_socket < 0) { s = fcm_vlan_disc_socket(p); if (s < 0) return s; @@ -2002,6 +2031,7 @@ int fcm_start_vlan_disc(struct fcoe_port *p) */ static void fcm_fcoe_action(struct fcm_netif *ff, struct fcoe_port *p) { + struct fcoe_port *vp; char *ifname = p->ifname; char fchost[FCHOSTBUFLEN]; char path[256]; @@ -2015,6 +2045,17 @@ static void fcm_fcoe_action(struct fcm_netif *ff, struct fcoe_port *p) break; case FCP_DESTROY_IF: FCM_LOG_DBG("OP: DESTROY %s\n", p->ifname); + if (p->auto_vlan) { + /* destroy all the VLANs */ + vp = fcm_find_fcoe_port(p->ifname, FCP_REAL_IFNAME); + while (vp) { + if (vp->auto_created) + fcp_set_next_action(vp, FCP_DESTROY_IF); + vp = fcm_find_next_fcoe_port(vp, p->ifname); + } + rc = fcm_success; + break; + } rc = fcm_fcoe_if_action(FCOE_DESTROY, ifname); break; case FCP_ENABLE_IF: @@ -2023,6 +2064,16 @@ static void fcm_fcoe_action(struct fcm_netif *ff, struct fcoe_port *p) break; case FCP_DISABLE_IF: FCM_LOG_DBG("OP: DISABLE %s\n", p->ifname); + if (p->auto_vlan) { + /* disable all the VLANs */ + vp = fcm_find_fcoe_port(p->ifname, FCP_REAL_IFNAME); + while (vp) { + if (vp->auto_created) + fcp_set_next_action(vp, FCP_DISABLE_IF); + vp = fcm_find_next_fcoe_port(vp, p->ifname); + } + break; + } rc = fcm_fcoe_if_action(FCOE_DISABLE, ifname); break; case FCP_RESET_IF: @@ -2165,12 +2216,11 @@ static void fcm_netif_advance(struct fcm_netif *ff) fcm_dcbd_state_set(ff, FCD_INIT); break; case FCP_ERROR: - if (ff->dcbd_retry_cnt < DCBD_MAX_REQ_RETRIES) { + fcp_action_set(ff->ifname, FCP_DISABLE_IF); + if (ff->dcbd_retry_cnt < DCBD_MAX_REQ_RETRIES) fcm_dcbd_state_set(ff, FCD_ERROR); - } else { - fcp_action_set(ff->ifname, FCP_DISABLE_IF); + else fcm_dcbd_state_set(ff, FCD_INIT); - } break; case FCP_WAIT: default: @@ -2333,8 +2383,22 @@ static struct fcoe_port *fcm_port_create(char *ifname, int cmd) static int fcm_cli_create(char *ifname, int cmd, struct sock_info **r) { - struct fcoe_port *p; + struct fcoe_port *p, *vp; + p = fcm_find_fcoe_port(ifname, FCP_CFG_IFNAME); + if (p && p->fcoe_enable) { + /* no action needed */ + return CLI_NO_ACTION; + } + /* re-enable previous VLANs */ + if (p && p->auto_vlan) { + vp = fcm_find_fcoe_port(p->ifname, FCP_REAL_IFNAME); + while (vp) { + if (vp->auto_created) + vp->fcoe_enable = 1; + vp = fcm_find_next_fcoe_port(vp, p->ifname); + } + } p = fcm_port_create(ifname, cmd); if (!p) return fcm_fail; @@ -2553,7 +2617,7 @@ int main(int argc, char **argv) sa_log_flags = 0; openlog(sa_log_prefix, LOG_CONS, LOG_DAEMON); - while ((c = getopt_long(argc, argv, "fdhv", + while ((c = getopt_long(argc, argv, "fdhsv", fcm_options, NULL)) != -1) { switch (c) { case 'f': @@ -2579,28 +2643,13 @@ int main(int argc, char **argv) if (argc != optind) fcm_usage(); - if (!fcm_fg) { - pid_t pid, sid; - - pid = fork(); - if (pid < 0) { - FCM_LOG("Starting daemon failed"); - exit(EXIT_FAILURE); - } else if (pid) - exit(EXIT_SUCCESS); - - /* Create a new SID for the child process */ - sid = setsid(); - if (sid < 0) - exit(EXIT_FAILURE); + if (!fcm_fg && daemon(0, !fcoe_config.use_syslog)) { + FCM_LOG("Starting daemon failed"); + exit(EXIT_FAILURE); } umask(0); - /* Change the current working directory */ - if ((chdir("/")) < 0) - exit(EXIT_FAILURE); - /* * Set up for signals. */ diff --git a/fcrls.c b/fcrls.c index 026dbd5..64d0bc9 100644 --- a/fcrls.c +++ b/fcrls.c @@ -395,7 +395,8 @@ static int rport_find(struct rport_info *rpi) return ENODEV; } while (n--) { - if (namelist[n]->d_type != DT_DIR) + if ((namelist[n]->d_type != DT_DIR) && + (namelist[n]->d_type != DT_LNK)) goto free_name; if (rport_parse(namelist[n]->d_name, &rpii)) goto free_name; diff --git a/include/fip.h b/include/fip.h index ae8a365..2b00b7c 100644 --- a/include/fip.h +++ b/include/fip.h @@ -27,8 +27,8 @@ #define ETH_P_FIP 0x8914 #define FIP_ALL_FCOE_MACS { 0x01, 0x10, 0x18, 0x01, 0x00, 0x00 } -#define FIP_ALL_FCF_MACS { 0x01, 0x10, 0x18, 0x01, 0x00, 0x01 } -#define FIP_ALL_ENODE_MACS { 0x01, 0x10, 0x18, 0x01, 0x00, 0x02 } +#define FIP_ALL_ENODE_MACS { 0x01, 0x10, 0x18, 0x01, 0x00, 0x01 } +#define FIP_ALL_FCF_MACS { 0x01, 0x10, 0x18, 0x01, 0x00, 0x02 } struct fiphdr { uint8_t fip_version; /* version, upper 4 bits only */ diff --git a/lib/sa_log.c b/lib/sa_log.c index 91c256f..498b08b 100644 --- a/lib/sa_log.c +++ b/lib/sa_log.c @@ -17,6 +17,7 @@ * Maintained at www.Open-FCoE.org */ +#define _GNU_SOURCE /* for GNU definition of strerror_r */ #include "fcoemon_utils.h" #include "net_types.h" #include "fc_types.h"