Commit 97c8389d54b9665c38105ea72a428a44b97ff2f6

Authored by Joe Eykholt
Committed by James Bottomley
1 parent af5f428763

[SCSI] fcoe, libfcoe: Add support for FIP. FCoE discovery and keep-alive.

FIP is the new standard way to discover Fibre-Channel Forwarders (FCFs)
by sending solicitations and listening for advertisements from FCFs.

It also provides for keep-alives and period advertisements so that both
parties know they have connectivity.  If the FCF loses connectivity to
the storage fabric, it can send a Link Reset to inform the E_node.

This version is also compatible with pre-FIP implementations, so no
configured selection between FIP mode and non-FIP mode is required.

We wait a couple seconds after sending the initial solicitation
and then send an old-style FLOGI.  If we receive any FIP frames,
we use FIP only mode.  If the old FLOGI receives a response,
we disable FIP mode.  After every reset or link up, this
determination is repeated.

Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Vasu Dev <vasu.dev@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>

Showing 4 changed files with 1499 additions and 137 deletions Side-by-side Diff

drivers/scsi/fcoe/fcoe.c
... ... @@ -37,6 +37,7 @@
37 37 #include <net/rtnetlink.h>
38 38  
39 39 #include <scsi/fc/fc_encaps.h>
  40 +#include <scsi/fc/fc_fip.h>
40 41  
41 42 #include <scsi/libfc.h>
42 43 #include <scsi/fc_frame.h>
... ... @@ -71,7 +72,6 @@
71 72 static int fcoe_hostlist_remove(const struct fc_lport *);
72 73  
73 74 static int fcoe_check_wait_queue(struct fc_lport *);
74   -static void fcoe_recv_flogi(struct fcoe_softc *, struct fc_frame *, u8 *);
75 75 static int fcoe_device_notification(struct notifier_block *, ulong, void *);
76 76 static void fcoe_dev_setup(void);
77 77 static void fcoe_dev_cleanup(void);
... ... @@ -185,7 +185,7 @@
185 185  
186 186 /* Setup lport private data to point to fcoe softc */
187 187 fc = lport_priv(lp);
188   - fc->lp = lp;
  188 + fc->ctlr.lp = lp;
189 189 fc->real_dev = netdev;
190 190 fc->phys_dev = netdev;
191 191  
... ... @@ -210,9 +210,6 @@
210 210 if (fc_set_mfs(lp, mfs))
211 211 return -EINVAL;
212 212  
213   - if (!fcoe_link_ok(lp))
214   - lp->link_up = 1;
215   -
216 213 /* offload features support */
217 214 if (fc->real_dev->features & NETIF_F_SG)
218 215 lp->sg_supp = 1;
... ... @@ -242,7 +239,7 @@
242 239 fc->fcoe_pending_queue_active = 0;
243 240  
244 241 /* setup Source Mac Address */
245   - memcpy(fc->ctl_src_addr, fc->real_dev->dev_addr,
  242 + memcpy(fc->ctlr.ctl_src_addr, fc->real_dev->dev_addr,
246 243 fc->real_dev->addr_len);
247 244  
248 245 wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0);
... ... @@ -358,6 +355,8 @@
358 355  
359 356 /* Don't listen for Ethernet packets anymore */
360 357 dev_remove_pack(&fc->fcoe_packet_type);
  358 + dev_remove_pack(&fc->fip_packet_type);
  359 + fcoe_ctlr_destroy(&fc->ctlr);
361 360  
362 361 /* Cleanup the fc_lport */
363 362 fc_lport_destroy(lp);
... ... @@ -375,8 +374,10 @@
375 374 rtnl_lock();
376 375 memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
377 376 dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN);
378   - if (compare_ether_addr(fc->data_src_addr, (u8[6]) { 0 }))
379   - dev_unicast_delete(fc->real_dev, fc->data_src_addr, ETH_ALEN);
  377 + if (!is_zero_ether_addr(fc->ctlr.data_src_addr))
  378 + dev_unicast_delete(fc->real_dev,
  379 + fc->ctlr.data_src_addr, ETH_ALEN);
  380 + dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
380 381 rtnl_unlock();
381 382  
382 383 /* Free the per-CPU revieve threads */
... ... @@ -438,6 +439,58 @@
438 439 };
439 440  
440 441 /**
  442 + * fcoe_fip_recv - handle a received FIP frame.
  443 + * @skb: the receive skb
  444 + * @dev: associated &net_device
  445 + * @ptype: the &packet_type structure which was used to register this handler.
  446 + * @orig_dev: original receive &net_device, in case @dev is a bond.
  447 + *
  448 + * Returns: 0 for success
  449 + */
  450 +static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev,
  451 + struct packet_type *ptype,
  452 + struct net_device *orig_dev)
  453 +{
  454 + struct fcoe_softc *fc;
  455 +
  456 + fc = container_of(ptype, struct fcoe_softc, fip_packet_type);
  457 + fcoe_ctlr_recv(&fc->ctlr, skb);
  458 + return 0;
  459 +}
  460 +
  461 +/**
  462 + * fcoe_fip_send() - send an Ethernet-encapsulated FIP frame.
  463 + * @fip: FCoE controller.
  464 + * @skb: FIP Packet.
  465 + */
  466 +static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
  467 +{
  468 + skb->dev = fcoe_from_ctlr(fip)->real_dev;
  469 + dev_queue_xmit(skb);
  470 +}
  471 +
  472 +/**
  473 + * fcoe_update_src_mac() - Update Ethernet MAC filters.
  474 + * @fip: FCoE controller.
  475 + * @old: Unicast MAC address to delete if the MAC is non-zero.
  476 + * @new: Unicast MAC address to add.
  477 + *
  478 + * Remove any previously-set unicast MAC filter.
  479 + * Add secondary FCoE MAC address filter for our OUI.
  480 + */
  481 +static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new)
  482 +{
  483 + struct fcoe_softc *fc;
  484 +
  485 + fc = fcoe_from_ctlr(fip);
  486 + rtnl_lock();
  487 + if (!is_zero_ether_addr(old))
  488 + dev_unicast_delete(fc->real_dev, old, ETH_ALEN);
  489 + dev_unicast_add(fc->real_dev, new, ETH_ALEN);
  490 + rtnl_unlock();
  491 +}
  492 +
  493 +/**
441 494 * fcoe_if_create() - this function creates the fcoe interface
442 495 * @netdev: pointer the associated netdevice
443 496 *
... ... @@ -485,6 +538,18 @@
485 538 goto out_host_put;
486 539 }
487 540  
  541 + /*
  542 + * Initialize FIP.
  543 + */
  544 + fcoe_ctlr_init(&fc->ctlr);
  545 + fc->ctlr.send = fcoe_fip_send;
  546 + fc->ctlr.update_mac = fcoe_update_src_mac;
  547 +
  548 + fc->fip_packet_type.func = fcoe_fip_recv;
  549 + fc->fip_packet_type.type = htons(ETH_P_FIP);
  550 + fc->fip_packet_type.dev = fc->real_dev;
  551 + dev_add_pack(&fc->fip_packet_type);
  552 +
488 553 /* configure lport scsi host properties */
489 554 rc = fcoe_shost_config(lp, shost, &netdev->dev);
490 555 if (rc) {
... ... @@ -513,6 +578,9 @@
513 578  
514 579 fc_fabric_login(lp);
515 580  
  581 + if (!fcoe_link_ok(lp))
  582 + fcoe_ctlr_link_up(&fc->ctlr);
  583 +
516 584 dev_hold(netdev);
517 585  
518 586 return rc;
519 587  
... ... @@ -727,11 +795,13 @@
727 795 unsigned int cpu = 0;
728 796  
729 797 fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type);
730   - lp = fc->lp;
  798 + lp = fc->ctlr.lp;
731 799 if (unlikely(lp == NULL)) {
732 800 FC_DBG("cannot find hba structure");
733 801 goto err2;
734 802 }
  803 + if (!lp->link_up)
  804 + goto err2;
735 805  
736 806 if (unlikely(debug_fcoe)) {
737 807 FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p tail:%p "
... ... @@ -929,7 +999,6 @@
929 999 unsigned int hlen; /* header length implies the version */
930 1000 unsigned int tlen; /* trailer length */
931 1001 unsigned int elen; /* eth header, may include vlan */
932   - int flogi_in_progress = 0;
933 1002 struct fcoe_softc *fc;
934 1003 u8 sof, eof;
935 1004 struct fcoe_hdr *hp;
936 1005  
937 1006  
... ... @@ -937,31 +1006,19 @@
937 1006 WARN_ON((fr_len(fp) % sizeof(u32)) != 0);
938 1007  
939 1008 fc = lport_priv(lp);
940   - /*
941   - * if it is a flogi then we need to learn gw-addr
942   - * and my own fcid
943   - */
944 1009 fh = fc_frame_header_get(fp);
945   - if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ)) {
946   - if (fc_frame_payload_op(fp) == ELS_FLOGI) {
947   - fc->flogi_oxid = ntohs(fh->fh_ox_id);
948   - fc->address_mode = FCOE_FCOUI_ADDR_MODE;
949   - fc->flogi_progress = 1;
950   - flogi_in_progress = 1;
951   - } else if (fc->flogi_progress && ntoh24(fh->fh_s_id) != 0) {
952   - /*
953   - * Here we must've gotten an SID by accepting an FLOGI
954   - * from a point-to-point connection. Switch to using
955   - * the source mac based on the SID. The destination
956   - * MAC in this case would have been set by receving the
957   - * FLOGI.
958   - */
959   - fc_fcoe_set_mac(fc->data_src_addr, fh->fh_s_id);
960   - fc->flogi_progress = 0;
961   - }
  1010 + skb = fp_skb(fp);
  1011 + wlen = skb->len / FCOE_WORD_TO_BYTE;
  1012 +
  1013 + if (!lp->link_up) {
  1014 + kfree(skb);
  1015 + return 0;
962 1016 }
963 1017  
964   - skb = fp_skb(fp);
  1018 + if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) &&
  1019 + fcoe_ctlr_els_send(&fc->ctlr, skb))
  1020 + return 0;
  1021 +
965 1022 sof = fr_sof(fp);
966 1023 eof = fr_eof(fp);
967 1024  
968 1025  
969 1026  
970 1027  
... ... @@ -1016,16 +1073,16 @@
1016 1073 /* fill up mac and fcoe headers */
1017 1074 eh = eth_hdr(skb);
1018 1075 eh->h_proto = htons(ETH_P_FCOE);
1019   - if (fc->address_mode == FCOE_FCOUI_ADDR_MODE)
  1076 + if (fc->ctlr.map_dest)
