summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2016-07-19 07:49:40 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2016-07-20 19:49:41 -0400
commit9a6cf881df0293cc1c06d31bcbeda6c23b95dcac (patch)
treec0e197eae96edd8539b5e1b54c4a04752c22759f
parentb3d30f4a24f0ef9ba04bd9dc84523c6c9d18c11b (diff)
fcoe: implement FIP VLAN responder
When running in VN2VN mode there is no central instance which would send out any FIP VLAN discovery notifications. So this patch adds a new sysfs attribute 'fip_vlan_responder' which will activate a FIP VLAN discovery responder. Signed-off-by: Hannes Reinecke <hare@suse.com> Acked-by: Johannes Thumshirn <jth@kernel.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/fcoe/fcoe.c6
-rw-r--r--drivers/scsi/fcoe/fcoe_ctlr.c224
-rw-r--r--drivers/scsi/fcoe/fcoe_sysfs.c39
-rw-r--r--include/scsi/libfc.h1
-rw-r--r--include/scsi/libfcoe.h5
5 files changed, 274 insertions, 1 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 61eda7498c90..c8a4305c7662 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -673,6 +673,12 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev)
673 fcoe = port->priv; 673 fcoe = port->priv;
674 ctlr = fcoe_to_ctlr(fcoe); 674 ctlr = fcoe_to_ctlr(fcoe);
675 675
676 /* Figure out the VLAN ID, if any */
677 if (netdev->priv_flags & IFF_802_1Q_VLAN)
678 lport->vlan = vlan_dev_vlan_id(netdev);
679 else
680 lport->vlan = 0;
681
676 /* 682 /*
677 * Determine max frame size based on underlying device and optional 683 * Determine max frame size based on underlying device and optional
678 * user-configured limit. If the MFS is too low, fcoe_link_ok() 684 * user-configured limit. If the MFS is too low, fcoe_link_ok()
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index dd455312de41..a569c65f22b1 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -59,6 +59,8 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *);
59static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *); 59static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *);
60static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *, u32, u8 *); 60static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *, u32, u8 *);
61 61
62static int fcoe_ctlr_vlan_recv(struct fcoe_ctlr *, struct sk_buff *);
63
62static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS; 64static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS;
63static u8 fcoe_all_enode[ETH_ALEN] = FIP_ALL_ENODE_MACS; 65static u8 fcoe_all_enode[ETH_ALEN] = FIP_ALL_ENODE_MACS;
64static u8 fcoe_all_vn2vn[ETH_ALEN] = FIP_ALL_VN2VN_MACS; 66static u8 fcoe_all_vn2vn[ETH_ALEN] = FIP_ALL_VN2VN_MACS;
@@ -149,6 +151,7 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode)
149{ 151{
150 fcoe_ctlr_set_state(fip, FIP_ST_LINK_WAIT); 152 fcoe_ctlr_set_state(fip, FIP_ST_LINK_WAIT);
151 fip->mode = mode; 153 fip->mode = mode;
154 fip->fip_resp = false;
152 INIT_LIST_HEAD(&fip->fcfs); 155 INIT_LIST_HEAD(&fip->fcfs);
153 mutex_init(&fip->ctlr_mutex); 156 mutex_init(&fip->ctlr_mutex);
154 spin_lock_init(&fip->ctlr_lock); 157 spin_lock_init(&fip->ctlr_lock);
@@ -1513,6 +1516,7 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb)
1513 struct fip_header *fiph; 1516 struct fip_header *fiph;
1514 struct ethhdr *eh; 1517 struct ethhdr *eh;
1515 enum fip_state state; 1518 enum fip_state state;
1519 bool fip_vlan_resp = false;
1516 u16 op; 1520 u16 op;
1517 u8 sub; 1521 u8 sub;
1518 1522
@@ -1546,11 +1550,17 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb)
1546 state = FIP_ST_ENABLED; 1550 state = FIP_ST_ENABLED;
1547 LIBFCOE_FIP_DBG(fip, "Using FIP mode\n"); 1551 LIBFCOE_FIP_DBG(fip, "Using FIP mode\n");
1548 } 1552 }
1553 fip_vlan_resp = fip->fip_resp;
1549 mutex_unlock(&fip->ctlr_mutex); 1554 mutex_unlock(&fip->ctlr_mutex);
1550 1555
1551 if (fip->mode == FIP_MODE_VN2VN && op == FIP_OP_VN2VN) 1556 if (fip->mode == FIP_MODE_VN2VN && op == FIP_OP_VN2VN)
1552 return fcoe_ctlr_vn_recv(fip, skb); 1557 return fcoe_ctlr_vn_recv(fip, skb);
1553 1558
1559 if (fip_vlan_resp && op == FIP_OP_VLAN) {
1560 LIBFCOE_FIP_DBG(fip, "fip vlan discovery\n");
1561 return fcoe_ctlr_vlan_recv(fip, skb);
1562 }
1563
1554 if (state != FIP_ST_ENABLED && state != FIP_ST_VNMP_UP && 1564 if (state != FIP_ST_ENABLED && state != FIP_ST_VNMP_UP &&
1555 state != FIP_ST_VNMP_CLAIM) 1565 state != FIP_ST_VNMP_CLAIM)
1556 goto drop; 1566 goto drop;
@@ -2704,6 +2714,220 @@ drop:
2704} 2714}
2705 2715
2706/** 2716/**
2717 * fcoe_ctlr_vlan_parse - parse vlan discovery request or response
2718 * @fip: The FCoE controller
2719 * @skb: incoming packet
2720 * @rdata: buffer for resulting parsed VLAN entry plus fcoe_rport
2721 *
2722 * Returns non-zero error number on error.
2723 * Does not consume the packet.
2724 */
2725static int fcoe_ctlr_vlan_parse(struct fcoe_ctlr *fip,
2726 struct sk_buff *skb,
2727 struct fc_rport_priv *rdata)
2728{
2729 struct fip_header *fiph;
2730 struct fip_desc *desc = NULL;
2731 struct fip_mac_desc *macd = NULL;
2732 struct fip_wwn_desc *wwn = NULL;
2733 struct fcoe_rport *frport;
2734 size_t rlen;
2735 size_t dlen;
2736 u32 desc_mask = 0;
2737 u32 dtype;
2738 u8 sub;
2739
2740 memset(rdata, 0, sizeof(*rdata) + sizeof(*frport));
2741 frport = fcoe_ctlr_rport(rdata);
2742
2743 fiph = (struct fip_header *)skb->data;
2744 frport->flags = ntohs(fiph->fip_flags);
2745
2746 sub = fiph->fip_subcode;
2747 switch (sub) {
2748 case FIP_SC_VL_REQ:
2749 desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME);
2750 break;
2751 default:
2752 LIBFCOE_FIP_DBG(fip, "vn_parse unknown subcode %u\n", sub);
2753 return -EINVAL;
2754 }
2755
2756 rlen = ntohs(fiph->fip_dl_len) * 4;
2757 if (rlen + sizeof(*fiph) > skb->len)
2758 return -EINVAL;
2759
2760 desc = (struct fip_desc *)(fiph + 1);
2761 while (rlen > 0) {
2762 dlen = desc->fip_dlen * FIP_BPW;
2763 if (dlen < sizeof(*desc) || dlen > rlen)
2764 return -EINVAL;
2765
2766 dtype = desc->fip_dtype;
2767 if (dtype < 32) {
2768 if (!(desc_mask & BIT(dtype))) {
2769 LIBFCOE_FIP_DBG(fip,
2770 "unexpected or duplicated desc "
2771 "desc type %u in "
2772 "FIP VN2VN subtype %u\n",
2773 dtype, sub);
2774 return -EINVAL;
2775 }
2776 desc_mask &= ~BIT(dtype);
2777 }
2778
2779 switch (dtype) {
2780 case FIP_DT_MAC:
2781 if (dlen != sizeof(struct fip_mac_desc))
2782 goto len_err;
2783 macd = (struct fip_mac_desc *)desc;
2784 if (!is_valid_ether_addr(macd->fd_mac)) {
2785 LIBFCOE_FIP_DBG(fip,
2786 "Invalid MAC addr %pM in FIP VN2VN\n",
2787 macd->fd_mac);
2788 return -EINVAL;
2789 }
2790 memcpy(frport->enode_mac, macd->fd_mac, ETH_ALEN);
2791 break;
2792 case FIP_DT_NAME:
2793 if (dlen != sizeof(struct fip_wwn_desc))
2794 goto len_err;
2795 wwn = (struct fip_wwn_desc *)desc;
2796 rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn);
2797 break;
2798 default:
2799 LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
2800 "in FIP probe\n", dtype);
2801 /* standard says ignore unknown descriptors >= 128 */
2802 if (dtype < FIP_DT_NON_CRITICAL)
2803 return -EINVAL;
2804 break;
2805 }
2806 desc = (struct fip_desc *)((char *)desc + dlen);
2807 rlen -= dlen;
2808 }
2809 return 0;
2810
2811len_err:
2812 LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n",
2813 dtype, dlen);
2814 return -EINVAL;
2815}
2816
2817/**
2818 * fcoe_ctlr_vlan_send() - Send a FIP VLAN Notification
2819 * @fip: The FCoE controller
2820 * @sub: sub-opcode for vlan notification or vn2vn vlan notification
2821 * @dest: The destination Ethernet MAC address
2822 * @min_len: minimum size of the Ethernet payload to be sent
2823 */
2824static void fcoe_ctlr_vlan_send(struct fcoe_ctlr *fip,
2825 enum fip_vlan_subcode sub,
2826 const u8 *dest)
2827{
2828 struct sk_buff *skb;
2829 struct fip_vlan_notify_frame {
2830 struct ethhdr eth;
2831 struct fip_header fip;
2832 struct fip_mac_desc mac;
2833 struct fip_vlan_desc vlan;
2834 } __packed * frame;
2835 size_t len;
2836 size_t dlen;
2837
2838 len = sizeof(*frame);
2839 dlen = sizeof(frame->mac) + sizeof(frame->vlan);
2840 len = max(len, sizeof(struct ethhdr));
2841
2842 skb = dev_alloc_skb(len);
2843 if (!skb)
2844 return;
2845
2846 LIBFCOE_FIP_DBG(fip, "fip %s vlan notification, vlan %d\n",
2847 fip->mode == FIP_MODE_VN2VN ? "vn2vn" : "fcf",
2848 fip->lp->vlan);
2849
2850 frame = (struct fip_vlan_notify_frame *)skb->data;
2851 memset(frame, 0, len);
2852 memcpy(frame->eth.h_dest, dest, ETH_ALEN);
2853
2854 memcpy(frame->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
2855 frame->eth.h_proto = htons(ETH_P_FIP);
2856
2857 frame->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
2858 frame->fip.fip_op = htons(FIP_OP_VLAN);
2859 frame->fip.fip_subcode = sub;
2860 frame->fip.fip_dl_len = htons(dlen / FIP_BPW);
2861
2862 frame->mac.fd_desc.fip_dtype = FIP_DT_MAC;
2863 frame->mac.fd_desc.fip_dlen = sizeof(frame->mac) / FIP_BPW;
2864 memcpy(frame->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
2865
2866 frame->vlan.fd_desc.fip_dtype = FIP_DT_VLAN;
2867 frame->vlan.fd_desc.fip_dlen = sizeof(frame->vlan) / FIP_BPW;
2868 put_unaligned_be16(fip->lp->vlan, &frame->vlan.fd_vlan);
2869
2870 skb_put(skb, len);
2871 skb->protocol = htons(ETH_P_FIP);
2872 skb->priority = fip->priority;
2873 skb_reset_mac_header(skb);
2874 skb_reset_network_header(skb);
2875
2876 fip->send(fip, skb);
2877}
2878
2879/**
2880 * fcoe_ctlr_vlan_disk_reply() - send FIP VLAN Discovery Notification.
2881 * @fip: The FCoE controller
2882 *
2883 * Called with ctlr_mutex held.
2884 */
2885static void fcoe_ctlr_vlan_disc_reply(struct fcoe_ctlr *fip,
2886 struct fc_rport_priv *rdata)
2887{
2888 struct fcoe_rport *frport = fcoe_ctlr_rport(rdata);
2889 enum fip_vlan_subcode sub = FIP_SC_VL_NOTE;
2890
2891 if (fip->mode == FIP_MODE_VN2VN)
2892 sub = FIP_SC_VL_VN2VN_NOTE;
2893
2894 fcoe_ctlr_vlan_send(fip, sub, frport->enode_mac);
2895}
2896
2897/**
2898 * fcoe_ctlr_vlan_recv - vlan request receive handler for VN2VN mode.
2899 * @lport: The local port
2900 * @fp: The received frame
2901 *
2902 */
2903static int fcoe_ctlr_vlan_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
2904{
2905 struct fip_header *fiph;
2906 enum fip_vlan_subcode sub;
2907 struct {
2908 struct fc_rport_priv rdata;
2909 struct fcoe_rport frport;
2910 } buf;
2911 int rc;
2912
2913 fiph = (struct fip_header *)skb->data;
2914 sub = fiph->fip_subcode;
2915 rc = fcoe_ctlr_vlan_parse(fip, skb, &buf.rdata);
2916 if (rc) {
2917 LIBFCOE_FIP_DBG(fip, "vlan_recv vlan_parse error %d\n", rc);
2918 goto drop;
2919 }
2920 mutex_lock(&fip->ctlr_mutex);
2921 if (sub == FIP_SC_VL_REQ)
2922 fcoe_ctlr_vlan_disc_reply(fip, &buf.rdata);
2923 mutex_unlock(&fip->ctlr_mutex);
2924
2925drop:
2926 kfree(skb);
2927 return rc;
2928}
2929
2930/**
2707 * fcoe_ctlr_disc_recv - discovery receive handler for VN2VN mode. 2931 * fcoe_ctlr_disc_recv - discovery receive handler for VN2VN mode.
2708 * @lport: The local port 2932 * @lport: The local port
2709 * @fp: The received frame 2933 * @fp: The received frame
diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c
index 045c4e11ee54..0675fd128734 100644
--- a/drivers/scsi/fcoe/fcoe_sysfs.c
+++ b/drivers/scsi/fcoe/fcoe_sysfs.c
@@ -385,6 +385,44 @@ static FCOE_DEVICE_ATTR(ctlr, enabled, S_IRUGO | S_IWUSR,
385 show_ctlr_enabled_state, 385 show_ctlr_enabled_state,
386 store_ctlr_enabled); 386 store_ctlr_enabled);
387 387
388static ssize_t store_ctlr_fip_resp(struct device *dev,
389 struct device_attribute *attr,
390 const char *buf, size_t count)
391{
392 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
393 struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr);
394
395 mutex_lock(&fip->ctlr_mutex);
396 if ((buf[1] == '\0') || ((buf[1] == '\n') && (buf[2] == '\0'))) {
397 if (buf[0] == '1') {
398 fip->fip_resp = 1;
399 mutex_unlock(&fip->ctlr_mutex);
400 return count;
401 }
402 if (buf[0] == '0') {
403 fip->fip_resp = 0;
404 mutex_unlock(&fip->ctlr_mutex);
405 return count;
406 }
407 }
408 mutex_unlock(&fip->ctlr_mutex);
409 return -EINVAL;
410}
411
412static ssize_t show_ctlr_fip_resp(struct device *dev,
413 struct device_attribute *attr,
414 char *buf)
415{
416 struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
417 struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr);
418
419 return sprintf(buf, "%d\n", fip->fip_resp ? 1 : 0);
420}
421
422static FCOE_DEVICE_ATTR(ctlr, fip_vlan_responder, S_IRUGO | S_IWUSR,
423 show_ctlr_fip_resp,
424 store_ctlr_fip_resp);
425
388static ssize_t 426static ssize_t
389store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev, 427store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev,
390 struct device_attribute *attr, 428 struct device_attribute *attr,
@@ -467,6 +505,7 @@ static struct attribute_group fcoe_ctlr_lesb_attr_group = {
467}; 505};
468 506
469static struct attribute *fcoe_ctlr_attrs[] = { 507static struct attribute *fcoe_ctlr_attrs[] = {
508 &device_attr_fcoe_ctlr_fip_vlan_responder.attr,
470 &device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr, 509 &device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr,
471 &device_attr_fcoe_ctlr_enabled.attr, 510 &device_attr_fcoe_ctlr_enabled.attr,
472 &device_attr_fcoe_ctlr_mode.attr, 511 &device_attr_fcoe_ctlr_mode.attr,
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 93d14daf0994..7428a53257ca 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -878,6 +878,7 @@ struct fc_lport {
878 struct libfc_function_template tt; 878 struct libfc_function_template tt;
879 u8 link_up; 879 u8 link_up;
880 u8 qfull; 880 u8 qfull;
881 u16 vlan;
881 enum fc_lport_state state; 882 enum fc_lport_state state;
882 unsigned long boot_time; 883 unsigned long boot_time;
883 struct fc_host_statistics host_stats; 884 struct fc_host_statistics host_stats;
diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h
index bcc5c3e82977..722d3264d3bf 100644
--- a/include/scsi/libfcoe.h
+++ b/include/scsi/libfcoe.h
@@ -110,8 +110,10 @@ enum fip_mode {
110 * @flogi_req_send: send of FLOGI requested 110 * @flogi_req_send: send of FLOGI requested
111 * @flogi_count: number of FLOGI attempts in AUTO mode. 111 * @flogi_count: number of FLOGI attempts in AUTO mode.
112 * @map_dest: use the FC_MAP mode for destination MAC addresses. 112 * @map_dest: use the FC_MAP mode for destination MAC addresses.
113 * @fip_resp: start FIP VLAN discovery responder
113 * @spma: supports SPMA server-provided MACs mode 114 * @spma: supports SPMA server-provided MACs mode
114 * @probe_tries: number of FC_IDs probed 115 * @probe_tries: number of FC_IDs probed
116 * @priority: DCBx FCoE APP priority
115 * @dest_addr: MAC address of the selected FC forwarder. 117 * @dest_addr: MAC address of the selected FC forwarder.
116 * @ctl_src_addr: the native MAC address of our local port. 118 * @ctl_src_addr: the native MAC address of our local port.
117 * @send: LLD-supplied function to handle sending FIP Ethernet frames 119 * @send: LLD-supplied function to handle sending FIP Ethernet frames
@@ -149,7 +151,8 @@ struct fcoe_ctlr {
149 u16 flogi_oxid; 151 u16 flogi_oxid;
150 u8 flogi_req_send; 152 u8 flogi_req_send;
151 u8 flogi_count; 153 u8 flogi_count;
152 u8 map_dest; 154 bool map_dest;
155 bool fip_resp;
153 u8 spma; 156 u8 spma;
154 u8 probe_tries; 157 u8 probe_tries;
155 u8 priority; 158 u8 priority;