aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe
diff options
context:
space:
mode:
authorJoe Eykholt <jeykholt@cisco.com>2010-07-20 18:20:30 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-07-28 10:05:56 -0400
commite10f8c667b874a57512c936089092a3d1ef7ab8a (patch)
tree8094610399133fd6e0ad26d23c46ec0a6cc91398 /drivers/scsi/fcoe
parent9b651da900ccfe5581befb46eb06ef781a1d7e74 (diff)
[SCSI] libfcoe: fcoe: fnic: add FIP VN2VN point-to-multipoint support
The FC-BB-6 committee is proposing a new FIP usage model called VN_port to VN_port mode. It allows VN_ports to discover each other over a loss-free L2 Ethernet without any FCF or Fibre-channel fabric services. This is point-to-multipoint. There is also a variant of this called point-to-point which provides for making sure there is just one pair of ports operating over the Ethernet fabric. We add these new states: VNMP_START, _PROBE1, _PROBE2, _CLAIM, and _UP. These usually go quickly in that sequence. After waiting a random amount of time up to 100 ms in START, we select a pseudo-random proposed locally-unique port ID and send out probes in states PROBE1 and PROBE2, 100 ms apart. If no probe responses are heard, we proceed to CLAIM state 400 ms later and send a claim notification. We wait another 400 ms to receive claim responses, which give us a list of the other nodes on the network, including their FC-4 capabilities. After another 400 ms we go to VNMP_UP state and should start interoperating with any of the nodes for whic we receivec claim responses. More details are in the spec.j Add the new mode as FIP_MODE_VN2VN. The driver must specify explicitly that it wants to operate in this mode. There is no automatic detection between point-to-multipoint and fabric mode, and the local port initialization is affected, so it isn't anticipated that there will ever be any such automatic switchover. It may eventually be possible to have both fabric and VN2VN modes on the same L2 network, which may be done by two separate local VN_ports (lports). When in VN2VN mode, FIP replaces libfc's fabric-oriented discovery module with its own simple code that adds remote ports as they are discovered from incoming claim notifications and responses. These hooks are placed by fcoe_disc_init(). A linear list of discovered vn_ports is maintained under the fcoe_ctlr struct. It is expected to be short for now, and accessed infrequently. It is kept under RCU for lock-ordering reasons. The lport and/or rport mutexes may be held when we need to lookup a fcoe_vnport during an ELS send. Change fcoe_ctlr_encaps() to lookup the destination vn_port in the list of peers for the destination MAC address of the FIP-encapsulated frame. Add a new function fcoe_disc_init() to initialize just the discovery portion of libfcoe for VN2VN mode. Signed-off-by: Joe Eykholt <jeykholt@cisco.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/fcoe')
-rw-r--r--drivers/scsi/fcoe/fcoe.c16
-rw-r--r--drivers/scsi/fcoe/libfcoe.c1075
2 files changed, 1029 insertions, 62 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 9d64e08305c7..216aba375fe1 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -315,7 +315,11 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe,
315 dev_uc_add(netdev, flogi_maddr); 315 dev_uc_add(netdev, flogi_maddr);
316 if (fip->spma) 316 if (fip->spma)
317 dev_uc_add(netdev, fip->ctl_src_addr); 317 dev_uc_add(netdev, fip->ctl_src_addr);
318 dev_mc_add(netdev, FIP_ALL_ENODE_MACS); 318 if (fip->mode == FIP_MODE_VN2VN) {
319 dev_mc_add(netdev, FIP_ALL_VN2VN_MACS);
320 dev_mc_add(netdev, FIP_ALL_P2P_MACS);
321 } else
322 dev_mc_add(netdev, FIP_ALL_ENODE_MACS);
319 323
320 /* 324 /*
321 * setup the receive function from ethernet driver 325 * setup the receive function from ethernet driver
@@ -401,7 +405,11 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
401 dev_uc_del(netdev, flogi_maddr); 405 dev_uc_del(netdev, flogi_maddr);
402 if (fip->spma) 406 if (fip->spma)
403 dev_uc_del(netdev, fip->ctl_src_addr); 407 dev_uc_del(netdev, fip->ctl_src_addr);
404 dev_mc_del(netdev, FIP_ALL_ENODE_MACS); 408 if (fip->mode == FIP_MODE_VN2VN) {
409 dev_mc_del(netdev, FIP_ALL_VN2VN_MACS);
410 dev_mc_del(netdev, FIP_ALL_P2P_MACS);
411 } else
412 dev_mc_del(netdev, FIP_ALL_ENODE_MACS);
405 413
406 /* Tell the LLD we are done w/ FCoE */ 414 /* Tell the LLD we are done w/ FCoE */
407 ops = netdev->netdev_ops; 415 ops = netdev->netdev_ops;
@@ -967,7 +975,7 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
967 } 975 }
968 976
969 /* Initialize the library */ 977 /* Initialize the library */
970 rc = fcoe_libfc_config(lport, &fcoe_libfc_fcn_templ); 978 rc = fcoe_libfc_config(lport, &fcoe->ctlr, &fcoe_libfc_fcn_templ, 1);
971 if (rc) { 979 if (rc) {
972 FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the " 980 FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the "
973 "interface\n"); 981 "interface\n");
@@ -2533,6 +2541,8 @@ static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, u32 did,
2533 switch (op) { 2541 switch (op) {
2534 case ELS_FLOGI: 2542 case ELS_FLOGI:
2535 case ELS_FDISC: 2543 case ELS_FDISC:
2544 if (lport->point_to_multipoint)
2545 break;
2536 return fc_elsct_send(lport, did, fp, op, fcoe_flogi_resp, 2546 return fc_elsct_send(lport, did, fp, op, fcoe_flogi_resp,
2537 fip, timeout); 2547 fip, timeout);
2538 case ELS_LOGO: 2548 case ELS_LOGO:
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index 11f3db5e506b..79df78f2b085 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -39,6 +39,7 @@
39#include <scsi/fc/fc_fip.h> 39#include <scsi/fc/fc_fip.h>
40#include <scsi/fc/fc_encaps.h> 40#include <scsi/fc/fc_encaps.h>
41#include <scsi/fc/fc_fcoe.h> 41#include <scsi/fc/fc_fcoe.h>
42#include <scsi/fc/fc_fcp.h>
42 43
43#include <scsi/libfc.h> 44#include <scsi/libfc.h>
44#include <scsi/libfcoe.h> 45#include <scsi/libfcoe.h>
@@ -54,7 +55,15 @@ static void fcoe_ctlr_timeout(unsigned long);
54static void fcoe_ctlr_timer_work(struct work_struct *); 55static void fcoe_ctlr_timer_work(struct work_struct *);
55static void fcoe_ctlr_recv_work(struct work_struct *); 56static void fcoe_ctlr_recv_work(struct work_struct *);
56 57
58static void fcoe_ctlr_vn_start(struct fcoe_ctlr *);
59static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *);
60static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *);
61static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *, u32, u8 *);
62
57static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS; 63static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS;
64static u8 fcoe_all_enode[ETH_ALEN] = FIP_ALL_ENODE_MACS;
65static u8 fcoe_all_vn2vn[ETH_ALEN] = FIP_ALL_VN2VN_MACS;
66static u8 fcoe_all_p2p[ETH_ALEN] = FIP_ALL_P2P_MACS;
58 67
59unsigned int libfcoe_debug_logging; 68unsigned int libfcoe_debug_logging;
60module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR); 69module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR);
@@ -86,6 +95,11 @@ static const char *fcoe_ctlr_states[] = {
86 [FIP_ST_AUTO] = "AUTO", 95 [FIP_ST_AUTO] = "AUTO",
87 [FIP_ST_NON_FIP] = "NON_FIP", 96 [FIP_ST_NON_FIP] = "NON_FIP",
88 [FIP_ST_ENABLED] = "ENABLED", 97 [FIP_ST_ENABLED] = "ENABLED",
98 [FIP_ST_VNMP_START] = "VNMP_START",
99 [FIP_ST_VNMP_PROBE1] = "VNMP_PROBE1",
100 [FIP_ST_VNMP_PROBE2] = "VNMP_PROBE2",
101 [FIP_ST_VNMP_CLAIM] = "VNMP_CLAIM",
102 [FIP_ST_VNMP_UP] = "VNMP_UP",
89}; 103};
90 104
91static const char *fcoe_ctlr_state(enum fip_state state) 105static const char *fcoe_ctlr_state(enum fip_state state)
@@ -295,11 +309,25 @@ void fcoe_ctlr_link_up(struct fcoe_ctlr *fip)
295 fc_linkup(fip->lp); 309 fc_linkup(fip->lp);
296 } else if (fip->state == FIP_ST_LINK_WAIT) { 310 } else if (fip->state == FIP_ST_LINK_WAIT) {
297 fcoe_ctlr_set_state(fip, fip->mode); 311 fcoe_ctlr_set_state(fip, fip->mode);
298 mutex_unlock(&fip->ctlr_mutex); 312 switch (fip->mode) {
299 if (fip->state == FIP_ST_AUTO) 313 default:
314 LIBFCOE_FIP_DBG(fip, "invalid mode %d\n", fip->mode);
315 /* fall-through */
316 case FIP_MODE_AUTO:
300 LIBFCOE_FIP_DBG(fip, "%s", "setting AUTO mode.\n"); 317 LIBFCOE_FIP_DBG(fip, "%s", "setting AUTO mode.\n");
301 fc_linkup(fip->lp); 318 /* fall-through */
302 fcoe_ctlr_solicit(fip, NULL); 319 case FIP_MODE_FABRIC:
320 case FIP_MODE_NON_FIP:
321 mutex_unlock(&fip->ctlr_mutex);
322 fc_linkup(fip->lp);
323 fcoe_ctlr_solicit(fip, NULL);
324 break;
325 case FIP_MODE_VN2VN:
326 fcoe_ctlr_vn_start(fip);
327 mutex_unlock(&fip->ctlr_mutex);
328 fc_linkup(fip->lp);
329 break;
330 }
303 } else 331 } else
304 mutex_unlock(&fip->ctlr_mutex); 332 mutex_unlock(&fip->ctlr_mutex);
305} 333}
@@ -423,6 +451,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip,
423 * @fip: The FCoE controller for the ELS frame 451 * @fip: The FCoE controller for the ELS frame
424 * @dtype: The FIP descriptor type for the frame 452 * @dtype: The FIP descriptor type for the frame
425 * @skb: The FCoE ELS frame including FC header but no FCoE headers 453 * @skb: The FCoE ELS frame including FC header but no FCoE headers
454 * @d_id: The destination port ID.
426 * 455 *
427 * Returns non-zero error code on failure. 456 * Returns non-zero error code on failure.
428 * 457 *
@@ -433,7 +462,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip,
433 * Ethernet header. The tailroom is for the FIP MAC descriptor. 462 * Ethernet header. The tailroom is for the FIP MAC descriptor.
434 */ 463 */
435static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, 464static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport,
436 u8 dtype, struct sk_buff *skb) 465 u8 dtype, struct sk_buff *skb, u32 d_id)
437{ 466{
438 struct fip_encaps_head { 467 struct fip_encaps_head {
439 struct ethhdr eth; 468 struct ethhdr eth;
@@ -445,21 +474,24 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport,
445 size_t dlen; 474 size_t dlen;
446 u16 fip_flags; 475 u16 fip_flags;
447 476
448 fcf = fip->sel_fcf;
449 if (!fcf)
450 return -ENODEV;
451
452 /* set flags according to both FCF and lport's capability on SPMA */
453 fip_flags = fcf->flags;
454 fip_flags &= fip->spma ? FIP_FL_SPMA | FIP_FL_FPMA : FIP_FL_FPMA;
455 if (!fip_flags)
456 return -ENODEV;
457
458 dlen = sizeof(struct fip_encaps) + skb->len; /* len before push */ 477 dlen = sizeof(struct fip_encaps) + skb->len; /* len before push */
459 cap = (struct fip_encaps_head *)skb_push(skb, sizeof(*cap)); 478 cap = (struct fip_encaps_head *)skb_push(skb, sizeof(*cap));
460
461 memset(cap, 0, sizeof(*cap)); 479 memset(cap, 0, sizeof(*cap));
462 memcpy(cap->eth.h_dest, fcf->fcf_mac, ETH_ALEN); 480
481 if (lport->point_to_multipoint) {
482 if (fcoe_ctlr_vn_lookup(fip, d_id, cap->eth.h_dest))
483 return -ENODEV;
484 } else {
485 fcf = fip->sel_fcf;
486 if (!fcf)
487 return -ENODEV;
488 fip_flags = fcf->flags;
489 fip_flags &= fip->spma ? FIP_FL_SPMA | FIP_FL_FPMA :
490 FIP_FL_FPMA;
491 if (!fip_flags)
492 return -ENODEV;
493 memcpy(cap->eth.h_dest, fcf->fcf_mac, ETH_ALEN);
494 }
463 memcpy(cap->eth.h_source, fip->ctl_src_addr, ETH_ALEN); 495 memcpy(cap->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
464 cap->eth.h_proto = htons(ETH_P_FIP); 496 cap->eth.h_proto = htons(ETH_P_FIP);
465 497
@@ -503,19 +535,22 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport,
503 * 535 *
504 * The caller must check that the length is a multiple of 4. 536 * The caller must check that the length is a multiple of 4.
505 * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes). 537 * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes).
538 * The the skb must also be an fc_frame.
506 */ 539 */
507int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, 540int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
508 struct sk_buff *skb) 541 struct sk_buff *skb)
509{ 542{
543 struct fc_frame *fp;
510 struct fc_frame_header *fh; 544 struct fc_frame_header *fh;
511 u16 old_xid; 545 u16 old_xid;
512 u8 op; 546 u8 op;
513 u8 mac[ETH_ALEN]; 547 u8 mac[ETH_ALEN];
514 548
549 fp = container_of(skb, struct fc_frame, skb);
515 fh = (struct fc_frame_header *)skb->data; 550 fh = (struct fc_frame_header *)skb->data;
516 op = *(u8 *)(fh + 1); 551 op = *(u8 *)(fh + 1);
517 552
518 if (op == ELS_FLOGI) { 553 if (op == ELS_FLOGI && fip->mode != FIP_MODE_VN2VN) {
519 old_xid = fip->flogi_oxid; 554 old_xid = fip->flogi_oxid;
520 fip->flogi_oxid = ntohs(fh->fh_ox_id); 555 fip->flogi_oxid = ntohs(fh->fh_ox_id);
521 if (fip->state == FIP_ST_AUTO) { 556 if (fip->state == FIP_ST_AUTO) {
@@ -533,9 +568,8 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
533 568
534 if (fip->state == FIP_ST_NON_FIP) 569 if (fip->state == FIP_ST_NON_FIP)
535 return 0; 570 return 0;
536 if (!fip->sel_fcf) 571 if (!fip->sel_fcf && fip->mode != FIP_MODE_VN2VN)
537 goto drop; 572 goto drop;
538
539 switch (op) { 573 switch (op) {
540 case ELS_FLOGI: 574 case ELS_FLOGI:
541 op = FIP_DT_FLOGI; 575 op = FIP_DT_FLOGI;
@@ -546,36 +580,49 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
546 op = FIP_DT_FDISC; 580 op = FIP_DT_FDISC;
547 break; 581 break;
548 case ELS_LOGO: 582 case ELS_LOGO:
549 if (fip->state != FIP_ST_ENABLED) 583 if (fip->mode == FIP_MODE_VN2VN) {
550 return 0; 584 if (fip->state != FIP_ST_VNMP_UP)
551 if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI) 585 return -EINVAL;
552 return 0; 586 if (ntoh24(fh->fh_d_id) == FC_FID_FLOGI)
587 return -EINVAL;
588 } else {
589 if (fip->state != FIP_ST_ENABLED)
590 return 0;
591 if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI)
592 return 0;
593 }
553 op = FIP_DT_LOGO; 594 op = FIP_DT_LOGO;
554 break; 595 break;
555 case ELS_LS_ACC: 596 case ELS_LS_ACC:
556 if (fip->flogi_oxid == FC_XID_UNKNOWN)
557 return 0;
558 if (!ntoh24(fh->fh_s_id))
559 return 0;
560 if (fip->state == FIP_ST_AUTO)
561 return 0;
562 /* 597 /*
563 * Here we must've gotten an SID by accepting an FLOGI 598 * If non-FIP, we may have gotten an SID by accepting an FLOGI
564 * from a point-to-point connection. Switch to using 599 * from a point-to-point connection. Switch to using
565 * the source mac based on the SID. The destination 600 * the source mac based on the SID. The destination
566 * MAC in this case would have been set by receving the 601 * MAC in this case would have been set by receving the
567 * FLOGI. 602 * FLOGI.
568 */ 603 */
569 fip->flogi_oxid = FC_XID_UNKNOWN; 604 if (fip->state == FIP_ST_NON_FIP) {
570 fc_fcoe_set_mac(mac, fh->fh_d_id); 605 if (fip->flogi_oxid == FC_XID_UNKNOWN)
571 fip->update_mac(lport, mac); 606 return 0;
607 fip->flogi_oxid = FC_XID_UNKNOWN;
608 fc_fcoe_set_mac(mac, fh->fh_d_id);
609 fip->update_mac(lport, mac);
610 }
611 /* fall through */
612 case ELS_LS_RJT:
613 op = fr_encaps(fp);
614 if (op)
615 break;
572 return 0; 616 return 0;
573 default: 617 default:
574 if (fip->state != FIP_ST_ENABLED) 618 if (fip->state != FIP_ST_ENABLED &&
619 fip->state != FIP_ST_VNMP_UP)
575 goto drop; 620 goto drop;
576 return 0; 621 return 0;
577 } 622 }
578 if (fcoe_ctlr_encaps(fip, lport, op, skb)) 623 LIBFCOE_FIP_DBG(fip, "els_send op %u d_id %x\n",
624 op, ntoh24(fh->fh_d_id));
625 if (fcoe_ctlr_encaps(fip, lport, op, skb, ntoh24(fh->fh_d_id)))
579 goto drop; 626 goto drop;
580 fip->send(fip, skb); 627 fip->send(fip, skb);
581 return -EINPROGRESS; 628 return -EINPROGRESS;
@@ -717,8 +764,9 @@ static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip,
717 ((struct fip_mac_desc *)desc)->fd_mac, 764 ((struct fip_mac_desc *)desc)->fd_mac,
718 ETH_ALEN); 765 ETH_ALEN);
719 if (!is_valid_ether_addr(fcf->fcf_mac)) { 766 if (!is_valid_ether_addr(fcf->fcf_mac)) {
720 LIBFCOE_FIP_DBG(fip, "Invalid MAC address " 767 LIBFCOE_FIP_DBG(fip,
721 "in FIP adv\n"); 768 "Invalid MAC addr %pM in FIP adv\n",
769 fcf->fcf_mac);
722 return -EINVAL; 770 return -EINVAL;
723 } 771 }
724 desc_mask &= ~BIT(FIP_DT_MAC); 772 desc_mask &= ~BIT(FIP_DT_MAC);
@@ -944,12 +992,6 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
944 memcpy(granted_mac, 992 memcpy(granted_mac,
945 ((struct fip_mac_desc *)desc)->fd_mac, 993 ((struct fip_mac_desc *)desc)->fd_mac,
946 ETH_ALEN); 994 ETH_ALEN);
947 if (!is_valid_ether_addr(granted_mac)) {
948 LIBFCOE_FIP_DBG(fip, "Invalid MAC address "
949 "in FIP ELS\n");
950 goto drop;
951 }
952 memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN);
953 break; 995 break;
954 case FIP_DT_FLOGI: 996 case FIP_DT_FLOGI:
955 case FIP_DT_FDISC: 997 case FIP_DT_FDISC:
@@ -990,10 +1032,20 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
990 goto drop; 1032 goto drop;
991 els_op = *(u8 *)(fh + 1); 1033 els_op = *(u8 *)(fh + 1);
992 1034
993 if (els_dtype == FIP_DT_FLOGI && sub == FIP_SC_REP && 1035 if ((els_dtype == FIP_DT_FLOGI || els_dtype == FIP_DT_FDISC) &&
994 fip->flogi_oxid == ntohs(fh->fh_ox_id) && 1036 sub == FIP_SC_REP && els_op == ELS_LS_ACC &&
995 els_op == ELS_LS_ACC && is_valid_ether_addr(granted_mac)) 1037 fip->mode != FIP_MODE_VN2VN) {
996 fip->flogi_oxid = FC_XID_UNKNOWN; 1038 if (!is_valid_ether_addr(granted_mac)) {
1039 LIBFCOE_FIP_DBG(fip,
1040 "Invalid MAC address %pM in FIP ELS\n",
1041 granted_mac);
1042 goto drop;
1043 }
1044 memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN);
1045
1046 if (fip->flogi_oxid == ntohs(fh->fh_ox_id))
1047 fip->flogi_oxid = FC_XID_UNKNOWN;
1048 }
997 1049
998 if ((desc_cnt == 0) || ((els_op != ELS_LS_RJT) && 1050 if ((desc_cnt == 0) || ((els_op != ELS_LS_RJT) &&
999 (!(1U << FIP_DT_MAC & desc_mask)))) { 1051 (!(1U << FIP_DT_MAC & desc_mask)))) {
@@ -1012,6 +1064,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
1012 fr_sof(fp) = FC_SOF_I3; 1064 fr_sof(fp) = FC_SOF_I3;
1013 fr_eof(fp) = FC_EOF_T; 1065 fr_eof(fp) = FC_EOF_T;
1014 fr_dev(fp) = lport; 1066 fr_dev(fp) = lport;
1067 fr_encaps(fp) = els_dtype;
1015 1068
1016 stats = per_cpu_ptr(lport->dev_stats, get_cpu()); 1069 stats = per_cpu_ptr(lport->dev_stats, get_cpu());
1017 stats->RxFrames++; 1070 stats->RxFrames++;
@@ -1188,8 +1241,13 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb)
1188 if (skb->len < sizeof(*fiph)) 1241 if (skb->len < sizeof(*fiph))
1189 goto drop; 1242 goto drop;
1190 eh = eth_hdr(skb); 1243 eh = eth_hdr(skb);
1191 if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) && 1244 if (fip->mode == FIP_MODE_VN2VN) {
1192 compare_ether_addr(eh->h_dest, FIP_ALL_ENODE_MACS)) 1245 if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) &&
1246 compare_ether_addr(eh->h_dest, fcoe_all_vn2vn) &&
1247 compare_ether_addr(eh->h_dest, fcoe_all_p2p))
1248 goto drop;
1249 } else if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) &&
1250 compare_ether_addr(eh->h_dest, fcoe_all_enode))
1193 goto drop; 1251 goto drop;
1194 fiph = (struct fip_header *)skb->data; 1252 fiph = (struct fip_header *)skb->data;
1195 op = ntohs(fiph->fip_op); 1253 op = ntohs(fiph->fip_op);
@@ -1209,13 +1267,22 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb)
1209 LIBFCOE_FIP_DBG(fip, "Using FIP mode\n"); 1267 LIBFCOE_FIP_DBG(fip, "Using FIP mode\n");
1210 } 1268 }
1211 mutex_unlock(&fip->ctlr_mutex); 1269 mutex_unlock(&fip->ctlr_mutex);
1212 if (state != FIP_ST_ENABLED) 1270
1271 if (fip->mode == FIP_MODE_VN2VN && op == FIP_OP_VN2VN)
1272 return fcoe_ctlr_vn_recv(fip, skb);
1273
1274 if (state != FIP_ST_ENABLED && state != FIP_ST_VNMP_UP &&
1275 state != FIP_ST_VNMP_CLAIM)
1213 goto drop; 1276 goto drop;
1214 1277
1215 if (op == FIP_OP_LS) { 1278 if (op == FIP_OP_LS) {
1216 fcoe_ctlr_recv_els(fip, skb); /* consumes skb */ 1279 fcoe_ctlr_recv_els(fip, skb); /* consumes skb */
1217 return 0; 1280 return 0;
1218 } 1281 }
1282
1283 if (state != FIP_ST_ENABLED)
1284 goto drop;
1285
1219 if (op == FIP_OP_DISC && sub == FIP_SC_ADV) 1286 if (op == FIP_OP_DISC && sub == FIP_SC_ADV)
1220 fcoe_ctlr_recv_adv(fip, skb); 1287 fcoe_ctlr_recv_adv(fip, skb);
1221 else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK) 1288 else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK)
@@ -1302,7 +1369,8 @@ static void fcoe_ctlr_timer_work(struct work_struct *work)
1302 unsigned long next_timer; 1369 unsigned long next_timer;
1303 1370
1304 fip = container_of(work, struct fcoe_ctlr, timer_work); 1371 fip = container_of(work, struct fcoe_ctlr, timer_work);
1305 1372 if (fip->mode == FIP_MODE_VN2VN)
1373 return fcoe_ctlr_vn_timeout(fip);
1306 mutex_lock(&fip->ctlr_mutex); 1374 mutex_lock(&fip->ctlr_mutex);
1307 if (fip->state == FIP_ST_DISABLED) { 1375 if (fip->state == FIP_ST_DISABLED) {
1308 mutex_unlock(&fip->ctlr_mutex); 1376 mutex_unlock(&fip->ctlr_mutex);
@@ -1340,7 +1408,6 @@ static void fcoe_ctlr_timer_work(struct work_struct *work)
1340 "Starting FCF discovery.\n", 1408 "Starting FCF discovery.\n",
1341 fip->lp->host->host_no); 1409 fip->lp->host->host_no);
1342 reset = 1; 1410 reset = 1;
1343 schedule_work(&fip->timer_work);
1344 } 1411 }
1345 } 1412 }
1346 1413
@@ -1515,26 +1582,916 @@ u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN],
1515EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac); 1582EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac);
1516 1583
1517/** 1584/**
1585 * fcoe_ctlr_rport() - return the fcoe_rport for a given fc_rport_priv
1586 * @rdata: libfc remote port
1587 */
1588static inline struct fcoe_rport *fcoe_ctlr_rport(struct fc_rport_priv *rdata)
1589{
1590 return (struct fcoe_rport *)(rdata + 1);
1591}
1592
1593/**
1594 * fcoe_ctlr_vn_send() - Send a FIP VN2VN Probe Request or Reply.
1595 * @fip: The FCoE controller
1596 * @sub: sub-opcode for probe request, reply, or advertisement.
1597 * @dest: The destination Ethernet MAC address
1598 * @min_len: minimum size of the Ethernet payload to be sent
1599 */
1600static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip,
1601 enum fip_vn2vn_subcode sub,
1602 const u8 *dest, size_t min_len)
1603{
1604 struct sk_buff *skb;
1605 struct fip_frame {
1606 struct ethhdr eth;
1607 struct fip_header fip;
1608 struct fip_mac_desc mac;
1609 struct fip_wwn_desc wwnn;
1610 struct fip_vn_desc vn;
1611 } __attribute__((packed)) *frame;
1612 struct fip_fc4_feat *ff;
1613 struct fip_size_desc *size;
1614 u32 fcp_feat;
1615 size_t len;
1616 size_t dlen;
1617
1618 len = sizeof(*frame);
1619 dlen = 0;
1620 if (sub == FIP_SC_VN_CLAIM_NOTIFY || sub == FIP_SC_VN_CLAIM_REP) {
1621 dlen = sizeof(struct fip_fc4_feat) +
1622 sizeof(struct fip_size_desc);
1623 len += dlen;
1624 }
1625 dlen += sizeof(frame->mac) + sizeof(frame->wwnn) + sizeof(frame->vn);
1626 len = max(len, min_len + sizeof(struct ethhdr));
1627
1628 skb = dev_alloc_skb(len);
1629 if (!skb)
1630 return;
1631
1632 frame = (struct fip_frame *)skb->data;
1633 memset(frame, 0, len);
1634 memcpy(frame->eth.h_dest, dest, ETH_ALEN);
1635 memcpy(frame->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
1636 frame->eth.h_proto = htons(ETH_P_FIP);
1637
1638 frame->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
1639 frame->fip.fip_op = htons(FIP_OP_VN2VN);
1640 frame->fip.fip_subcode = sub;
1641 frame->fip.fip_dl_len = htons(dlen / FIP_BPW);
1642
1643 frame->mac.fd_desc.fip_dtype = FIP_DT_MAC;
1644 frame->mac.fd_desc.fip_dlen = sizeof(frame->mac) / FIP_BPW;
1645 memcpy(frame->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
1646
1647 frame->wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
1648 frame->wwnn.fd_desc.fip_dlen = sizeof(frame->wwnn) / FIP_BPW;
1649 put_unaligned_be64(fip->lp->wwnn, &frame->wwnn.fd_wwn);
1650
1651 frame->vn.fd_desc.fip_dtype = FIP_DT_VN_ID;
1652 frame->vn.fd_desc.fip_dlen = sizeof(frame->vn) / FIP_BPW;
1653 hton24(frame->vn.fd_mac, FIP_VN_FC_MAP);
1654 hton24(frame->vn.fd_mac + 3, fip->port_id);
1655 hton24(frame->vn.fd_fc_id, fip->port_id);
1656 put_unaligned_be64(fip->lp->wwpn, &frame->vn.fd_wwpn);
1657
1658 /*
1659 * For claims, add FC-4 features.
1660 * TBD: Add interface to get fc-4 types and features from libfc.
1661 */
1662 if (sub == FIP_SC_VN_CLAIM_NOTIFY || sub == FIP_SC_VN_CLAIM_REP) {
1663 ff = (struct fip_fc4_feat *)(frame + 1);
1664 ff->fd_desc.fip_dtype = FIP_DT_FC4F;
1665 ff->fd_desc.fip_dlen = sizeof(*ff) / FIP_BPW;
1666 ff->fd_fts = fip->lp->fcts;
1667
1668 fcp_feat = 0;
1669 if (fip->lp->service_params & FCP_SPPF_INIT_FCN)
1670 fcp_feat |= FCP_FEAT_INIT;
1671 if (fip->lp->service_params & FCP_SPPF_TARG_FCN)
1672 fcp_feat |= FCP_FEAT_TARG;
1673 fcp_feat <<= (FC_TYPE_FCP * 4) % 32;
1674 ff->fd_ff.fd_feat[FC_TYPE_FCP * 4 / 32] = htonl(fcp_feat);
1675
1676 size = (struct fip_size_desc *)(ff + 1);
1677 size->fd_desc.fip_dtype = FIP_DT_FCOE_SIZE;
1678 size->fd_desc.fip_dlen = sizeof(*size) / FIP_BPW;
1679 size->fd_size = htons(fcoe_ctlr_fcoe_size(fip));
1680 }
1681
1682 skb_put(skb, len);
1683 skb->protocol = htons(ETH_P_FIP);
1684 skb_reset_mac_header(skb);
1685 skb_reset_network_header(skb);
1686
1687 fip->send(fip, skb);
1688}
1689
1690/**
1691 * fcoe_ctlr_vn_rport_callback - Event handler for rport events.
1692 * @lport: The lport which is receiving the event
1693 * @rdata: remote port private data
1694 * @event: The event that occured
1695 *
1696 * Locking Note: The rport lock must not be held when calling this function.
1697 */
1698static void fcoe_ctlr_vn_rport_callback(struct fc_lport *lport,
1699 struct fc_rport_priv *rdata,
1700 enum fc_rport_event event)
1701{
1702 struct fcoe_ctlr *fip = lport->disc.priv;
1703 struct fcoe_rport *frport = fcoe_ctlr_rport(rdata);
1704
1705 LIBFCOE_FIP_DBG(fip, "vn_rport_callback %x event %d\n",
1706 rdata->ids.port_id, event);
1707
1708 mutex_lock(&fip->ctlr_mutex);
1709 switch (event) {
1710 case RPORT_EV_READY:
1711 frport->login_count = 0;
1712 break;
1713 case RPORT_EV_LOGO:
1714 case RPORT_EV_FAILED:
1715 case RPORT_EV_STOP:
1716 frport->login_count++;
1717 if (frport->login_count > FCOE_CTLR_VN2VN_LOGIN_LIMIT) {
1718 LIBFCOE_FIP_DBG(fip,
1719 "rport FLOGI limited port_id %6.6x\n",
1720 rdata->ids.port_id);
1721 lport->tt.rport_logoff(rdata);
1722 }
1723 break;
1724 default:
1725 break;
1726 }
1727 mutex_unlock(&fip->ctlr_mutex);
1728}
1729
1730static struct fc_rport_operations fcoe_ctlr_vn_rport_ops = {
1731 .event_callback = fcoe_ctlr_vn_rport_callback,
1732};
1733
1734/**
1735 * fcoe_ctlr_disc_stop_locked() - stop discovery in VN2VN mode
1736 * @fip: The FCoE controller
1737 *
1738 * Called with ctlr_mutex held.
1739 */
1740static void fcoe_ctlr_disc_stop_locked(struct fc_lport *lport)
1741{
1742 mutex_lock(&lport->disc.disc_mutex);
1743 lport->disc.disc_callback = NULL;
1744 mutex_unlock(&lport->disc.disc_mutex);
1745}
1746
1747/**
1748 * fcoe_ctlr_disc_stop() - stop discovery in VN2VN mode
1749 * @fip: The FCoE controller
1750 *
1751 * Called through the local port template for discovery.
1752 * Called without the ctlr_mutex held.
1753 */
1754static void fcoe_ctlr_disc_stop(struct fc_lport *lport)
1755{
1756 struct fcoe_ctlr *fip = lport->disc.priv;
1757
1758 mutex_lock(&fip->ctlr_mutex);
1759 fcoe_ctlr_disc_stop_locked(lport);
1760 mutex_unlock(&fip->ctlr_mutex);
1761}
1762
1763/**
1764 * fcoe_ctlr_disc_stop_final() - stop discovery for shutdown in VN2VN mode
1765 * @fip: The FCoE controller
1766 *
1767 * Called through the local port template for discovery.
1768 * Called without the ctlr_mutex held.
1769 */
1770static void fcoe_ctlr_disc_stop_final(struct fc_lport *lport)
1771{
1772 fcoe_ctlr_disc_stop(lport);
1773 lport->tt.rport_flush_queue();
1774 synchronize_rcu();
1775}
1776
1777/**
1778 * fcoe_ctlr_vn_restart() - VN2VN probe restart with new port_id
1779 * @fip: The FCoE controller
1780 *
1781 * Called with fcoe_ctlr lock held.
1782 */
1783static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip)
1784{
1785 unsigned long wait;
1786 u32 port_id;
1787
1788 fcoe_ctlr_disc_stop_locked(fip->lp);
1789
1790 /*
1791 * Get proposed port ID.
1792 * If this is the first try after link up, use any previous port_id.
1793 * If there was none, use the low bits of the port_name.
1794 * On subsequent tries, get the next random one.
1795 * Don't use reserved IDs, use another non-zero value, just as random.
1796 */
1797 port_id = fip->port_id;
1798 if (fip->probe_tries)
1799 port_id = prandom32(&fip->rnd_state) & 0xffff;
1800 else if (!port_id)
1801 port_id = fip->lp->wwpn & 0xffff;
1802 if (!port_id || port_id == 0xffff)
1803 port_id = 1;
1804 fip->port_id = port_id;
1805
1806 if (fip->probe_tries < FIP_VN_RLIM_COUNT) {
1807 fip->probe_tries++;
1808 wait = random32() % FIP_VN_PROBE_WAIT;
1809 } else
1810 wait = FIP_VN_RLIM_INT;
1811 mod_timer(&fip->timer, jiffies + msecs_to_jiffies(wait));
1812 fcoe_ctlr_set_state(fip, FIP_ST_VNMP_START);
1813}
1814
1815/**
1816 * fcoe_ctlr_vn_start() - Start in VN2VN mode
1817 * @fip: The FCoE controller
1818 *
1819 * Called with fcoe_ctlr lock held.
1820 */
1821static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip)
1822{
1823 fip->probe_tries = 0;
1824 prandom32_seed(&fip->rnd_state, fip->lp->wwpn);
1825 fcoe_ctlr_vn_restart(fip);
1826}
1827
1828/**
1829 * fcoe_ctlr_vn_parse - parse probe request or response
1830 * @fip: The FCoE controller
1831 * @skb: incoming packet
1832 * @rdata: buffer for resulting parsed VN entry plus fcoe_rport
1833 *
1834 * Returns non-zero error number on error.
1835 * Does not consume the packet.
1836 */
1837static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
1838 struct sk_buff *skb,
1839 struct fc_rport_priv *rdata)
1840{
1841 struct fip_header *fiph;
1842 struct fip_desc *desc = NULL;
1843 struct fip_mac_desc *macd = NULL;
1844 struct fip_wwn_desc *wwn = NULL;
1845 struct fip_vn_desc *vn = NULL;
1846 struct fip_size_desc *size = NULL;
1847 struct fcoe_rport *frport;
1848 size_t rlen;
1849 size_t dlen;
1850 u32 desc_mask = 0;
1851 u32 dtype;
1852 u8 sub;
1853
1854 memset(rdata, 0, sizeof(*rdata) + sizeof(*frport));
1855 frport = fcoe_ctlr_rport(rdata);
1856
1857 fiph = (struct fip_header *)skb->data;
1858 frport->flags = ntohs(fiph->fip_flags);
1859
1860 sub = fiph->fip_subcode;
1861 switch (sub) {
1862 case FIP_SC_VN_PROBE_REQ:
1863 case FIP_SC_VN_PROBE_REP:
1864 case FIP_SC_VN_BEACON:
1865 desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) |
1866 BIT(FIP_DT_VN_ID);
1867 break;
1868 case FIP_SC_VN_CLAIM_NOTIFY:
1869 case FIP_SC_VN_CLAIM_REP:
1870 desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) |
1871 BIT(FIP_DT_VN_ID) | BIT(FIP_DT_FC4F) |
1872 BIT(FIP_DT_FCOE_SIZE);
1873 break;
1874 default:
1875 LIBFCOE_FIP_DBG(fip, "vn_parse unknown subcode %u\n", sub);
1876 return -EINVAL;
1877 }
1878
1879 rlen = ntohs(fiph->fip_dl_len) * 4;
1880 if (rlen + sizeof(*fiph) > skb->len)
1881 return -EINVAL;
1882
1883 desc = (struct fip_desc *)(fiph + 1);
1884 while (rlen > 0) {
1885 dlen = desc->fip_dlen * FIP_BPW;
1886 if (dlen < sizeof(*desc) || dlen > rlen)
1887 return -EINVAL;
1888
1889 dtype = desc->fip_dtype;
1890 if (dtype < 32) {
1891 if (!(desc_mask & BIT(dtype))) {
1892 LIBFCOE_FIP_DBG(fip,
1893 "unexpected or duplicated desc "
1894 "desc type %u in "
1895 "FIP VN2VN subtype %u\n",
1896 dtype, sub);
1897 return -EINVAL;
1898 }
1899 desc_mask &= ~BIT(dtype);
1900 }
1901
1902 switch (dtype) {
1903 case FIP_DT_MAC:
1904 if (dlen != sizeof(struct fip_mac_desc))
1905 goto len_err;
1906 macd = (struct fip_mac_desc *)desc;
1907 if (!is_valid_ether_addr(macd->fd_mac)) {
1908 LIBFCOE_FIP_DBG(fip,
1909 "Invalid MAC addr %pM in FIP VN2VN\n",
1910 macd->fd_mac);
1911 return -EINVAL;
1912 }
1913 memcpy(frport->enode_mac, macd->fd_mac, ETH_ALEN);
1914 break;
1915 case FIP_DT_NAME:
1916 if (dlen != sizeof(struct fip_wwn_desc))
1917 goto len_err;
1918 wwn = (struct fip_wwn_desc *)desc;
1919 rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn);
1920 break;
1921 case FIP_DT_VN_ID:
1922 if (dlen != sizeof(struct fip_vn_desc))
1923 goto len_err;
1924 vn = (struct fip_vn_desc *)desc;
1925 memcpy(frport->vn_mac, vn->fd_mac, ETH_ALEN);
1926 rdata->ids.port_id = ntoh24(vn->fd_fc_id);
1927 rdata->ids.port_name = get_unaligned_be64(&vn->fd_wwpn);
1928 break;
1929 case FIP_DT_FC4F:
1930 if (dlen != sizeof(struct fip_fc4_feat))
1931 goto len_err;
1932 break;
1933 case FIP_DT_FCOE_SIZE:
1934 if (dlen != sizeof(struct fip_size_desc))
1935 goto len_err;
1936 size = (struct fip_size_desc *)desc;
1937 frport->fcoe_len = ntohs(size->fd_size);
1938 break;
1939 default:
1940 LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
1941 "in FIP probe\n", dtype);
1942 /* standard says ignore unknown descriptors >= 128 */
1943 if (dtype < FIP_DT_VENDOR_BASE)
1944 return -EINVAL;
1945 break;
1946 }
1947 desc = (struct fip_desc *)((char *)desc + dlen);
1948 rlen -= dlen;
1949 }
1950 return 0;
1951
1952len_err:
1953 LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n",
1954 dtype, dlen);
1955 return -EINVAL;
1956}
1957
1958/**
1959 * fcoe_ctlr_vn_send_claim() - send multicast FIP VN2VN Claim Notification.
1960 * @fip: The FCoE controller
1961 *
1962 * Called with ctlr_mutex held.
1963 */
1964static void fcoe_ctlr_vn_send_claim(struct fcoe_ctlr *fip)
1965{
1966 fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_NOTIFY, fcoe_all_vn2vn, 0);
1967 fip->sol_time = jiffies;
1968}
1969
1970/**
1971 * fcoe_ctlr_vn_probe_req() - handle incoming VN2VN probe request.
1972 * @fip: The FCoE controller
1973 * @rdata: parsed remote port with frport from the probe request
1974 *
1975 * Called with ctlr_mutex held.
1976 */
1977static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
1978 struct fc_rport_priv *rdata)
1979{
1980 struct fcoe_rport *frport = fcoe_ctlr_rport(rdata);
1981
1982 if (rdata->ids.port_id != fip->port_id)
1983 return;
1984
1985 switch (fip->state) {
1986 case FIP_ST_VNMP_CLAIM:
1987 case FIP_ST_VNMP_UP:
1988 fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
1989 frport->enode_mac, 0);
1990 break;
1991 case FIP_ST_VNMP_PROBE1:
1992 case FIP_ST_VNMP_PROBE2:
1993 /*
1994 * Decide whether to reply to the Probe.
1995 * Our selected address is never a "recorded" one, so
1996 * only reply if our WWPN is greater and the
1997 * Probe's REC bit is not set.
1998 * If we don't reply, we will change our address.
1999 */
2000 if (fip->lp->wwpn > rdata->ids.port_name &&
2001 !(frport->flags & FIP_FL_REC_OR_P2P)) {
2002 fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
2003 frport->enode_mac, 0);
2004 break;
2005 }
2006 /* fall through */
2007 case FIP_ST_VNMP_START:
2008 fcoe_ctlr_vn_restart(fip);
2009 break;
2010 default:
2011 break;
2012 }
2013}
2014
2015/**
2016 * fcoe_ctlr_vn_probe_reply() - handle incoming VN2VN probe reply.
2017 * @fip: The FCoE controller
2018 * @rdata: parsed remote port with frport from the probe request
2019 *
2020 * Called with ctlr_mutex held.
2021 */
2022static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip,
2023 struct fc_rport_priv *rdata)
2024{
2025 if (rdata->ids.port_id != fip->port_id)
2026 return;
2027 switch (fip->state) {
2028 case FIP_ST_VNMP_START:
2029 case FIP_ST_VNMP_PROBE1:
2030 case FIP_ST_VNMP_PROBE2:
2031 case FIP_ST_VNMP_CLAIM:
2032 fcoe_ctlr_vn_restart(fip);
2033 break;
2034 case FIP_ST_VNMP_UP:
2035 fcoe_ctlr_vn_send_claim(fip);
2036 break;
2037 default:
2038 break;
2039 }
2040}
2041
2042/**
2043 * fcoe_ctlr_vn_add() - Add a VN2VN entry to the list, based on a claim reply.
2044 * @fip: The FCoE controller
2045 * @new: newly-parsed remote port with frport as a template for new rdata
2046 *
2047 * Called with ctlr_mutex held.
2048 */
2049static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new)
2050{
2051 struct fc_lport *lport = fip->lp;
2052 struct fc_rport_priv *rdata;
2053 struct fc_rport_identifiers *ids;
2054 struct fcoe_rport *frport;
2055 u32 port_id;
2056
2057 port_id = new->ids.port_id;
2058 if (port_id == fip->port_id)
2059 return;
2060
2061 mutex_lock(&lport->disc.disc_mutex);
2062 rdata = lport->tt.rport_create(lport, port_id);
2063 if (!rdata) {
2064 mutex_unlock(&lport->disc.disc_mutex);
2065 return;
2066 }
2067
2068 rdata->ops = &fcoe_ctlr_vn_rport_ops;
2069 rdata->disc_id = lport->disc.disc_id;
2070
2071 ids = &rdata->ids;
2072 if ((ids->port_name != -1 && ids->port_name != new->ids.port_name) ||
2073 (ids->node_name != -1 && ids->node_name != new->ids.node_name))
2074 lport->tt.rport_logoff(rdata);
2075 ids->port_name = new->ids.port_name;
2076 ids->node_name = new->ids.node_name;
2077 mutex_unlock(&lport->disc.disc_mutex);
2078
2079 frport = fcoe_ctlr_rport(rdata);
2080 LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s\n",
2081 port_id, frport->fcoe_len ? "old" : "new");
2082 *frport = *fcoe_ctlr_rport(new);
2083 frport->time = 0;
2084}
2085
2086/**
2087 * fcoe_ctlr_vn_lookup() - Find VN remote port's MAC address
2088 * @fip: The FCoE controller
2089 * @port_id: The port_id of the remote VN_node
2090 * @mac: buffer which will hold the VN_NODE destination MAC address, if found.
2091 *
2092 * Returns non-zero error if no remote port found.
2093 */
2094static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *fip, u32 port_id, u8 *mac)
2095{
2096 struct fc_lport *lport = fip->lp;
2097 struct fc_rport_priv *rdata;
2098 struct fcoe_rport *frport;
2099 int ret = -1;
2100
2101 rcu_read_lock();
2102 rdata = lport->tt.rport_lookup(lport, port_id);
2103 if (rdata) {
2104 frport = fcoe_ctlr_rport(rdata);
2105 memcpy(mac, frport->enode_mac, ETH_ALEN);
2106 ret = 0;
2107 }
2108 rcu_read_unlock();
2109 return ret;
2110}
2111
2112/**
2113 * fcoe_ctlr_vn_claim_notify() - handle received FIP VN2VN Claim Notification
2114 * @fip: The FCoE controller
2115 * @new: newly-parsed remote port with frport as a template for new rdata
2116 *
2117 * Called with ctlr_mutex held.
2118 */
2119static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
2120 struct fc_rport_priv *new)
2121{
2122 struct fcoe_rport *frport = fcoe_ctlr_rport(new);
2123
2124 if (frport->flags & FIP_FL_REC_OR_P2P) {
2125 fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
2126 return;
2127 }
2128 switch (fip->state) {
2129 case FIP_ST_VNMP_START:
2130 case FIP_ST_VNMP_PROBE1:
2131 case FIP_ST_VNMP_PROBE2:
2132 if (new->ids.port_id == fip->port_id)
2133 fcoe_ctlr_vn_restart(fip);
2134 break;
2135 case FIP_ST_VNMP_CLAIM:
2136 case FIP_ST_VNMP_UP:
2137 if (new->ids.port_id == fip->port_id) {
2138 if (new->ids.port_name > fip->lp->wwpn) {
2139 fcoe_ctlr_vn_restart(fip);
2140 break;
2141 }
2142 fcoe_ctlr_vn_send_claim(fip);
2143 break;
2144 }
2145 fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_REP, frport->enode_mac,
2146 min((u32)frport->fcoe_len,
2147 fcoe_ctlr_fcoe_size(fip)));
2148 fcoe_ctlr_vn_add(fip, new);
2149 break;
2150 default:
2151 break;
2152 }
2153}
2154
2155/**
2156 * fcoe_ctlr_vn_claim_resp() - handle received Claim Response
2157 * @fip: The FCoE controller that received the frame
2158 * @new: newly-parsed remote port with frport from the Claim Response
2159 *
2160 * Called with ctlr_mutex held.
2161 */
2162static void fcoe_ctlr_vn_claim_resp(struct fcoe_ctlr *fip,
2163 struct fc_rport_priv *new)
2164{
2165 LIBFCOE_FIP_DBG(fip, "claim resp from from rport %x - state %s\n",
2166 new->ids.port_id, fcoe_ctlr_state(fip->state));
2167 if (fip->state == FIP_ST_VNMP_UP || fip->state == FIP_ST_VNMP_CLAIM)
2168 fcoe_ctlr_vn_add(fip, new);
2169}
2170
2171/**
2172 * fcoe_ctlr_vn_beacon() - handle received beacon.
2173 * @fip: The FCoE controller that received the frame
2174 * @new: newly-parsed remote port with frport from the Beacon
2175 *
2176 * Called with ctlr_mutex held.
2177 */
2178static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip,
2179 struct fc_rport_priv *new)
2180{
2181 struct fc_lport *lport = fip->lp;
2182 struct fc_rport_priv *rdata;
2183 struct fcoe_rport *frport;
2184
2185 frport = fcoe_ctlr_rport(new);
2186 if (frport->flags & FIP_FL_REC_OR_P2P) {
2187 fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
2188 return;
2189 }
2190 mutex_lock(&lport->disc.disc_mutex);
2191 rdata = lport->tt.rport_lookup(lport, new->ids.port_id);
2192 if (rdata)
2193 kref_get(&rdata->kref);
2194 mutex_unlock(&lport->disc.disc_mutex);
2195 if (rdata) {
2196 if (rdata->ids.node_name == new->ids.node_name &&
2197 rdata->ids.port_name == new->ids.port_name) {
2198 frport = fcoe_ctlr_rport(rdata);
2199 if (!frport->time && fip->state == FIP_ST_VNMP_UP)
2200 lport->tt.rport_login(rdata);
2201 frport->time = jiffies;
2202 }
2203 kref_put(&rdata->kref, lport->tt.rport_destroy);
2204 return;
2205 }
2206 if (fip->state != FIP_ST_VNMP_UP)
2207 return;
2208
2209 /*
2210 * Beacon from a new neighbor.
2211 * Send a claim notify if one hasn't been sent recently.
2212 * Don't add the neighbor yet.
2213 */
2214 LIBFCOE_FIP_DBG(fip, "beacon from new rport %x. sending claim notify\n",
2215 new->ids.port_id);
2216 if (time_after(jiffies,
2217 fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT)))
2218 fcoe_ctlr_vn_send_claim(fip);
2219}
2220
2221/**
2222 * fcoe_ctlr_vn_age() - Check for VN_ports without recent beacons
2223 * @fip: The FCoE controller
2224 *
2225 * Called with ctlr_mutex held.
2226 * Called only in state FIP_ST_VNMP_UP.
2227 * Returns the soonest time for next age-out or a time far in the future.
2228 */
2229static unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr *fip)
2230{
2231 struct fc_lport *lport = fip->lp;
2232 struct fc_rport_priv *rdata;
2233 struct fcoe_rport *frport;
2234 unsigned long next_time;
2235 unsigned long deadline;
2236
2237 next_time = jiffies + msecs_to_jiffies(FIP_VN_BEACON_INT * 10);
2238 mutex_lock(&lport->disc.disc_mutex);
2239 list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) {
2240 frport = fcoe_ctlr_rport(rdata);
2241 if (!frport->time)
2242 continue;
2243 deadline = frport->time +
2244 msecs_to_jiffies(FIP_VN_BEACON_INT * 25 / 10);
2245 if (time_after_eq(jiffies, deadline)) {
2246 frport->time = 0;
2247 LIBFCOE_FIP_DBG(fip,
2248 "port %16.16llx fc_id %6.6x beacon expired\n",
2249 rdata->ids.port_name, rdata->ids.port_id);
2250 lport->tt.rport_logoff(rdata);
2251 } else if (time_before(deadline, next_time))
2252 next_time = deadline;
2253 }
2254 mutex_unlock(&lport->disc.disc_mutex);
2255 return next_time;
2256}
2257
2258/**
2259 * fcoe_ctlr_vn_recv() - Receive a FIP frame
2260 * @fip: The FCoE controller that received the frame
2261 * @skb: The received FIP frame
2262 *
2263 * Returns non-zero if the frame is dropped.
2264 * Always consumes the frame.
2265 */
2266static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
2267{
2268 struct fip_header *fiph;
2269 enum fip_vn2vn_subcode sub;
2270 union {
2271 struct fc_rport_priv rdata;
2272 struct fcoe_rport frport;
2273 } buf;
2274 int rc;
2275
2276 fiph = (struct fip_header *)skb->data;
2277 sub = fiph->fip_subcode;
2278
2279 rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata);
2280 if (rc) {
2281 LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc);
2282 goto drop;
2283 }
2284
2285 mutex_lock(&fip->ctlr_mutex);
2286 switch (sub) {
2287 case FIP_SC_VN_PROBE_REQ:
2288 fcoe_ctlr_vn_probe_req(fip, &buf.rdata);
2289 break;
2290 case FIP_SC_VN_PROBE_REP:
2291 fcoe_ctlr_vn_probe_reply(fip, &buf.rdata);
2292 break;
2293 case FIP_SC_VN_CLAIM_NOTIFY:
2294 fcoe_ctlr_vn_claim_notify(fip, &buf.rdata);
2295 break;
2296 case FIP_SC_VN_CLAIM_REP:
2297 fcoe_ctlr_vn_claim_resp(fip, &buf.rdata);
2298 break;
2299 case FIP_SC_VN_BEACON:
2300 fcoe_ctlr_vn_beacon(fip, &buf.rdata);
2301 break;
2302 default:
2303 LIBFCOE_FIP_DBG(fip, "vn_recv unknown subcode %d\n", sub);
2304 rc = -1;
2305 break;
2306 }
2307 mutex_unlock(&fip->ctlr_mutex);
2308drop:
2309 kfree_skb(skb);
2310 return rc;
2311}
2312
2313/**
2314 * fcoe_ctlr_disc_recv - discovery receive handler for VN2VN mode.
2315 * @fip: The FCoE controller
2316 *
2317 * This should never be called since we don't see RSCNs or other
2318 * fabric-generated ELSes.
2319 */
2320static void fcoe_ctlr_disc_recv(struct fc_seq *seq, struct fc_frame *fp,
2321 struct fc_lport *lport)
2322{
2323 struct fc_seq_els_data rjt_data;
2324
2325 rjt_data.fp = NULL;
2326 rjt_data.reason = ELS_RJT_UNSUP;
2327 rjt_data.explan = ELS_EXPL_NONE;
2328 lport->tt.seq_els_rsp_send(seq, ELS_LS_RJT, &rjt_data);
2329 fc_frame_free(fp);
2330}
2331
2332/**
2333 * fcoe_ctlr_disc_recv - start discovery for VN2VN mode.
2334 * @fip: The FCoE controller
2335 *
2336 * This sets a flag indicating that remote ports should be created
2337 * and started for the peers we discover. We use the disc_callback
2338 * pointer as that flag. Peers already discovered are created here.
2339 *
2340 * The lport lock is held during this call. The callback must be done
2341 * later, without holding either the lport or discovery locks.
2342 * The fcoe_ctlr lock may also be held during this call.
2343 */
2344static void fcoe_ctlr_disc_start(void (*callback)(struct fc_lport *,
2345 enum fc_disc_event),
2346 struct fc_lport *lport)
2347{
2348 struct fc_disc *disc = &lport->disc;
2349 struct fcoe_ctlr *fip = disc->priv;
2350
2351 mutex_lock(&disc->disc_mutex);
2352 disc->disc_callback = callback;
2353 disc->disc_id = (disc->disc_id + 2) | 1;
2354 disc->pending = 1;
2355 schedule_work(&fip->timer_work);
2356 mutex_unlock(&disc->disc_mutex);
2357}
2358
2359/**
2360 * fcoe_ctlr_vn_disc() - report FIP VN_port discovery results after claim state.
2361 * @fip: The FCoE controller
2362 *
2363 * Starts the FLOGI and PLOGI login process to each discovered rport for which
2364 * we've received at least one beacon.
2365 * Performs the discovery complete callback.
2366 */
2367static void fcoe_ctlr_vn_disc(struct fcoe_ctlr *fip)
2368{
2369 struct fc_lport *lport = fip->lp;
2370 struct fc_disc *disc = &lport->disc;
2371 struct fc_rport_priv *rdata;
2372 struct fcoe_rport *frport;
2373 void (*callback)(struct fc_lport *, enum fc_disc_event);
2374
2375 mutex_lock(&disc->disc_mutex);
2376 callback = disc->pending ? disc->disc_callback : NULL;
2377 disc->pending = 0;
2378 list_for_each_entry_rcu(rdata, &disc->rports, peers) {
2379 frport = fcoe_ctlr_rport(rdata);
2380 if (frport->time)
2381 lport->tt.rport_login(rdata);
2382 }
2383 mutex_unlock(&disc->disc_mutex);
2384 if (callback)
2385 callback(lport, DISC_EV_SUCCESS);
2386}
2387
2388/**
2389 * fcoe_ctlr_vn_timeout - timer work function for VN2VN mode.
2390 * @fip: The FCoE controller
2391 */
2392static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
2393{
2394 unsigned long next_time;
2395 u8 mac[ETH_ALEN];
2396 u32 new_port_id = 0;
2397
2398 mutex_lock(&fip->ctlr_mutex);
2399 switch (fip->state) {
2400 case FIP_ST_VNMP_START:
2401 fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE1);
2402 fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
2403 next_time = jiffies + msecs_to_jiffies(FIP_VN_PROBE_WAIT);
2404 break;
2405 case FIP_ST_VNMP_PROBE1:
2406 fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE2);
2407 fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
2408 next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
2409 break;
2410 case FIP_ST_VNMP_PROBE2:
2411 fcoe_ctlr_set_state(fip, FIP_ST_VNMP_CLAIM);
2412 new_port_id = fip->port_id;
2413 hton24(mac, FIP_VN_FC_MAP);
2414 hton24(mac + 3, new_port_id);
2415 fip->update_mac(fip->lp, mac);
2416 fcoe_ctlr_vn_send_claim(fip);
2417 next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
2418 break;
2419 case FIP_ST_VNMP_CLAIM:
2420 /*
2421 * This may be invoked either by starting discovery so don't
2422 * go to the next state unless it's been long enough.
2423 */
2424 next_time = fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT);
2425 if (time_after_eq(jiffies, next_time)) {
2426 fcoe_ctlr_set_state(fip, FIP_ST_VNMP_UP);
2427 fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON,
2428 fcoe_all_vn2vn, 0);
2429 next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
2430 fip->port_ka_time = next_time;
2431 }
2432 fcoe_ctlr_vn_disc(fip);
2433 break;
2434 case FIP_ST_VNMP_UP:
2435 next_time = fcoe_ctlr_vn_age(fip);
2436 if (time_after_eq(jiffies, fip->port_ka_time)) {
2437 fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON,
2438 fcoe_all_vn2vn, 0);
2439 fip->port_ka_time = jiffies +
2440 msecs_to_jiffies(FIP_VN_BEACON_INT +
2441 (random32() % FIP_VN_BEACON_FUZZ));
2442 }
2443 if (time_before(fip->port_ka_time, next_time))
2444 next_time = fip->port_ka_time;
2445 break;
2446 case FIP_ST_LINK_WAIT:
2447 goto unlock;
2448 default:
2449 WARN(1, "unexpected state %d", fip->state);
2450 goto unlock;
2451 }
2452 mod_timer(&fip->timer, next_time);
2453unlock:
2454 mutex_unlock(&fip->ctlr_mutex);
2455
2456 /* If port ID is new, notify local port after dropping ctlr_mutex */
2457 if (new_port_id)
2458 fc_lport_set_local_id(fip->lp, new_port_id);
2459}
2460
2461/**
1518 * fcoe_libfc_config() - Sets up libfc related properties for local port 2462 * fcoe_libfc_config() - Sets up libfc related properties for local port
1519 * @lp: The local port to configure libfc for 2463 * @lp: The local port to configure libfc for
2464 * @fip: The FCoE controller in use by the local port
1520 * @tt: The libfc function template 2465 * @tt: The libfc function template
2466 * @init_fcp: If non-zero, the FCP portion of libfc should be initialized
1521 * 2467 *
1522 * Returns : 0 for success 2468 * Returns : 0 for success
1523 */ 2469 */
1524int fcoe_libfc_config(struct fc_lport *lport, 2470int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip,
1525 struct libfc_function_template *tt) 2471 const struct libfc_function_template *tt, int init_fcp)
1526{ 2472{
1527 /* Set the function pointers set by the LLDD */ 2473 /* Set the function pointers set by the LLDD */
1528 memcpy(&lport->tt, tt, sizeof(*tt)); 2474 memcpy(&lport->tt, tt, sizeof(*tt));
1529 if (fc_fcp_init(lport)) 2475 if (init_fcp && fc_fcp_init(lport))
1530 return -ENOMEM; 2476 return -ENOMEM;
1531 fc_exch_init(lport); 2477 fc_exch_init(lport);
1532 fc_elsct_init(lport); 2478 fc_elsct_init(lport);
1533 fc_lport_init(lport); 2479 fc_lport_init(lport);
2480 if (fip->mode == FIP_MODE_VN2VN)
2481 lport->rport_priv_size = sizeof(struct fcoe_rport);
1534 fc_rport_init(lport); 2482 fc_rport_init(lport);
1535 fc_disc_init(lport); 2483 if (fip->mode == FIP_MODE_VN2VN) {
1536 2484 lport->point_to_multipoint = 1;
2485 lport->tt.disc_recv_req = fcoe_ctlr_disc_recv;
2486 lport->tt.disc_start = fcoe_ctlr_disc_start;
2487 lport->tt.disc_stop = fcoe_ctlr_disc_stop;
2488 lport->tt.disc_stop_final = fcoe_ctlr_disc_stop_final;
2489 mutex_init(&lport->disc.disc_mutex);
2490 INIT_LIST_HEAD(&lport->disc.rports);
2491 lport->disc.priv = fip;
2492 } else {
2493 fc_disc_init(lport);
2494 }
1537 return 0; 2495 return 0;
1538} 2496}
1539EXPORT_SYMBOL_GPL(fcoe_libfc_config); 2497EXPORT_SYMBOL_GPL(fcoe_libfc_config);
1540