1020 1077 fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id);
1021 1078 else
1022 1079 /* insert GW address */
1023   - memcpy(eh->h_dest, fc->dest_addr, ETH_ALEN);
  1080 + memcpy(eh->h_dest, fc->ctlr.dest_addr, ETH_ALEN);
1024 1081  
1025   - if (unlikely(flogi_in_progress))
1026   - memcpy(eh->h_source, fc->ctl_src_addr, ETH_ALEN);
  1082 + if (unlikely(fc->ctlr.flogi_oxid != FC_XID_UNKNOWN))
  1083 + memcpy(eh->h_source, fc->ctlr.ctl_src_addr, ETH_ALEN);
1027 1084 else
1028   - memcpy(eh->h_source, fc->data_src_addr, ETH_ALEN);
  1085 + memcpy(eh->h_source, fc->ctlr.data_src_addr, ETH_ALEN);
1029 1086  
1030 1087 hp = (struct fcoe_hdr *)(eh + 1);
1031 1088 memset(hp, 0, sizeof(*hp));
1032 1089  
... ... @@ -1125,11 +1182,9 @@
1125 1182 * Save source MAC address before discarding header.
1126 1183 */
1127 1184 fc = lport_priv(lp);
1128   - if (unlikely(fc->flogi_progress))
1129   - mac = eth_hdr(skb)->h_source;
1130   -
1131 1185 if (skb_is_nonlinear(skb))
1132 1186 skb_linearize(skb); /* not ideal */
  1187 + mac = eth_hdr(skb)->h_source;
1133 1188  
1134 1189 /*
1135 1190 * Frame length checks and setting up the header pointers
1136 1191  
... ... @@ -1204,72 +1259,17 @@
1204 1259 }
1205 1260 fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
1206 1261 }
1207   - /* non flogi and non data exchanges are handled here */
1208   - if (unlikely(fc->flogi_progress))
1209   - fcoe_recv_flogi(fc, fp, mac);
  1262 + if (unlikely(fc->ctlr.flogi_oxid != FC_XID_UNKNOWN) &&
  1263 + fcoe_ctlr_recv_flogi(&fc->ctlr, fp, mac)) {
  1264 + fc_frame_free(fp);
  1265 + continue;
  1266 + }
1210 1267 fc_exch_recv(lp, lp->emp, fp);
1211 1268 }
1212 1269 return 0;
1213 1270 }
1214 1271  
1215 1272 /**
1216   - * fcoe_recv_flogi() - flogi receive function
1217   - * @fc: associated fcoe_softc
1218   - * @fp: the recieved frame
1219   - * @sa: the source address of this flogi
1220   - *
1221   - * This is responsible to parse the flogi response and sets the corresponding
1222   - * mac address for the initiator, eitehr OUI based or GW based.
1223   - *
1224   - * Returns: none
1225   - */
1226   -static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa)
1227   -{
1228   - struct fc_frame_header *fh;
1229   - u8 op;
1230   -
1231   - fh = fc_frame_header_get(fp);
1232   - if (fh->fh_type != FC_TYPE_ELS)
1233   - return;
1234   - op = fc_frame_payload_op(fp);
1235   - if (op == ELS_LS_ACC && fh->fh_r_ctl == FC_RCTL_ELS_REP &&
1236   - fc->flogi_oxid == ntohs(fh->fh_ox_id)) {
1237   - /*
1238   - * FLOGI accepted.
1239   - * If the src mac addr is FC_OUI-based, then we mark the
1240   - * address_mode flag to use FC_OUI-based Ethernet DA.
1241   - * Otherwise we use the FCoE gateway addr
1242   - */
1243   - if (!compare_ether_addr(sa, (u8[6]) FC_FCOE_FLOGI_MAC)) {
1244   - fc->address_mode = FCOE_FCOUI_ADDR_MODE;
1245   - } else {
1246   - memcpy(fc->dest_addr, sa, ETH_ALEN);
1247   - fc->address_mode = FCOE_GW_ADDR_MODE;
1248   - }
1249   -
1250   - /*
1251   - * Remove any previously-set unicast MAC filter.
1252   - * Add secondary FCoE MAC address filter for our OUI.
1253   - */
1254   - rtnl_lock();
1255   - if (compare_ether_addr(fc->data_src_addr, (u8[6]) { 0 }))
1256   - dev_unicast_delete(fc->real_dev, fc->data_src_addr,
1257   - ETH_ALEN);
1258   - fc_fcoe_set_mac(fc->data_src_addr, fh->fh_d_id);
1259   - dev_unicast_add(fc->real_dev, fc->data_src_addr, ETH_ALEN);
1260   - rtnl_unlock();
1261   -
1262   - fc->flogi_progress = 0;
1263   - } else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) {
1264   - /*
1265   - * Save source MAC for point-to-point responses.
1266   - */
1267   - memcpy(fc->dest_addr, sa, ETH_ALEN);
1268   - fc->address_mode = FCOE_GW_ADDR_MODE;
1269   - }
1270   -}
1271   -
1272   -/**
1273 1273 * fcoe_watchdog() - fcoe timer callback
1274 1274 * @vp:
1275 1275 *
... ... @@ -1285,8 +1285,8 @@
1285 1285  
1286 1286 read_lock(&fcoe_hostlist_lock);
1287 1287 list_for_each_entry(fc, &fcoe_hostlist, list) {
1288   - if (fc->lp)
1289   - fcoe_check_wait_queue(fc->lp);
  1288 + if (fc->ctlr.lp)
  1289 + fcoe_check_wait_queue(fc->ctlr.lp);
1290 1290 }
1291 1291 read_unlock(&fcoe_hostlist_lock);
1292 1292  
1293 1293  
... ... @@ -1387,14 +1387,14 @@
1387 1387 struct net_device *real_dev = ptr;
1388 1388 struct fcoe_softc *fc;
1389 1389 struct fcoe_dev_stats *stats;
1390   - u32 new_link_up;
  1390 + u32 link_possible = 1;
1391 1391 u32 mfs;
1392 1392 int rc = NOTIFY_OK;
1393 1393  
1394 1394 read_lock(&fcoe_hostlist_lock);
1395 1395 list_for_each_entry(fc, &fcoe_hostlist, list) {
1396 1396 if (fc->real_dev == real_dev) {
1397   - lp = fc->lp;
  1397 + lp = fc->ctlr.lp;
1398 1398 break;
1399 1399 }
1400 1400 }
1401 1401  
1402 1402  
... ... @@ -1404,15 +1404,13 @@
1404 1404 goto out;
1405 1405 }
1406 1406  
1407   - new_link_up = lp->link_up;
1408 1407 switch (event) {
1409 1408 case NETDEV_DOWN:
1410 1409 case NETDEV_GOING_DOWN:
1411   - new_link_up = 0;
  1410 + link_possible = 0;
1412 1411 break;
1413 1412 case NETDEV_UP:
1414 1413 case NETDEV_CHANGE:
1415   - new_link_up = !fcoe_link_ok(lp);
1416 1414 break;
1417 1415 case NETDEV_CHANGEMTU:
1418 1416 mfs = fc->real_dev->mtu -
1419 1417  
1420 1418  
... ... @@ -1420,22 +1418,18 @@
1420 1418 sizeof(struct fcoe_crc_eof));
1421 1419 if (mfs >= FC_MIN_MAX_FRAME)
1422 1420 fc_set_mfs(lp, mfs);
1423   - new_link_up = !fcoe_link_ok(lp);
1424 1421 break;
1425 1422 case NETDEV_REGISTER:
1426 1423 break;
1427 1424 default:
1428   - FC_DBG("unknown event %ld call", event);
  1425 + FC_DBG("Unknown event %ld from netdev netlink\n", event);
1429 1426 }
1430   - if (lp->link_up != new_link_up) {
1431   - if (new_link_up)
1432   - fc_linkup(lp);
1433   - else {
1434   - stats = fc_lport_get_stats(lp);
1435   - stats->LinkFailureCount++;
1436   - fc_linkdown(lp);
1437   - fcoe_clean_pending_queue(lp);
1438   - }
  1427 + if (link_possible && !fcoe_link_ok(lp))
  1428 + fcoe_ctlr_link_up(&fc->ctlr);
  1429 + else if (fcoe_ctlr_link_down(&fc->ctlr)) {
  1430 + stats = fc_lport_get_stats(lp);
  1431 + stats->LinkFailureCount++;
  1432 + fcoe_clean_pending_queue(lp);
1439 1433 }
1440 1434 out:
1441 1435 return rc;
... ... @@ -1761,7 +1755,7 @@
1761 1755  
1762 1756 fc = fcoe_hostlist_lookup_softc(netdev);
1763 1757  
1764   - return (fc) ? fc->lp : NULL;
  1758 + return (fc) ? fc->ctlr.lp : NULL;
1765 1759 }
1766 1760 EXPORT_SYMBOL_GPL(fcoe_hostlist_lookup);
1767 1761  
drivers/scsi/fcoe/fcoe.h
... ... @@ -26,10 +26,6 @@
26 26 #define FCOE_MAX_QUEUE_DEPTH 256
27 27 #define FCOE_LOW_QUEUE_DEPTH 32
28 28  
29   -/* destination address mode */
30   -#define FCOE_GW_ADDR_MODE 0x00
31   -#define FCOE_FCOUI_ADDR_MODE 0x01
32   -
33 29 #define FCOE_WORD_TO_BYTE 4
34 30  
35 31 #define FCOE_VERSION "0.1"
36 32  
37 33  
38 34  
... ... @@ -59,23 +55,16 @@
59 55 */
60 56 struct fcoe_softc {
61 57 struct list_head list;
62   - struct fc_lport *lp;
63 58 struct net_device *real_dev;
64 59 struct net_device *phys_dev; /* device with ethtool_ops */
65 60 struct packet_type fcoe_packet_type;
  61 + struct packet_type fip_packet_type;
66 62 struct sk_buff_head fcoe_pending_queue;
67 63 u8 fcoe_pending_queue_active;
68   -
69   - u8 dest_addr[ETH_ALEN];
70   - u8 ctl_src_addr[ETH_ALEN];
71   - u8 data_src_addr[ETH_ALEN];
72   - /*
73   - * fcoe protocol address learning related stuff
74   - */
75   - u16 flogi_oxid;
76   - u8 flogi_progress;
77   - u8 address_mode;
  64 + struct fcoe_ctlr ctlr;
78 65 };
  66 +
  67 +#define fcoe_from_ctlr(fc) container_of(fc, struct fcoe_softc, ctlr)
