mirror of
https://github.com/xcat2/xNBA.git
synced 2024-11-22 17:41:55 +00:00
[fcoe] Add support for FIP VLAN discovery
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
parent
b4706c88c9
commit
1790f56fb2
@ -86,4 +86,7 @@ enum fcoe_eof {
|
||||
FCOE_EOF_A = 0x50, /**< End of Frame Abort */
|
||||
};
|
||||
|
||||
/** FCoE VLAN priority */
|
||||
#define FCOE_VLAN_PRIORITY 3
|
||||
|
||||
#endif /* _IPXE_FCOE_H */
|
||||
|
152
src/net/fcoe.c
152
src/net/fcoe.c
@ -29,6 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <ipxe/xfer.h>
|
||||
#include <ipxe/netdevice.h>
|
||||
#include <ipxe/ethernet.h>
|
||||
#include <ipxe/vlan.h>
|
||||
#include <ipxe/features.h>
|
||||
#include <ipxe/errortab.h>
|
||||
#include <ipxe/device.h>
|
||||
@ -103,6 +104,10 @@ enum fcoe_flags {
|
||||
FCOE_HAVE_FIP_FCF = 0x0004,
|
||||
/** FCoE forwarder supports server-provided MAC addresses */
|
||||
FCOE_FCF_ALLOWS_SPMA = 0x0008,
|
||||
/** An alternative VLAN has been found */
|
||||
FCOE_VLAN_FOUND = 0x0010,
|
||||
/** VLAN discovery has timed out */
|
||||
FCOE_VLAN_TIMED_OUT = 0x0020,
|
||||
};
|
||||
|
||||
struct net_protocol fcoe_protocol __net_protocol;
|
||||
@ -124,6 +129,15 @@ static uint8_t all_fcf_macs[ETH_ALEN] =
|
||||
static uint8_t default_fcf_mac[ETH_ALEN] =
|
||||
{ 0x0e, 0xfc, 0x00, 0xff, 0xff, 0xfe };
|
||||
|
||||
/** Maximum number of VLAN requests before giving up on VLAN discovery */
|
||||
#define FCOE_MAX_VLAN_REQUESTS 2
|
||||
|
||||
/** Delay between retrying VLAN requests */
|
||||
#define FCOE_VLAN_RETRY_DELAY ( TICKS_PER_SEC )
|
||||
|
||||
/** Delay between retrying polling VLAN requests */
|
||||
#define FCOE_VLAN_POLL_DELAY ( 30 * TICKS_PER_SEC )
|
||||
|
||||
/** Maximum number of FIP solicitations before giving up on FIP */
|
||||
#define FCOE_MAX_FIP_SOLICITATIONS 2
|
||||
|
||||
@ -182,8 +196,9 @@ static void fcoe_reset ( struct fcoe_port *fcoe ) {
|
||||
netdev_link_ok ( fcoe->netdev ) ) {
|
||||
fcoe->flags |= FCOE_HAVE_NETWORK;
|
||||
start_timer_nodelay ( &fcoe->timer );
|
||||
DBGC ( fcoe, "FCoE %s starting FIP solicitation\n",
|
||||
fcoe->netdev->name );
|
||||
DBGC ( fcoe, "FCoE %s starting %s\n", fcoe->netdev->name,
|
||||
( vlan_can_be_trunk ( fcoe->netdev ) ?
|
||||
"VLAN discovery" : "FIP solicitation" ) );
|
||||
}
|
||||
|
||||
/* Send notification of window change */
|
||||
@ -533,6 +548,100 @@ static int fcoe_fip_parse ( struct fcoe_port *fcoe, struct fip_header *fiphdr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send FIP VLAN request
|
||||
*
|
||||
* @v fcoe FCoE port
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int fcoe_fip_tx_vlan ( struct fcoe_port *fcoe ) {
|
||||
struct io_buffer *iobuf;
|
||||
struct {
|
||||
struct fip_header hdr;
|
||||
struct fip_mac_address mac_address;
|
||||
} __attribute__ (( packed )) *request;
|
||||
int rc;
|
||||
|
||||
/* Allocate I/O buffer */
|
||||
iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( *request ) );
|
||||
if ( ! iobuf )
|
||||
return -ENOMEM;
|
||||
iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
|
||||
|
||||
/* Construct VLAN request */
|
||||
request = iob_put ( iobuf, sizeof ( *request ) );
|
||||
memset ( request, 0, sizeof ( *request ) );
|
||||
request->hdr.version = FIP_VERSION;
|
||||
request->hdr.code = htons ( FIP_CODE_VLAN );
|
||||
request->hdr.subcode = FIP_VLAN_REQUEST;
|
||||
request->hdr.len = htons ( ( sizeof ( *request ) -
|
||||
sizeof ( request->hdr ) ) / 4 );
|
||||
request->mac_address.type = FIP_MAC_ADDRESS;
|
||||
request->mac_address.len =
|
||||
( sizeof ( request->mac_address ) / 4 );
|
||||
memcpy ( request->mac_address.mac, fcoe->netdev->ll_addr,
|
||||
sizeof ( request->mac_address.mac ) );
|
||||
|
||||
/* Send VLAN request */
|
||||
if ( ( rc = net_tx ( iob_disown ( iobuf ), fcoe->netdev,
|
||||
&fip_protocol, all_fcf_macs,
|
||||
fcoe->netdev->ll_addr ) ) != 0 ) {
|
||||
DBGC ( fcoe, "FCoE %s could not send VLAN request: "
|
||||
"%s\n", fcoe->netdev->name, strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle received FIP VLAN notification
|
||||
*
|
||||
* @v fcoe FCoE port
|
||||
* @v descs Descriptor list
|
||||
* @v flags Flags
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int fcoe_fip_rx_vlan ( struct fcoe_port *fcoe,
|
||||
struct fip_descriptors *descs,
|
||||
unsigned int flags __unused ) {
|
||||
struct fip_mac_address *mac_address = fip_mac_address ( descs );
|
||||
struct fip_vlan *vlan = fip_vlan ( descs );
|
||||
unsigned int tag;
|
||||
int rc;
|
||||
|
||||
/* Sanity checks */
|
||||
if ( ! mac_address ) {
|
||||
DBGC ( fcoe, "FCoE %s received VLAN notification missing MAC "
|
||||
"address\n", fcoe->netdev->name );
|
||||
return -EINVAL;
|
||||
}
|
||||
if ( ! vlan ) {
|
||||
DBGC ( fcoe, "FCoE %s received VLAN notification missing VLAN "
|
||||
"tag\n", fcoe->netdev->name );
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Create VLAN */
|
||||
tag = ntohs ( vlan->vlan );
|
||||
DBGC ( fcoe, "FCoE %s creating VLAN %d for FCF %s\n",
|
||||
fcoe->netdev->name, tag, eth_ntoa ( mac_address->mac ) );
|
||||
if ( ( rc = vlan_create ( fcoe->netdev, tag,
|
||||
FCOE_VLAN_PRIORITY ) ) != 0 ) {
|
||||
DBGC ( fcoe, "FCoE %s could not create VLAN %d: %s\n",
|
||||
fcoe->netdev->name, tag, strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Record that a VLAN was found. This FCoE port will play no
|
||||
* further active role; the real FCoE traffic will use the
|
||||
* port automatically created for the new VLAN device.
|
||||
*/
|
||||
fcoe->flags |= FCOE_VLAN_FOUND;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send FIP discovery solicitation
|
||||
*
|
||||
@ -797,6 +906,8 @@ struct fip_handler {
|
||||
|
||||
/** FIP handlers */
|
||||
static struct fip_handler fip_handlers[] = {
|
||||
{ FIP_CODE_VLAN, FIP_VLAN_NOTIFY,
|
||||
fcoe_fip_rx_vlan },
|
||||
{ FIP_CODE_DISCOVERY, FIP_DISCOVERY_ADVERTISE,
|
||||
fcoe_fip_rx_advertisement },
|
||||
{ FIP_CODE_ELS, FIP_ELS_RESPONSE,
|
||||
@ -891,7 +1002,42 @@ static void fcoe_expired ( struct retry_timer *timer, int over __unused ) {
|
||||
/* Increment the timeout counter */
|
||||
fcoe->timeouts++;
|
||||
|
||||
if ( ! ( fcoe->flags & FCOE_HAVE_FCF ) ) {
|
||||
if ( vlan_can_be_trunk ( fcoe->netdev ) &
|
||||
! ( fcoe->flags & FCOE_VLAN_TIMED_OUT ) ) {
|
||||
|
||||
/* If we have already found a VLAN, send infrequent
|
||||
* VLAN requests, in case VLAN information changes.
|
||||
*/
|
||||
if ( fcoe->flags & FCOE_VLAN_FOUND ) {
|
||||
fcoe->flags &= ~FCOE_VLAN_FOUND;
|
||||
fcoe->timeouts = 0;
|
||||
start_timer_fixed ( &fcoe->timer,
|
||||
FCOE_VLAN_POLL_DELAY );
|
||||
fcoe_fip_tx_vlan ( fcoe );
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we have not yet found a VLAN, and we have not
|
||||
* yet timed out and given up on finding one, then
|
||||
* send a VLAN request and wait.
|
||||
*/
|
||||
if ( fcoe->timeouts <= FCOE_MAX_VLAN_REQUESTS ) {
|
||||
start_timer_fixed ( &fcoe->timer,
|
||||
FCOE_VLAN_RETRY_DELAY );
|
||||
fcoe_fip_tx_vlan ( fcoe );
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have timed out waiting for a VLAN; proceed to
|
||||
* FIP discovery.
|
||||
*/
|
||||
fcoe->flags |= FCOE_VLAN_TIMED_OUT;
|
||||
fcoe->timeouts = 0;
|
||||
DBGC ( fcoe, "FCoE %s giving up on VLAN discovery\n",
|
||||
fcoe->netdev->name );
|
||||
start_timer_nodelay ( &fcoe->timer );
|
||||
|
||||
} else if ( ! ( fcoe->flags & FCOE_HAVE_FCF ) ) {
|
||||
|
||||
/* If we have not yet found a FIP-capable forwarder,
|
||||
* and we have not yet timed out and given up on
|
||||
|
Loading…
Reference in New Issue
Block a user