Bhanu Gollapudi wrote:
> As per FC-BB-5 rev.2, section 7.8.7.1, strict ordering of FIP descriptors
> is required for ELS requests. Also, look for missing and duplicate critical 
> descriptors.

I rechecked the spec it really doesn't say we must enforce the
descriptor order on receive.

It does say the receiver must accept them in any order except
for ELSes, but it doesn't say we can't accept them out-of-order
in the ELS case as well.

That said, its OK with me if we insist on the order.  It makes it more
likely that switches will stay correct.

> 
> Signed-off-by: Bhanu Prakash Gollapudi <[email protected]>
> ---
>  drivers/scsi/fcoe/libfcoe.c |   31 ++++++++++++++++++++++++++++---
>  1 files changed, 28 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
> index 450c621..fa94650 100644
> --- a/drivers/scsi/fcoe/libfcoe.c
> +++ b/drivers/scsi/fcoe/libfcoe.c
> @@ -861,7 +861,8 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, 
> struct sk_buff *skb)
>       size_t els_len = 0;
>       size_t rlen;
>       size_t dlen;
> -     u32 dupl_desc = 0;
> +     u32 desc_mask = 0;
> +     u32 desc_cnt = 0;
>  
>       fiph = (struct fip_header *)skb->data;
>       sub = fiph->fip_subcode;
> @@ -874,20 +875,27 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, 
> struct sk_buff *skb)
>  
>       desc = (struct fip_desc *)(fiph + 1);
>       while (rlen > 0) {
> +             desc_cnt++;
>               dlen = desc->fip_dlen * FIP_BPW;
>               if (dlen < sizeof(*desc) || dlen > rlen)
>                       goto drop;
>               /* Drop ELS if there are duplicate critical descriptors */
>               if (desc->fip_dtype < 32) {
> -                     if (dupl_desc & 1U << desc->fip_dtype) {
> +                     if (desc_mask & 1U << desc->fip_dtype) {
>                               LIBFCOE_FIP_DBG(fip, "Duplicate Critical "
>                                               "Descriptors in FIP ELS\n");
>                               goto drop;
>                       }
> -                     dupl_desc |= (1 << desc->fip_dtype);
> +                     desc_mask |= (1 << desc->fip_dtype);
>               }
>               switch (desc->fip_dtype) {
>               case FIP_DT_MAC:
> +                     if (desc_cnt == 1) {
> +                             LIBFCOE_FIP_DBG(fip, "FIP descriptors "
> +                                             "received out of order\n");
> +                             goto drop;
> +                     }
> +
>                       if (dlen != sizeof(struct fip_mac_desc))
>                               goto len_err;
>                       memcpy(granted_mac,
> @@ -904,6 +912,11 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, 
> struct sk_buff *skb)
>               case FIP_DT_FDISC:
>               case FIP_DT_LOGO:
>               case FIP_DT_ELP:
> +                     if (desc_cnt != 1) {
> +                             LIBFCOE_FIP_DBG(fip, "FIP descriptors "
> +                                             "received out of order\n");
> +                             goto drop;
> +                     }
>                       if (fh)
>                               goto drop;
>                       if (dlen < sizeof(*els) + sizeof(*fh) + 1)
> @@ -919,6 +932,11 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, 
> struct sk_buff *skb)
>                       /* standard says ignore unknown descriptors >= 128 */
>                       if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
>                               goto drop;
> +                     if (desc_cnt <= 2) {
> +                             LIBFCOE_FIP_DBG(fip, "FIP descriptors "
> +                                             "received out of order\n");
> +                             goto drop;
> +                     }
>                       break;
>               }
>               desc = (struct fip_desc *)((char *)desc + dlen);
> @@ -934,6 +952,13 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, 
> struct sk_buff *skb)
>           els_op == ELS_LS_ACC && is_valid_ether_addr(granted_mac))
>               fip->flogi_oxid = FC_XID_UNKNOWN;
>  
> +     if ((desc_cnt == 0) || ((els_op != ELS_LS_RJT) &&
> +         (!(1U << FIP_DT_MAC & desc_mask)))) {
> +             LIBFCOE_FIP_DBG(fip, "Missing critical descriptors "
> +                             "in FIP ELS\n");
> +             goto drop;
> +     }
> +
>       /*
>        * Convert skb into an fc_frame containing only the ELS.
>        */

_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel

Reply via email to