79 68  
80 69 static inline struct net_device *fcoe_netdev(
81 70 const struct fc_lport *lp)
drivers/scsi/fcoe/libfcoe.c
Changes suppressed. Click to show
1 1 /*
2   - * Copyright(c) 2009 Intel Corporation. All rights reserved.
  2 + * Copyright (c) 2008-2009 Cisco Systems, Inc. All rights reserved.
  3 + * Copyright (c) 2009 Intel Corporation. All rights reserved.
3 4 *
4 5 * This program is free software; you can redistribute it and/or modify it
5 6 * under the terms and conditions of the GNU General Public License,
6 7  
7 8  
8 9  
9 10  
10 11  
11 12  
... ... @@ -17,14 +18,1260 @@
17 18 * Maintained at www.Open-FCoE.org
18 19 */
19 20  
  21 +#include <linux/types.h>
20 22 #include <linux/module.h>
  23 +#include <linux/kernel.h>
  24 +#include <linux/list.h>
  25 +#include <linux/spinlock.h>
  26 +#include <linux/timer.h>
21 27 #include <linux/netdevice.h>
  28 +#include <linux/etherdevice.h>
  29 +#include <linux/ethtool.h>
  30 +#include <linux/if_ether.h>
  31 +#include <linux/if_vlan.h>
  32 +#include <linux/netdevice.h>
  33 +#include <linux/errno.h>
  34 +#include <linux/bitops.h>
  35 +#include <net/rtnetlink.h>
22 36  
  37 +#include <scsi/fc/fc_els.h>
  38 +#include <scsi/fc/fc_fs.h>
  39 +#include <scsi/fc/fc_fip.h>
  40 +#include <scsi/fc/fc_encaps.h>
  41 +#include <scsi/fc/fc_fcoe.h>
  42 +
23 43 #include <scsi/libfc.h>
  44 +#include <scsi/libfcoe.h>
24 45  
25 46 MODULE_AUTHOR("Open-FCoE.org");
26   -MODULE_DESCRIPTION("FCoE");
  47 +MODULE_DESCRIPTION("FIP discovery protocol support for FCoE HBAs");
27 48 MODULE_LICENSE("GPL v2");
  49 +
  50 +#define FCOE_CTLR_MIN_FKA 500 /* min keep alive (mS) */
  51 +#define FCOE_CTLR_DEF_FKA FIP_DEF_FKA /* default keep alive (mS) */
  52 +
  53 +static void fcoe_ctlr_timeout(unsigned long);
  54 +static void fcoe_ctlr_link_work(struct work_struct *);
  55 +static void fcoe_ctlr_recv_work(struct work_struct *);
  56 +
  57 +static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS;
  58 +
  59 +static u32 fcoe_ctlr_debug; /* 1 for basic, 2 for noisy debug */
  60 +
  61 +#define FIP_DBG_LVL(level, fmt, args...) \
  62 + do { \
  63 + if (fcoe_ctlr_debug >= (level)) \
  64 + FC_DBG(fmt, ##args); \
  65 + } while (0)
  66 +
  67 +#define FIP_DBG(fmt, args...) FIP_DBG_LVL(1, fmt, ##args)
  68 +
  69 +/*
  70 + * Return non-zero if FCF fcoe_size has been validated.
  71 + */
  72 +static inline int fcoe_ctlr_mtu_valid(const struct fcoe_fcf *fcf)
  73 +{
  74 + return (fcf->flags & FIP_FL_SOL) != 0;
  75 +}
  76 +
  77 +/*
  78 + * Return non-zero if the FCF is usable.
  79 + */
  80 +static inline int fcoe_ctlr_fcf_usable(struct fcoe_fcf *fcf)
  81 +{
  82 + u16 flags = FIP_FL_SOL | FIP_FL_AVAIL;
  83 +
  84 + return (fcf->flags & flags) == flags;
  85 +}
  86 +
  87 +/**
  88 + * fcoe_ctlr_init() - Initialize the FCoE Controller instance.
  89 + * @fip: FCoE controller.
  90 + */
  91 +void fcoe_ctlr_init(struct fcoe_ctlr *fip)
  92 +{
  93 + fip->state = FIP_ST_LINK_WAIT;
  94 + INIT_LIST_HEAD(&fip->fcfs);
  95 + spin_lock_init(&fip->lock);
  96 + fip->flogi_oxid = FC_XID_UNKNOWN;
  97 + setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip);
  98 + INIT_WORK(&fip->link_work, fcoe_ctlr_link_work);
  99 + INIT_WORK(&fip->recv_work, fcoe_ctlr_recv_work);
  100 + skb_queue_head_init(&fip->fip_recv_list);
  101 +}
  102 +EXPORT_SYMBOL(fcoe_ctlr_init);
  103 +
  104 +/**
  105 + * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller.
  106 + * @fip: FCoE controller.
  107 + *
  108 + * Called with &fcoe_ctlr lock held.
  109 + */
  110 +static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip)
  111 +{
  112 + struct fcoe_fcf *fcf;
  113 + struct fcoe_fcf *next;
  114 +
  115 + fip->sel_fcf = NULL;
  116 + list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
  117 + list_del(&fcf->list);
  118 + kfree(fcf);
  119 + }
  120 + fip->fcf_count = 0;
  121 + fip->sel_time = 0;
  122 +}
  123 +
  124 +/**
  125 + * fcoe_ctrl_destroy() - Disable and tear-down the FCoE controller.
  126 + * @fip: FCoE controller.
  127 + *
  128 + * This is called by FCoE drivers before freeing the &fcoe_ctlr.
  129 + *
  130 + * The receive handler will have been deleted before this to guarantee
  131 + * that no more recv_work will be scheduled.
  132 + *
  133 + * The timer routine will simply return once we set FIP_ST_DISABLED.
  134 + * This guarantees that no further timeouts or work will be scheduled.
  135 + */
  136 +void fcoe_ctlr_destroy(struct fcoe_ctlr *fip)
  137 +{
  138 + flush_work(&fip->recv_work);
  139 + spin_lock_bh(&fip->lock);
  140 + fip->state = FIP_ST_DISABLED;
  141 + fcoe_ctlr_reset_fcfs(fip);
  142 + spin_unlock_bh(&fip->lock);
  143 + del_timer_sync(&fip->timer);
  144 + flush_work(&fip->link_work);
  145 +}
  146 +EXPORT_SYMBOL(fcoe_ctlr_destroy);
  147 +
  148 +/**
  149 + * fcoe_ctlr_fcoe_size() - Return the maximum FCoE size required for VN_Port.
  150 + * @fip: FCoE controller.
  151 + *
  152 + * Returns the maximum packet size including the FCoE header and trailer,
  153 + * but not including any Ethernet or VLAN headers.
  154 + */
  155 +static inline u32 fcoe_ctlr_fcoe_size(struct fcoe_ctlr *fip)
  156 +{
  157 + /*
  158 + * Determine the max FCoE frame size allowed, including
  159 + * FCoE header and trailer.
  160 + * Note: lp->mfs is currently the payload size, not the frame size.
  161 + */
  162 + return fip->lp->mfs + sizeof(struct fc_frame_header) +
  163 + sizeof(struct fcoe_hdr) + sizeof(struct fcoe_crc_eof);
  164 +}
  165 +
  166 +/**
  167 + * fcoe_ctlr_solicit() - Send a solicitation.
  168 + * @fip: FCoE controller.
  169 + * @fcf: Destination FCF. If NULL, a multicast solicitation is sent.
  170 + */
  171 +static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf)
  172 +{
  173 + struct sk_buff *skb;
  174 + struct fip_sol {
  175 + struct ethhdr eth;
  176 + struct fip_header fip;
  177 + struct {
  178 + struct fip_mac_desc mac;
  179 + struct fip_wwn_desc wwnn;
  180 + struct fip_size_desc size;
  181 + } __attribute__((packed)) desc;
  182 + } __attribute__((packed)) *sol;
  183 + u32 fcoe_size;
  184 +
  185 + skb = dev_alloc_skb(sizeof(*sol));
  186 + if (!skb)
  187 + return;
  188 +
  189 + sol = (struct fip_sol *)skb->data;
  190 +
  191 + memset(sol, 0, sizeof(*sol));
  192 + memcpy(sol->eth.h_dest, fcf ? fcf->fcf_mac : fcoe_all_fcfs, ETH_ALEN);
  193 + memcpy(sol->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
  194 + sol->eth.h_proto = htons(ETH_P_FIP);
  195 +
  196 + sol->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
  197 + sol->fip.fip_op = htons(FIP_OP_DISC);
  198 + sol->fip.fip_subcode = FIP_SC_SOL;
  199 + sol->fip.fip_dl_len = htons(sizeof(sol->desc) / FIP_BPW);
  200 + sol->fip.fip_flags = htons(FIP_FL_FPMA);
  201 +
  202 + sol->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC;
  203 + sol->desc.mac.fd_desc.fip_dlen = sizeof(sol->desc.mac) / FIP_BPW;
  204 + memcpy(sol->desc.mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
  205 +
  206 + sol->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
  207 + sol->desc.wwnn.fd_desc.fip_dlen = sizeof(sol->desc.wwnn) / FIP_BPW;
  208 + put_unaligned_be64(fip->lp->wwnn, &sol->desc.wwnn.fd_wwn);
  209 +
  210 + fcoe_size = fcoe_ctlr_fcoe_size(fip);
  211 + sol->desc.size.fd_desc.fip_dtype = FIP_DT_FCOE_SIZE;
  212 + sol->desc.size.fd_desc.fip_dlen = sizeof(sol->desc.size) / FIP_BPW;
  213 + sol->desc.size.fd_size = htons(fcoe_size);
  214 +
  215 + skb_put(skb, sizeof(*sol));
  216 + skb->protocol = htons(ETH_P_802_3);
  217 + skb_reset_mac_header(skb);
  218 + skb_reset_network_header(skb);
  219 + fip->send(fip, skb);
  220 +
  221 + if (!fcf)
  222 + fip->sol_time = jiffies;
  223 +}
  224 +
  225 +/**
  226 + * fcoe_ctlr_link_up() - Start FCoE controller.
  227 + * @fip: FCoE controller.
  228 + *
  229 + * Called from the LLD when the network link is ready.
  230 + */
  231 +void fcoe_ctlr_link_up(struct fcoe_ctlr *fip)
  232 +{
  233 + spin_lock_bh(&fip->lock);
  234 + if (fip->state == FIP_ST_NON_FIP || fip->state == FIP_ST_AUTO) {
  235 + fip->last_link = 1;
  236 + fip->link = 1;
  237 + spin_unlock_bh(&fip->lock);
  238 + fc_linkup(fip->lp);
  239 + } else if (fip->state == FIP_ST_LINK_WAIT) {
  240 + fip->state = FIP_ST_AUTO;
  241 + fip->last_link = 1;
  242 + fip->link = 1;
  243 + spin_unlock_bh(&fip->lock);
  244 + FIP_DBG("%s", "setting AUTO mode.\n");
  245 + fc_linkup(fip->lp);
  246 + fcoe_ctlr_solicit(fip, NULL);
  247 + } else
  248 + spin_unlock_bh(&fip->lock);
  249 +}
  250 +EXPORT_SYMBOL(fcoe_ctlr_link_up);
  251 +
  252 +/**
  253 + * fcoe_ctlr_reset() - Reset FIP.
  254 + * @fip: FCoE controller.
  255 + * @new_state: FIP state to be entered.
  256 + *
  257 + * Returns non-zero if the link was up and now isn't.
  258 + */
  259 +static int fcoe_ctlr_reset(struct fcoe_ctlr *fip, enum fip_state new_state)
  260 +{
  261 + struct fc_lport *lp = fip->lp;
  262 + int link_dropped;
  263 +
  264 + spin_lock_bh(&fip->lock);
  265 + fcoe_ctlr_reset_fcfs(fip);
  266 + del_timer(&fip->timer);
  267 + fip->state = new_state;
  268 + fip->ctlr_ka_time = 0;
  269 + fip->port_ka_time = 0;
  270 + fip->sol_time = 0;
  271 + fip->flogi_oxid = FC_XID_UNKNOWN;
  272 + fip->map_dest = 0;
  273 + fip->last_link = 0;
  274 + link_dropped = fip->link;
  275 + fip->link = 0;
  276 + spin_unlock_bh(&fip->lock);
  277 +
  278 + if (link_dropped)
  279 + fc_linkdown(lp);
  280 +
  281 + if (new_state == FIP_ST_ENABLED) {
  282 + fcoe_ctlr_solicit(fip, NULL);
  283 + fc_linkup(lp);
  284 + link_dropped = 0;
  285 + }
  286 + return link_dropped;
  287 +}
  288 +
  289 +/**
  290 + * fcoe_ctlr_link_down() - Stop FCoE controller.
  291 + * @fip: FCoE controller.
  292 + *
  293 + * Returns non-zero if the link was up and now isn't.
  294 + *
  295 + * Called from the LLD when the network link is not ready.
  296 + * There may be multiple calls while the link is down.
  297 + */
  298 +int fcoe_ctlr_link_down(struct fcoe_ctlr *fip)
  299 +{
  300 + return fcoe_ctlr_reset(fip, FIP_ST_LINK_WAIT);
  301 +}
  302 +EXPORT_SYMBOL(fcoe_ctlr_link_down);
  303 +
  304 +/**
  305 + * fcoe_ctlr_send_keep_alive() - Send a keep-alive to the selected FCF.
  306 + * @fip: FCoE controller.
  307 + * @ports: 0 for controller keep-alive, 1 for port keep-alive.
  308 + * @sa: source MAC address.
  309 + *
  310 + * A controller keep-alive is sent every fka_period (typically 8 seconds).
  311 + * The source MAC is the native MAC address.
  312 + *
  313 + * A port keep-alive is sent every 90 seconds while logged in.
  314 + * The source MAC is the assigned mapped source address.
  315 + * The destination is the FCF's F-port.
  316 + */
  317 +static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa)
  318 +{
  319 + struct sk_buff *skb;
  320 + struct fip_kal {
  321 + struct ethhdr eth;
  322 + struct fip_header fip;
  323 + struct fip_mac_desc mac;
  324 + } __attribute__((packed)) *kal;
  325 + struct fip_vn_desc *vn;
  326 + u32 len;
  327 + struct fc_lport *lp;
  328 + struct fcoe_fcf *fcf;
  329 +
  330 + fcf = fip->sel_fcf;
  331 + lp = fip->lp;
  332 + if (!fcf || !fc_host_port_id(lp->host))
  333 + return;
  334 +
  335 + len = fcoe_ctlr_fcoe_size(fip) + sizeof(struct ethhdr);
  336 + BUG_ON(len < sizeof(*kal) + sizeof(*vn));
  337 + skb = dev_alloc_skb(len);
  338 + if (!skb)
  339 + return;
  340 +
  341 + kal = (struct fip_kal *)skb->data;
  342 + memset(kal, 0, len);
  343 + memcpy(kal->eth.h_dest, fcf->fcf_mac, ETH_ALEN);
  344 + memcpy(kal->eth.h_source, sa, ETH_ALEN);
  345 + kal->eth.h_proto = htons(ETH_P_FIP);
  346 +
  347 + kal->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
  348 + kal->fip.fip_op = htons(FIP_OP_CTRL);
  349 + kal->fip.fip_subcode = FIP_SC_KEEP_ALIVE;
  350 + kal->fip.fip_dl_len = htons((sizeof(kal->mac) +
  351 + ports * sizeof(*vn)) / FIP_BPW);
  352 + kal->fip.fip_flags = htons(FIP_FL_FPMA);
  353 +
  354 + kal->mac.fd_desc.fip_dtype = FIP_DT_MAC;
  355 + kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW;
  356 + memcpy(kal->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
  357 +
  358 + if (ports) {
  359 + vn = (struct fip_vn_desc *)(kal + 1);
  360 + vn->fd_desc.fip_dtype = FIP_DT_VN_ID;
  361 + vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW;
  362 + memcpy(vn->fd_mac, fip->data_src_addr, ETH_ALEN);
  363 + hton24(vn->fd_fc_id, fc_host_port_id(lp->host));
  364 + put_unaligned_be64(lp->wwpn, &vn->fd_wwpn);
  365 + }
  366 +
  367 + skb_put(skb, len);
  368 + skb->protocol = htons(ETH_P_802_3);
  369 + skb_reset_mac_header(skb);
  370 + skb_reset_network_header(skb);
  371 + fip->send(fip, skb);
  372 +}
  373 +
  374 +/**
  375 + * fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it.
  376 + * @fip: FCoE controller.
  377 + * @dtype: FIP descriptor type for the frame.
  378 + * @skb: FCoE ELS frame including FC header but no FCoE headers.
  379 + *
  380 + * Returns non-zero error code on failure.
  381 + *
  382 + * The caller must check that the length is a multiple of 4.
  383 + *
  384 + * The @skb must have enough headroom (28 bytes) and tailroom (8 bytes).
  385 + * Headroom includes the FIP encapsulation description, FIP header, and
  386 + * Ethernet header. The tailroom is for the FIP MAC descriptor.
  387 + */
  388 +static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip,
  389 + u8 dtype, struct sk_buff *skb)
  390 +{
  391 + struct fip_encaps_head {
  392 + struct ethhdr eth;
  393 + struct fip_header fip;
  394 + struct fip_encaps encaps;
  395 + } __attribute__((packed)) *cap;
  396 + struct fip_mac_desc *mac;
  397 + struct fcoe_fcf *fcf;
  398 + size_t dlen;
  399 +
  400 + fcf = fip->sel_fcf;
  401 + if (!fcf)
  402 + return -ENODEV;
  403 + dlen = sizeof(struct fip_encaps) + skb->len; /* len before push */
  404 + cap = (struct fip_encaps_head *)skb_push(skb, sizeof(*cap));
  405 +
  406 + memset(cap, 0, sizeof(*cap));
  407 + memcpy(cap->eth.h_dest, fcf->fcf_mac, ETH_ALEN);
  408 + memcpy(cap->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
  409 + cap->eth.h_proto = htons(ETH_P_FIP);
  410 +
  411 + cap->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
  412 + cap->fip.fip_op = htons(FIP_OP_LS);
  413 + cap->fip.fip_subcode = FIP_SC_REQ;
  414 + cap->fip.fip_dl_len = htons((dlen + sizeof(*mac)) / FIP_BPW);
  415 + cap->fip.fip_flags = htons(FIP_FL_FPMA);
  416 +
  417 + cap->encaps.fd_desc.fip_dtype = dtype;
  418 + cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW;
  419 +
  420 + mac = (struct fip_mac_desc *)skb_put(skb, sizeof(*mac));
  421 + memset(mac, 0, sizeof(mac));
  422 + mac->fd_desc.fip_dtype = FIP_DT_MAC;
  423 + mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW;
  424 + if (dtype != ELS_FLOGI)
  425 + memcpy(mac->fd_mac, fip->data_src_addr, ETH_ALEN);
  426 +
  427 + skb->protocol = htons(ETH_P_802_3);
  428 + skb_reset_mac_header(skb);
  429 + skb_reset_network_header(skb);
  430 + return 0;
  431 +}
  432 +
  433 +/**
  434 + * fcoe_ctlr_els_send() - Send an ELS frame encapsulated by FIP if appropriate.
  435 + * @fip: FCoE controller.
  436 + * @skb: FCoE ELS frame including FC header but no FCoE headers.
  437 + *
  438 + * Returns a non-zero error code if the frame should not be sent.
  439 + * Returns zero if the caller should send the frame with FCoE encapsulation.
  440 + *
  441 + * The caller must check that the length is a multiple of 4.
  442 + * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes).
  443 + */
  444 +int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
  445 +{
  446 + struct fc_frame_header *fh;
  447 + u16 old_xid;
  448 + u8 op;
  449 +
  450 + if (fip->state == FIP_ST_NON_FIP)
  451 + return 0;
  452 +
  453 + fh = (struct fc_frame_header *)skb->data;
  454 + op = *(u8 *)(fh + 1);
  455 +
  456 + switch (op) {
  457 + case ELS_FLOGI:
  458 + old_xid = fip->flogi_oxid;
  459 + fip->flogi_oxid = ntohs(fh->fh_ox_id);
  460 + if (fip->state == FIP_ST_AUTO) {
  461 + if (old_xid == FC_XID_UNKNOWN)
  462 + fip->flogi_count = 0;
  463 + fip->flogi_count++;
  464 + if (fip->flogi_count < 3)
  465 + goto drop;
  466 + fip->map_dest = 1;
  467 + return 0;
  468 + }
  469 + op = FIP_DT_FLOGI;
  470 + break;
  471 + case ELS_FDISC:
  472 + if (ntoh24(fh->fh_s_id))
  473 + return 0;
  474 + op = FIP_DT_FDISC;
  475 + break;
  476 + case ELS_LOGO:
  477 + if (fip->state != FIP_ST_ENABLED)
  478 + return 0;
  479 + if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI)
  480 + return 0;
  481 + op = FIP_DT_LOGO;
  482 + break;
  483 + case ELS_LS_ACC:
  484 + if (fip->flogi_oxid == FC_XID_UNKNOWN)
  485 + return 0;
  486 + if (!ntoh24(fh->fh_s_id))
  487 + return 0;
  488 + if (fip->state == FIP_ST_AUTO)
  489 + return 0;
  490 + /*
  491 + * Here we must've gotten an SID by accepting an FLOGI
  492 + * from a point-to-point connection. Switch to using
  493 + * the source mac based on the SID. The destination
  494 + * MAC in this case would have been set by receving the
  495 + * FLOGI.
  496 + */
  497 + fip->flogi_oxid = FC_XID_UNKNOWN;
  498 + fc_fcoe_set_mac(fip->data_src_addr, fh->fh_s_id);
  499 + return 0;
  500 + default:
  501 + if (fip->state != FIP_ST_ENABLED)
  502 + goto drop;
  503 + return 0;
  504 + }
  505 + if (fcoe_ctlr_encaps(fip, op, skb))
  506 + goto drop;
  507 + fip->send(fip, skb);
  508 + return -EINPROGRESS;
  509 +drop:
  510 + kfree_skb(skb);
  511 + return -EINVAL;
  512 +}
  513 +EXPORT_SYMBOL(fcoe_ctlr_els_send);
  514 +
  515 +/*
  516 + * fcoe_ctlr_age_fcfs() - Reset and free all old FCFs for a controller.
  517 + * @fip: FCoE controller.
  518 + *
  519 + * Called with lock held.
  520 + *
  521 + * An FCF is considered old if we have missed three advertisements.
  522 + * That is, there have been no valid advertisement from it for three
  523 + * times its keep-alive period including fuzz.
  524 + *
  525 + * In addition, determine the time when an FCF selection can occur.
  526 + */
  527 +static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
  528 +{
  529 + struct fcoe_fcf *fcf;
  530 + struct fcoe_fcf *next;
  531 + unsigned long sel_time = 0;
  532 +
  533 + list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
  534 + if (time_after(jiffies, fcf->time + fcf->fka_period * 3 +
  535 + msecs_to_jiffies(FIP_FCF_FUZZ * 3))) {
  536 + if (fip->sel_fcf == fcf)
  537 + fip->sel_fcf = NULL;
  538 + list_del(&fcf->list);
  539 + WARN_ON(!fip->fcf_count);
  540 + fip->fcf_count--;
  541 + kfree(fcf);
  542 + } else if (fcoe_ctlr_mtu_valid(fcf) &&
  543 + (!sel_time || time_before(sel_time, fcf->time))) {
  544 + sel_time = fcf->time;
  545 + }
  546 + }
  547 + if (sel_time) {
  548 + sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY);
  549 + fip->sel_time = sel_time;
  550 + if (time_before(sel_time, fip->timer.expires))
  551 + mod_timer(&fip->timer, sel_time);
  552 + } else {
  553 + fip->sel_time = 0;
  554 + }
  555 +}
  556 +
  557 +/**
  558 + * fcoe_ctlr_parse_adv() - Decode a FIP advertisement into a new FCF entry.
  559 + * @skb: received FIP advertisement frame
  560 + * @fcf: resulting FCF entry.
  561 + *
  562 + * Returns zero on a valid parsed advertisement,
  563 + * otherwise returns non zero value.
  564 + */
  565 +static int fcoe_ctlr_parse_adv(struct sk_buff *skb, struct fcoe_fcf *fcf)
  566 +{
  567 + struct fip_header *fiph;
  568 + struct fip_desc *desc = NULL;
  569 + struct fip_wwn_desc *wwn;
  570 + struct fip_fab_desc *fab;
  571 + struct fip_fka_desc *fka;
  572 + unsigned long t;
  573 + size_t rlen;
  574 + size_t dlen;
  575 +
  576 + memset(fcf, 0, sizeof(*fcf));
  577 + fcf->fka_period = msecs_to_jiffies(FCOE_CTLR_DEF_FKA);
  578 +
  579 + fiph = (struct fip_header *)skb->data;
  580 + fcf->flags = ntohs(fiph->fip_flags);
  581 +
  582 + rlen = ntohs(fiph->fip_dl_len) * 4;
  583 + if (rlen + sizeof(*fiph) > skb->len)
  584 + return -EINVAL;
  585 +
  586 + desc = (struct fip_desc *)(fiph + 1);
  587 + while (rlen > 0) {
  588 + dlen = desc->fip_dlen * FIP_BPW;
  589 + if (dlen < sizeof(*desc) || dlen > rlen)
  590 + return -EINVAL;
  591 + switch (desc->fip_dtype) {
  592 + case FIP_DT_PRI:
  593 + if (dlen != sizeof(struct fip_pri_desc))
  594 + goto len_err;
  595 + fcf->pri = ((struct fip_pri_desc *)desc)->fd_pri;
  596 + break;
  597 + case FIP_DT_MAC:
  598 + if (dlen != sizeof(struct fip_mac_desc))
  599 + goto len_err;
  600 + memcpy(fcf->fcf_mac,
  601 + ((struct fip_mac_desc *)desc)->fd_mac,
  602 + ETH_ALEN);
  603 + if (!is_valid_ether_addr(fcf->fcf_mac)) {
  604 + FIP_DBG("invalid MAC addr in FIP adv\n");
  605 + return -EINVAL;
  606 + }
  607 + break;
  608 + case FIP_DT_NAME:
  609 + if (dlen != sizeof(struct fip_wwn_desc))
  610 + goto len_err;
  611 + wwn = (struct fip_wwn_desc *)desc;
  612 + fcf->switch_name = get_unaligned_be64(&wwn->fd_wwn);
  613 + break;
  614 + case FIP_DT_FAB:
  615 + if (dlen != sizeof(struct fip_fab_desc))
  616 + goto len_err;
  617 + fab = (struct fip_fab_desc *)desc;
  618 + fcf->fabric_name = get_unaligned_be64(&fab->fd_wwn);
  619 + fcf->vfid = ntohs(fab->fd_vfid);
  620 + fcf->fc_map = ntoh24(fab->fd_map);
  621 + break;
  622 + case FIP_DT_FKA:
  623 + if (dlen != sizeof(struct fip_fka_desc))
  624 + goto len_err;
  625 + fka = (struct fip_fka_desc *)desc;
  626 + t = ntohl(fka->fd_fka_period);
  627 + if (t >= FCOE_CTLR_MIN_FKA)
  628 + fcf->fka_period = msecs_to_jiffies(t);
  629 + break;
  630 + case FIP_DT_MAP_OUI:
  631 + case FIP_DT_FCOE_SIZE:
  632 + case FIP_DT_FLOGI:
  633 + case FIP_DT_FDISC:
  634 + case FIP_DT_LOGO:
  635 + case FIP_DT_ELP:
  636 + default:
  637 + FIP_DBG("unexpected descriptor type %x in FIP adv\n",
  638 + desc->fip_dtype);
  639 + /* standard says ignore unknown descriptors >= 128 */
  640 + if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
  641 + return -EINVAL;
  642 + continue;
  643 + }
  644 + desc = (struct fip_desc *)((char *)desc + dlen);
  645 + rlen -= dlen;
  646 + }
  647 + if (!fcf->fc_map || (fcf->fc_map & 0x10000))
  648 + return -EINVAL;
  649 + if (!fcf->switch_name || !fcf->fabric_name)
  650 + return -EINVAL;
  651 + return 0;
  652 +
  653 +len_err:
  654 + FIP_DBG("FIP length error in descriptor type %x len %zu\n",
  655 + desc->fip_dtype, dlen);
  656 + return -EINVAL;
  657 +}
  658 +
  659 +/**
  660 + * fcoe_ctlr_recv_adv() - Handle an incoming advertisement.
  661 + * @fip: FCoE controller.
  662 + * @skb: Received FIP packet.
  663 + */
  664 +static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
  665 +{
  666 + struct fcoe_fcf *fcf;
  667 + struct fcoe_fcf new;
  668 + struct fcoe_fcf *found;
  669 + unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV);
  670 + int first = 0;
  671 + int mtu_valid;
  672 +
  673 + if (fcoe_ctlr_parse_adv(skb, &new))
  674 + return;
  675 +
  676 + spin_lock_bh(&fip->lock);
  677 + first = list_empty(&fip->fcfs);
  678 + found = NULL;
  679 + list_for_each_entry(fcf, &fip->fcfs, list) {
  680 + if (fcf->switch_name == new.switch_name &&
  681 + fcf->fabric_name == new.fabric_name &&
  682 + fcf->fc_map == new.fc_map &&
  683 + compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) {
  684 + found = fcf;
  685 + break;
  686 + }
  687 + }
  688 + if (!found) {
  689 + if (fip->fcf_count >= FCOE_CTLR_FCF_LIMIT)
  690 + goto out;
  691 +
  692 + fcf = kmalloc(sizeof(*fcf), GFP_ATOMIC);
  693 + if (!fcf)
  694 + goto out;
  695 +
  696 + fip->fcf_count++;
  697 + memcpy(fcf, &new, sizeof(new));
  698 + list_add(&fcf->list, &fip->fcfs);
  699 + } else {
  700 + /*
  701 + * Flags in advertisements are ignored once the FCF is
  702 + * selected. Flags in unsolicited advertisements are
  703 + * ignored after a usable solicited advertisement
  704 + * has been received.
  705 + */
  706 + if (fcf == fip->sel_fcf) {
  707 + fip->ctlr_ka_time -= fcf->fka_period;
  708 + fip->ctlr_ka_time += new.fka_period;
  709 + if (time_before(fip->ctlr_ka_time, fip->timer.expires))
  710 + mod_timer(&fip->timer, fip->ctlr_ka_time);
  711 + } else if (!fcoe_ctlr_fcf_usable(fcf))
  712 + fcf->flags = new.flags;
  713 + fcf->fka_period = new.fka_period;
  714 + memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN);
  715 + }
  716 + mtu_valid = fcoe_ctlr_mtu_valid(fcf);
  717 + fcf->time = jiffies;
  718 + FIP_DBG_LVL(found ? 2 : 1, "%s FCF for fab %llx map %x val %d\n",
  719 + found ? "old" : "new",
  720 + fcf->fabric_name, fcf->fc_map, mtu_valid);
  721 +
  722 + /*
  723 + * If this advertisement is not solicited and our max receive size
  724 + * hasn't been verified, send a solicited advertisement.
  725 + */
  726 + if (!mtu_valid)
  727 + fcoe_ctlr_solicit(fip, fcf);
  728 +
  729 + /*
  730 + * If its been a while since we did a solicit, and this is
  731 + * the first advertisement we've received, do a multicast
  732 + * solicitation to gather as many advertisements as we can
  733 + * before selection occurs.
  734 + */
  735 + if (first && time_after(jiffies, fip->sol_time + sol_tov))
  736 + fcoe_ctlr_solicit(fip, NULL);
  737 +
  738 + /*
  739 + * If this is the first validated FCF, note the time and
  740 + * set a timer to trigger selection.
  741 + */
  742 + if (mtu_valid && !fip->sel_time && fcoe_ctlr_fcf_usable(fcf)) {
  743 + fip->sel_time = jiffies +
  744 + msecs_to_jiffies(FCOE_CTLR_START_DELAY);
  745 + if (!timer_pending(&fip->timer) ||
  746 + time_before(fip->sel_time, fip->timer.expires))
  747 + mod_timer(&fip->timer, fip->sel_time);
  748 + }
  749 +out:
  750 + spin_unlock_bh(&fip->lock);
  751 +}
  752 +
  753 +/**
  754 + * fcoe_ctlr_recv_els() - Handle an incoming FIP-encapsulated ELS frame.
  755 + * @fip: FCoE controller.
  756 + * @skb: Received FIP packet.
  757 + */
  758 +static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
  759 +{
  760 + struct fc_lport *lp = fip->lp;
  761 + struct fip_header *fiph;
  762 + struct fc_frame *fp;
  763 + struct fc_frame_header *fh = NULL;
  764 + struct fip_desc *desc;
  765 + struct fip_encaps *els;
  766 + struct fcoe_dev_stats *stats;
  767 + enum fip_desc_type els_dtype = 0;
  768 + u8 els_op;
  769 + u8 sub;
  770 + u8 granted_mac[ETH_ALEN] = { 0 };
  771 + size_t els_len = 0;
  772 + size_t rlen;
  773 + size_t dlen;
  774 +
  775 + fiph = (struct fip_header *)skb->data;
  776 + sub = fiph->fip_subcode;
  777 + if (sub != FIP_SC_REQ && sub != FIP_SC_REP)
  778 + goto drop;
  779 +
  780 + rlen = ntohs(fiph->fip_dl_len) * 4;
  781 + if (rlen + sizeof(*fiph) > skb->len)
  782 + goto drop;
  783 +
  784 + desc = (struct fip_desc *)(fiph + 1);
  785 + while (rlen > 0) {
  786 + dlen = desc->fip_dlen * FIP_BPW;
  787 + if (dlen < sizeof(*desc) || dlen > rlen)
  788 + goto drop;
  789 + switch (desc->fip_dtype) {
  790 + case FIP_DT_MAC:
  791 + if (dlen != sizeof(struct fip_mac_desc))
  792 + goto len_err;
  793 + memcpy(granted_mac,
  794 + ((struct fip_mac_desc *)desc)->fd_mac,
  795 + ETH_ALEN);
  796 + if (!is_valid_ether_addr(granted_mac)) {
  797 + FIP_DBG("invalid MAC addrs in FIP ELS\n");
  798 + goto drop;
  799 + }
  800 + break;
  801 + case FIP_DT_FLOGI:
  802 + case FIP_DT_FDISC:
  803 + case FIP_DT_LOGO:
  804 + case FIP_DT_ELP:
  805 + if (fh)
  806 + goto drop;
  807 + if (dlen < sizeof(*els) + sizeof(*fh) + 1)
  808 + goto len_err;
  809 + els_len = dlen - sizeof(*els);
  810 + els = (struct fip_encaps *)desc;
  811 + fh = (struct fc_frame_header *)(els + 1);
  812 + els_dtype = desc->fip_dtype;
  813 + break;
  814 + default:
  815 + FIP_DBG("unexpected descriptor type %x "
  816 + "in FIP adv\n", desc->fip_dtype);
  817 + /* standard says ignore unknown descriptors >= 128 */
  818 + if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
  819 + goto drop;
  820 + continue;
  821 + }
  822 + desc = (struct fip_desc *)((char *)desc + dlen);
  823 + rlen -= dlen;
  824 + }
  825 +
  826 + if (!fh)
  827 + goto drop;
  828 + els_op = *(u8 *)(fh + 1);
  829 +
  830 + if (els_dtype == FIP_DT_FLOGI && sub == FIP_SC_REP &&
  831 + fip->flogi_oxid == ntohs(fh->fh_ox_id) &&
  832 + els_op == ELS_LS_ACC && is_valid_ether_addr(granted_mac)) {
  833 + fip->flogi_oxid = FC_XID_UNKNOWN;
  834 + fip->update_mac(fip, fip->data_src_addr, granted_mac);
  835 + memcpy(fip->data_src_addr, granted_mac, ETH_ALEN);
  836 + }
  837 +
  838 + /*
  839 + * Convert skb into an fc_frame containing only the ELS.
  840 + */
  841 + skb_pull(skb, (u8 *)fh - skb->data);
  842 + skb_trim(skb, els_len);
  843 + fp = (struct fc_frame *)skb;
  844 + fc_frame_init(fp);
  845 + fr_sof(fp) = FC_SOF_I3;
  846 + fr_eof(fp) = FC_EOF_T;
  847 + fr_dev(fp) = lp;
  848 +
  849 + stats = fc_lport_get_stats(lp);
  850 + stats->RxFrames++;
  851 + stats->RxWords += skb->len / FIP_BPW;
  852 +
  853 + fc_exch_recv(lp, lp->emp, fp);
  854 + return;
  855 +
  856 +len_err:
  857 + FIP_DBG("FIP length error in descriptor type %x len %zu\n",
  858 + desc->fip_dtype, dlen);
  859 +drop:
  860 + kfree_skb(skb);
  861 +}
  862 +
  863 +/**
  864 + * fcoe_ctlr_recv_els() - Handle an incoming link reset frame.
  865 + * @fip: FCoE controller.
  866 + * @fh: Received FIP header.
  867 + *
  868 + * There may be multiple VN_Port descriptors.
  869 + * The overall length has already been checked.
  870 + */
  871 +static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
  872 + struct fip_header *fh)
  873 +{
  874 + struct fip_desc *desc;
  875 + struct fip_mac_desc *mp;
  876 + struct fip_wwn_desc *wp;
  877 + struct fip_vn_desc *vp;
  878 + size_t rlen;
  879 + size_t dlen;
  880 + struct fcoe_fcf *fcf = fip->sel_fcf;
  881 + struct fc_lport *lp = fip->lp;
  882 + u32 desc_mask;
  883 +
  884 + FIP_DBG("Clear Virtual Link received\n");
  885 + if (!fcf)
  886 + return;
  887 + if (!fcf || !fc_host_port_id(lp->host))
  888 + return;
  889 +
  890 + /*
  891 + * mask of required descriptors. Validating each one clears its bit.
  892 + */
  893 + desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) | BIT(FIP_DT_VN_ID);
  894 +
  895 + rlen = ntohs(fh->fip_dl_len) * FIP_BPW;
  896 + desc = (struct fip_desc *)(fh + 1);
  897 + while (rlen >= sizeof(*desc)) {
  898 + dlen = desc->fip_dlen * FIP_BPW;
  899 + if (dlen > rlen)
  900 + return;
  901 + switch (desc->fip_dtype) {
  902 + case FIP_DT_MAC:
  903 + mp = (struct fip_mac_desc *)desc;
  904 + if (dlen < sizeof(*mp))
  905 + return;
  906 + if (compare_ether_addr(mp->fd_mac, fcf->fcf_mac))
  907 + return;
  908 + desc_mask &= ~BIT(FIP_DT_MAC);
  909 + break;
  910 + case FIP_DT_NAME:
  911 + wp = (struct fip_wwn_desc *)desc;
  912 + if (dlen < sizeof(*wp))
  913 + return;
  914 + if (get_unaligned_be64(&wp->fd_wwn) != fcf->switch_name)
  915 + return;
  916 + desc_mask &= ~BIT(FIP_DT_NAME);
  917 + break;
  918 + case FIP_DT_VN_ID:
  919 + vp = (struct fip_vn_desc *)desc;
  920 + if (dlen < sizeof(*vp))
  921 + return;
  922 + if (compare_ether_addr(vp->fd_mac,
  923 + fip->data_src_addr) == 0 &&
  924 + get_unaligned_be64(&vp->fd_wwpn) == lp->wwpn &&
  925 + ntoh24(vp->fd_fc_id) == fc_host_port_id(lp->host))
  926 + desc_mask &= ~BIT(FIP_DT_VN_ID);
  927 + break;
  928 + default:
  929 + /* standard says ignore unknown descriptors >= 128 */
  930 + if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
  931 + return;
  932 + break;
  933 + }
  934 + desc = (struct fip_desc *)((char *)desc + dlen);
  935 + rlen -= dlen;
  936 + }
  937 +
  938 + /*
  939 + * reset only if all required descriptors were present and valid.
  940 + */
  941 + if (desc_mask) {
  942 + FIP_DBG("missing descriptors mask %x\n", desc_mask);
  943 + } else {
  944 + FIP_DBG("performing Clear Virtual Link\n");
  945 + fcoe_ctlr_reset(fip, FIP_ST_ENABLED);
  946 + }
  947 +}
  948 +
  949 +/**
  950 + * fcoe_ctlr_recv() - Receive a FIP frame.
  951 + * @fip: FCoE controller.
  952 + * @skb: Received FIP packet.
  953 + *
  954 + * This is called from NET_RX_SOFTIRQ.
  955 + */
  956 +void fcoe_ctlr_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
  957 +{
  958 + spin_lock_bh(&fip->fip_recv_list.lock);
  959 + __skb_queue_tail(&fip->fip_recv_list, skb);
  960 + spin_unlock_bh(&fip->fip_recv_list.lock);
  961 + schedule_work(&fip->recv_work);
  962 +}
  963 +EXPORT_SYMBOL(fcoe_ctlr_recv);
  964 +
  965 +/**
  966 + * fcoe_ctlr_recv_handler() - Receive a FIP frame.
  967 + * @fip: FCoE controller.
  968 + * @skb: Received FIP packet.
  969 + *
  970 + * Returns non-zero if the frame is dropped.
  971 + */
  972 +static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb)
  973 +{
  974 + struct fip_header *fiph;
  975 + struct ethhdr *eh;
  976 + enum fip_state state;
  977 + u16 op;
  978 + u8 sub;
  979 +
  980 + if (skb_linearize(skb))
  981 + goto drop;
  982 + if (skb->len < sizeof(*fiph))
  983 + goto drop;
  984 + eh = eth_hdr(skb);
  985 + if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) &&
  986 + compare_ether_addr(eh->h_dest, FIP_ALL_ENODE_MACS))
  987 + goto drop;
  988 + fiph = (struct fip_header *)skb->data;
  989 + op = ntohs(fiph->fip_op);
  990 + sub = fiph->fip_subcode;
  991 +
  992 + FIP_DBG_LVL(2, "ver %x op %x/%x dl %x fl %x\n",
  993 + FIP_VER_DECAPS(fiph->fip_ver), op, sub,
  994 + ntohs(fiph->fip_dl_len), ntohs(fiph->fip_flags));
  995 +
  996 + if (FIP_VER_DECAPS(fiph->fip_ver) != FIP_VER)
  997 + goto drop;
  998 + if (ntohs(fiph->fip_dl_len) * FIP_BPW + sizeof(*fiph) > skb->len)
  999 + goto drop;
  1000 +
  1001 + spin_lock_bh(&fip->lock);
  1002 + state = fip->state;
  1003 + if (state == FIP_ST_AUTO) {
  1004 + fip->map_dest = 0;
  1005 + fip->state = FIP_ST_ENABLED;
  1006 + state = FIP_ST_ENABLED;
  1007 + FIP_DBG("using FIP mode\n");
  1008 + }
  1009 + spin_unlock_bh(&fip->lock);
  1010 + if (state != FIP_ST_ENABLED)
  1011 + goto drop;
  1012 +
  1013 + if (op == FIP_OP_LS) {
  1014 + fcoe_ctlr_recv_els(fip, skb); /* consumes skb */
  1015 + return 0;
  1016 + }
  1017 + if (op == FIP_OP_DISC && sub == FIP_SC_ADV)
  1018 + fcoe_ctlr_recv_adv(fip, skb);
  1019 + else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK)
  1020 + fcoe_ctlr_recv_clr_vlink(fip, fiph);
  1021 + kfree_skb(skb);
  1022 + return 0;
  1023 +drop:
  1024 + kfree_skb(skb);
  1025 + return -1;
  1026 +}
  1027 +
  1028 +/**
  1029 + * fcoe_ctlr_select() - Select the best FCF, if possible.
  1030 + * @fip: FCoE controller.
  1031 + *
  1032 + * If there are conflicting advertisements, no FCF can be chosen.
  1033 + *
  1034 + * Called with lock held.
  1035 + */
  1036 +static void fcoe_ctlr_select(struct fcoe_ctlr *fip)
  1037 +{
  1038 + struct fcoe_fcf *fcf;
  1039 + struct fcoe_fcf *best = NULL;
  1040 +
  1041 + list_for_each_entry(fcf, &fip->fcfs, list) {
  1042 + FIP_DBG("consider FCF for fab %llx VFID %d map %x val %d\n",
  1043 + fcf->fabric_name, fcf->vfid,
  1044 + fcf->fc_map, fcoe_ctlr_mtu_valid(fcf));
  1045 + if (!fcoe_ctlr_fcf_usable(fcf)) {
  1046 + FIP_DBG("FCF for fab %llx map %x %svalid %savailable\n",
  1047 + fcf->fabric_name, fcf->fc_map,
  1048 + (fcf->flags & FIP_FL_SOL) ? "" : "in",
  1049 + (fcf->flags & FIP_FL_AVAIL) ? "" : "un");
  1050 + continue;
  1051 + }
  1052 + if (!best) {
  1053 + best = fcf;
  1054 + continue;
  1055 + }
  1056 + if (fcf->fabric_name != best->fabric_name ||
  1057 + fcf->vfid != best->vfid ||
  1058 + fcf->fc_map != best->fc_map) {
  1059 + FIP_DBG("conflicting fabric, VFID, or FC-MAP\n");
  1060 + return;
  1061 + }
  1062 + if (fcf->pri < best->pri)
  1063 + best = fcf;
  1064 + }
  1065 + fip->sel_fcf = best;
  1066 +}
  1067 +
  1068 +/**
  1069 + * fcoe_ctlr_timeout() - FIP timer function.
  1070 + * @arg: &fcoe_ctlr pointer.
  1071 + *
  1072 + * Ages FCFs. Triggers FCF selection if possible. Sends keep-alives.
  1073 + */
  1074 +static void fcoe_ctlr_timeout(unsigned long arg)
  1075 +{
  1076 + struct fcoe_ctlr *fip = (struct fcoe_ctlr *)arg;
  1077 + struct fcoe_fcf *sel;
  1078 + struct fcoe_fcf *fcf;
  1079 + unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD);
  1080 + DECLARE_MAC_BUF(buf);
  1081 + u8 send_ctlr_ka;
  1082 + u8 send_port_ka;
  1083 +
  1084 + spin_lock_bh(&fip->lock);
  1085 + if (fip->state == FIP_ST_DISABLED) {
  1086 + spin_unlock_bh(&fip->lock);
  1087 + return;
  1088 + }
  1089 +
  1090 + fcf = fip->sel_fcf;
  1091 + fcoe_ctlr_age_fcfs(fip);
  1092 +
  1093 + sel = fip->sel_fcf;
  1094 + if (!sel && fip->sel_time && time_after_eq(jiffies, fip->sel_time)) {
  1095 + fcoe_ctlr_select(fip);
  1096 + sel = fip->sel_fcf;
  1097 + fip->sel_time = 0;
  1098 + }
  1099 +
  1100 + if (sel != fcf) {
  1101 + fcf = sel; /* the old FCF may have been freed */
  1102 + if (sel) {
  1103 + printk(KERN_INFO "host%d: FIP selected "
  1104 + "Fibre-Channel Forwarder MAC %s\n",
  1105 + fip->lp->host->host_no,
  1106 + print_mac(buf, sel->fcf_mac));
  1107 + memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN);
  1108 + fip->port_ka_time = jiffies +
  1109 + msecs_to_jiffies(FIP_VN_KA_PERIOD);
  1110 + fip->ctlr_ka_time = jiffies + sel->fka_period;
  1111 + fip->link = 1;
  1112 + } else {
  1113 + printk(KERN_NOTICE "host%d: "
  1114 + "FIP Fibre-Channel Forwarder timed out. "
  1115 + "Starting FCF discovery.\n",
  1116 + fip->lp->host->host_no);
  1117 + fip->link = 0;
  1118 + }
  1119 + schedule_work(&fip->link_work);
  1120 + }
  1121 +
  1122 + send_ctlr_ka = 0;
  1123 + send_port_ka = 0;
  1124 + if (sel) {
  1125 + if (time_after_eq(jiffies, fip->ctlr_ka_time)) {
  1126 + fip->ctlr_ka_time = jiffies + sel->fka_period;
  1127 + send_ctlr_ka = 1;
  1128 + }
  1129 + if (time_after(next_timer, fip->ctlr_ka_time))
  1130 + next_timer = fip->ctlr_ka_time;
  1131 +
  1132 + if (time_after_eq(jiffies, fip->port_ka_time)) {
  1133 + fip->port_ka_time += jiffies +
  1134 + msecs_to_jiffies(FIP_VN_KA_PERIOD);
  1135 + send_port_ka = 1;
  1136 + }
  1137 + if (time_after(next_timer, fip->port_ka_time))
  1138 + next_timer = fip->port_ka_time;
  1139 + mod_timer(&fip->timer, next_timer);
  1140 + } else if (fip->sel_time) {
  1141 + next_timer = fip->sel_time +
  1142 + msecs_to_jiffies(FCOE_CTLR_START_DELAY);
  1143 + mod_timer(&fip->timer, next_timer);
  1144 + }
  1145 + spin_unlock_bh(&fip->lock);
  1146 +
  1147 + if (send_ctlr_ka)
  1148 + fcoe_ctlr_send_keep_alive(fip, 0, fip->ctl_src_addr);
  1149 + if (send_port_ka)
  1150 + fcoe_ctlr_send_keep_alive(fip, 1, fip->data_src_addr);
  1151 +}
  1152 +
  1153 +/**
  1154 + * fcoe_ctlr_link_work() - worker thread function for link changes.
  1155 + * @work: pointer to link_work member inside &fcoe_ctlr.
  1156 + *
  1157 + * See if the link status has changed and if so, report it.
  1158 + *
  1159 + * This is here because fc_linkup() and fc_linkdown() must not
  1160 + * be called from the timer directly, since they use a mutex.
  1161 + */
  1162 +static void fcoe_ctlr_link_work(struct work_struct *work)
  1163 +{
  1164 + struct fcoe_ctlr *fip;
  1165 + int link;
  1166 + int last_link;
  1167 +
  1168 + fip = container_of(work, struct fcoe_ctlr, link_work);
  1169 + spin_lock_bh(&fip->lock);
  1170 + last_link = fip->last_link;
  1171 + link = fip->link;
  1172 + fip->last_link = link;
  1173 + spin_unlock_bh(&fip->lock);
  1174 +
  1175 + if (last_link != link) {
  1176 + if (link)
  1177 + fc_linkup(fip->lp);
  1178 + else
  1179 + fcoe_ctlr_reset(fip, FIP_ST_LINK_WAIT);
  1180 + }
  1181 +}
  1182 +
  1183 +/**
  1184 + * fcoe_ctlr_recv_work() - Worker thread function for receiving FIP frames.
  1185 + * @recv_work: pointer to recv_work member inside &fcoe_ctlr.
  1186 + */
  1187 +static void fcoe_ctlr_recv_work(struct work_struct *recv_work)
  1188 +{
  1189 + struct fcoe_ctlr *fip;
  1190 + struct sk_buff *skb;
  1191 +
  1192 + fip = container_of(recv_work, struct fcoe_ctlr, recv_work);
  1193 + spin_lock_bh(&fip->fip_recv_list.lock);
  1194 + while ((skb = __skb_dequeue(&fip->fip_recv_list))) {
  1195 + spin_unlock_bh(&fip->fip_recv_list.lock);
  1196 + fcoe_ctlr_recv_handler(fip, skb);
  1197 + spin_lock_bh(&fip->fip_recv_list.lock);
  1198 + }
  1199 + spin_unlock_bh(&fip->fip_recv_list.lock);
  1200 +}
  1201 +
  1202 +/**
  1203 + * fcoe_ctlr_recv_flogi() - snoop Pre-FIP receipt of FLOGI response or request.
  1204 + * @fip: FCoE controller.
  1205 + * @fp: FC frame.
  1206 + * @sa: Ethernet source MAC address from received FCoE frame.
  1207 + *
  1208 + * Snoop potential response to FLOGI or even incoming FLOGI.
  1209 + *
  1210 + * The caller has checked that we are waiting for login as indicated
  1211 + * by fip->flogi_oxid != FC_XID_UNKNOWN.
  1212 + *
  1213 + * The caller is responsible for freeing the frame.
  1214 + *
  1215 + * Return non-zero if the frame should not be delivered to libfc.
  1216 + */
  1217 +int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa)
  1218 +{
  1219 + struct fc_frame_header *fh;
  1220 + u8 op;
  1221 + u8 mac[ETH_ALEN];
  1222 +
  1223 + fh = fc_frame_header_get(fp);
  1224 + if (fh->fh_type != FC_TYPE_ELS)
  1225 + return 0;
  1226 +
  1227 + op = fc_frame_payload_op(fp);
  1228 + if (op == ELS_LS_ACC && fh->fh_r_ctl == FC_RCTL_ELS_REP &&
  1229 + fip->flogi_oxid == ntohs(fh->fh_ox_id)) {
  1230 +
  1231 + spin_lock_bh(&fip->lock);
  1232 + if (fip->state != FIP_ST_AUTO && fip->state != FIP_ST_NON_FIP) {
  1233 + spin_unlock_bh(&fip->lock);
  1234 + return -EINVAL;
  1235 + }
  1236 + fip->state = FIP_ST_NON_FIP;
  1237 + FIP_DBG("received FLOGI LS_ACC using non-FIP mode\n");
  1238 +
  1239 + /*
  1240 + * FLOGI accepted.
  1241 + * If the src mac addr is FC_OUI-based, then we mark the
  1242 + * address_mode flag to use FC_OUI-based Ethernet DA.
  1243 + * Otherwise we use the FCoE gateway addr
  1244 + */
  1245 + if (!compare_ether_addr(sa, (u8[6])FC_FCOE_FLOGI_MAC)) {
  1246 + fip->map_dest = 1;
  1247 + } else {
  1248 + memcpy(fip->dest_addr, sa, ETH_ALEN);
  1249 + fip->map_dest = 0;
  1250 + }
  1251 + fip->flogi_oxid = FC_XID_UNKNOWN;
  1252 + memcpy(mac, fip->data_src_addr, ETH_ALEN);
  1253 + fc_fcoe_set_mac(fip->data_src_addr, fh->fh_d_id);
  1254 + spin_unlock_bh(&fip->lock);
  1255 +
  1256 + fip->update_mac(fip, mac, fip->data_src_addr);
  1257 + } else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) {
  1258 + /*
  1259 + * Save source MAC for point-to-point responses.
  1260 + */
  1261 + spin_lock_bh(&fip->lock);
  1262 + if (fip->state == FIP_ST_AUTO || fip->state == FIP_ST_NON_FIP) {
  1263 + memcpy(fip->dest_addr, sa, ETH_ALEN);
  1264 + fip->map_dest = 0;
  1265 + if (fip->state == FIP_ST_NON_FIP)
  1266 + FIP_DBG("received FLOGI REQ, "
  1267 + "using non-FIP mode\n");
  1268 + fip->state = FIP_ST_NON_FIP;
  1269 + }
  1270 + spin_unlock_bh(&fip->lock);
  1271 + }
  1272 + return 0;
  1273 +}
  1274 +EXPORT_SYMBOL(fcoe_ctlr_recv_flogi);
28 1275  
29 1276 /**
30 1277 * fcoe_wwn_from_mac() - Converts 48-bit IEEE MAC address to 64-bit FC WWN.
include/scsi/libfcoe.h
1 1 /*
2   - * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
  2 + * Copyright (c) 2008-2009 Cisco Systems, Inc. All rights reserved.
  3 + * Copyright (c) 2007-2008 Intel Corporation. All rights reserved.
3 4 *
4 5 * This program is free software; you can redistribute it and/or modify it
5 6 * under the terms and conditions of the GNU General Public License,
6 7  
7 8  
... ... @@ -20,10 +21,141 @@
20 21 #ifndef _LIBFCOE_H
21 22 #define _LIBFCOE_H
22 23  
  24 +#include <linux/etherdevice.h>
  25 +#include <linux/if_ether.h>
23 26 #include <linux/netdevice.h>
24 27 #include <linux/skbuff.h>
  28 +#include <linux/workqueue.h>
25 29 #include <scsi/fc/fc_fcoe.h>
26 30 #include <scsi/libfc.h>
  31 +
  32 +/*
  33 + * FIP tunable parameters.
  34 + */
  35 +#define FCOE_CTLR_START_DELAY 2000 /* mS after first adv. to choose FCF */
  36 +#define FCOE_CTRL_SOL_TOV 2000 /* min. solicitation interval (mS) */
  37 +#define FCOE_CTLR_FCF_LIMIT 20 /* max. number of FCF entries */
  38 +
  39 +/**
  40 + * enum fip_state - internal state of FCoE controller.
  41 + * @FIP_ST_DISABLED: controller has been disabled or not yet enabled.
  42 + * @FIP_ST_LINK_WAIT: the physical link is down or unusable.
  43 + * @FIP_ST_AUTO: determining whether to use FIP or non-FIP mode.
  44 + * @FIP_ST_NON_FIP: non-FIP mode selected.
  45 + * @FIP_ST_ENABLED: FIP mode selected.
  46 + */
  47 +enum fip_state {
  48 + FIP_ST_DISABLED,
  49 + FIP_ST_LINK_WAIT,
  50 + FIP_ST_AUTO,
  51 + FIP_ST_NON_FIP,
  52 + FIP_ST_ENABLED,
  53 +};
  54 +
  55 +/**
  56 + * struct fcoe_ctlr - FCoE Controller and FIP state.
  57 + * @state: internal FIP state for network link and FIP or non-FIP mode.
  58 + * @lp: &fc_lport: libfc local port.
  59 + * @sel_fcf: currently selected FCF, or NULL.
  60 + * @fcfs: list of discovered FCFs.
  61 + * @fcf_count: number of discovered FCF entries.
  62 + * @sol_time: time when a multicast solicitation was last sent.
  63 + * @sel_time: time after which to select an FCF.
  64 + * @port_ka_time: time of next port keep-alive.
  65 + * @ctlr_ka_time: time of next controller keep-alive.
  66 + * @timer: timer struct used for all delayed events.
  67 + * @link_work: &work_struct for doing FCF selection.
  68 + * @recv_work: &work_struct for receiving FIP frames.
  69 + * @fip_recv_list: list of received FIP frames.
  70 + * @user_mfs: configured maximum FC frame size, including FC header.
  71 + * @flogi_oxid: exchange ID of most recent fabric login.
  72 + * @flogi_count: number of FLOGI attempts in AUTO mode.
  73 + * @link: current link status for libfc.
  74 + * @last_link: last link state reported to libfc.
  75 + * @map_dest: use the FC_MAP mode for destination MAC addresses.
  76 + * @dest_addr: MAC address of the selected FC forwarder.
  77 + * @ctl_src_addr: the native MAC address of our local port.
  78 + * @data_src_addr: the assigned MAC address for the local port after FLOGI.
  79 + * @send: LLD-supplied function to handle sending of FIP Ethernet frames.
  80 + * @update_mac: LLD-supplied function to handle changes to MAC addresses.
  81 + * @lock: lock protecting this structure.
  82 + *
  83 + * This structure is used by all FCoE drivers. It contains information
  84 + * needed by all FCoE low-level drivers (LLDs) as well as internal state
  85 + * for FIP, and fields shared with the LLDS.
  86 + */
  87 +struct fcoe_ctlr {
  88 + enum fip_state state;
  89 + struct fc_lport *lp;
  90 + struct fcoe_fcf *sel_fcf;
  91 + struct list_head fcfs;
  92 + u16 fcf_count;
  93 + unsigned long sol_time;
  94 + unsigned long sel_time;
  95 + unsigned long port_ka_time;
  96 + unsigned long ctlr_ka_time;
  97 + struct timer_list timer;
  98 + struct work_struct link_work;
  99 + struct work_struct recv_work;
  100 + struct sk_buff_head fip_recv_list;
  101 + u16 user_mfs;
  102 + u16 flogi_oxid;
  103 + u8 flogi_count;
  104 + u8 link;
  105 + u8 last_link;
  106 + u8 map_dest;
  107 + u8 dest_addr[ETH_ALEN];
  108 + u8 ctl_src_addr[ETH_ALEN];
  109 + u8 data_src_addr[ETH_ALEN];
  110 +
  111 + void (*send)(struct fcoe_ctlr *, struct sk_buff *);
  112 + void (*update_mac)(struct fcoe_ctlr *, u8 *old, u8 *new);
  113 + spinlock_t lock;
  114 +};
  115 +
  116 +/*
  117 + * struct fcoe_fcf - Fibre-Channel Forwarder.
  118 + * @list: list linkage.
  119 + * @time: system time (jiffies) when an advertisement was last received.
  120 + * @switch_name: WWN of switch from advertisement.
  121 + * @fabric_name: WWN of fabric from advertisement.
  122 + * @fc_map: FC_MAP value from advertisement.
  123 + * @fcf_mac: Ethernet address of the FCF.
  124 + * @vfid: virtual fabric ID.
  125 + * @pri: seletion priority, smaller values are better.
  126 + * @flags: flags received from advertisement.
  127 + * @fka_period: keep-alive period, in jiffies.
  128 + *
  129 + * A Fibre-Channel Forwarder (FCF) is the entity on the Ethernet that
  130 + * passes FCoE frames on to an FC fabric. This structure represents
  131 + * one FCF from which advertisements have been received.
  132 + *
  133 + * When looking up an FCF, @switch_name, @fabric_name, @fc_map, @vfid, and
  134 + * @fcf_mac together form the lookup key.
  135 + */
  136 +struct fcoe_fcf {
  137 + struct list_head list;
  138 + unsigned long time;
  139 +
  140 + u64 switch_name;
  141 + u64 fabric_name;
  142 + u32 fc_map;
  143 + u16 vfid;
  144 + u8 fcf_mac[ETH_ALEN];
  145 +
  146 + u8 pri;
  147 + u16 flags;
  148 + u32 fka_period;
  149 +};
  150 +
  151 +/* FIP API functions */
  152 +void fcoe_ctlr_init(struct fcoe_ctlr *);
  153 +void fcoe_ctlr_destroy(struct fcoe_ctlr *);
  154 +void fcoe_ctlr_link_up(struct fcoe_ctlr *);
  155 +int fcoe_ctlr_link_down(struct fcoe_ctlr *);
  156 +int fcoe_ctlr_els_send(struct fcoe_ctlr *, struct sk_buff *);
  157 +void fcoe_ctlr_recv(struct fcoe_ctlr *, struct sk_buff *);
  158 +int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *, struct fc_frame *fp, u8 *sa);
27 159  
28 160 /* libfcoe funcs */
29 161 u64 fcoe_wwn_from_mac(unsigned char mac[], unsigned int, unsigned int);