linux/include/scsi/fc_frame.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * Copyright(c) 2007 Intel Corporation. All rights reserved.
   4 *
   5 * Maintained at www.Open-FCoE.org
   6 */
   7
   8#ifndef _FC_FRAME_H_
   9#define _FC_FRAME_H_
  10
  11#include <linux/scatterlist.h>
  12#include <linux/skbuff.h>
  13#include <scsi/scsi_cmnd.h>
  14
  15#include <scsi/fc/fc_fs.h>
  16#include <scsi/fc/fc_fcp.h>
  17#include <scsi/fc/fc_encaps.h>
  18
  19#include <linux/if_ether.h>
  20
  21/* some helpful macros */
  22
  23#define ntohll(x) be64_to_cpu(x)
  24#define htonll(x) cpu_to_be64(x)
  25
  26static inline u32 ntoh24(const u8 *p)
  27{
  28        return (p[0] << 16) | (p[1] << 8) | p[2];
  29}
  30
  31static inline void hton24(u8 *p, u32 v)
  32{
  33        p[0] = (v >> 16) & 0xff;
  34        p[1] = (v >> 8) & 0xff;
  35        p[2] = v & 0xff;
  36}
  37
  38/*
  39 * The fc_frame interface is used to pass frame data between functions.
  40 * The frame includes the data buffer, length, and SOF / EOF delimiter types.
  41 * A pointer to the port structure of the receiving port is also includeded.
  42 */
  43
  44#define FC_FRAME_HEADROOM       32      /* headroom for VLAN + FCoE headers */
  45#define FC_FRAME_TAILROOM       8       /* trailer space for FCoE */
  46
  47/* Max number of skb frags allowed, reserving one for fcoe_crc_eof page */
  48#define FC_FRAME_SG_LEN         (MAX_SKB_FRAGS - 1)
  49
  50#define fp_skb(fp)      (&((fp)->skb))
  51#define fr_hdr(fp)      ((fp)->skb.data)
  52#define fr_len(fp)      ((fp)->skb.len)
  53#define fr_cb(fp)       ((struct fcoe_rcv_info *)&((fp)->skb.cb[0]))
  54#define fr_dev(fp)      (fr_cb(fp)->fr_dev)
  55#define fr_seq(fp)      (fr_cb(fp)->fr_seq)
  56#define fr_sof(fp)      (fr_cb(fp)->fr_sof)
  57#define fr_eof(fp)      (fr_cb(fp)->fr_eof)
  58#define fr_flags(fp)    (fr_cb(fp)->fr_flags)
  59#define fr_encaps(fp)   (fr_cb(fp)->fr_encaps)
  60#define fr_max_payload(fp)      (fr_cb(fp)->fr_max_payload)
  61#define fr_fsp(fp)      (fr_cb(fp)->fr_fsp)
  62#define fr_crc(fp)      (fr_cb(fp)->fr_crc)
  63
  64struct fc_frame {
  65        struct sk_buff skb;
  66};
  67
  68struct fcoe_rcv_info {
  69        struct fc_lport *fr_dev;        /* transport layer private pointer */
  70        struct fc_seq   *fr_seq;        /* for use with exchange manager */
  71        struct fc_fcp_pkt *fr_fsp;      /* for the corresponding fcp I/O */
  72        u32             fr_crc;
  73        u16             fr_max_payload; /* max FC payload */
  74        u8              fr_sof;         /* start of frame delimiter */
  75        u8              fr_eof;         /* end of frame delimiter */
  76        u8              fr_flags;       /* flags - see below */
  77        u8              fr_encaps;      /* LLD encapsulation info (e.g. FIP) */
  78        u8              granted_mac[ETH_ALEN]; /* FCoE MAC address */
  79};
  80
  81
  82/*
  83 * Get fc_frame pointer for an skb that's already been imported.
  84 */
  85static inline struct fcoe_rcv_info *fcoe_dev_from_skb(const struct sk_buff *skb)
  86{
  87        BUILD_BUG_ON(sizeof(struct fcoe_rcv_info) > sizeof(skb->cb));
  88        return (struct fcoe_rcv_info *) skb->cb;
  89}
  90
  91/*
  92 * fr_flags.
  93 */
  94#define FCPHF_CRC_UNCHECKED     0x01    /* CRC not computed, still appended */
  95
  96/*
  97 * Initialize a frame.
  98 * We don't do a complete memset here for performance reasons.
  99 * The caller must set fr_free, fr_hdr, fr_len, fr_sof, and fr_eof eventually.
 100 */
 101static inline void fc_frame_init(struct fc_frame *fp)
 102{
 103        fr_dev(fp) = NULL;
 104        fr_seq(fp) = NULL;
 105        fr_flags(fp) = 0;
 106        fr_encaps(fp) = 0;
 107}
 108
 109struct fc_frame *fc_frame_alloc_fill(struct fc_lport *, size_t payload_len);
 110struct fc_frame *_fc_frame_alloc(size_t payload_len);
 111
 112/*
 113 * Allocate fc_frame structure and buffer.  Set the initial length to
 114 * payload_size + sizeof (struct fc_frame_header).
 115 */
 116static inline struct fc_frame *fc_frame_alloc(struct fc_lport *dev, size_t len)
 117{
 118        struct fc_frame *fp;
 119
 120        /*
 121         * Note: Since len will often be a constant multiple of 4,
 122         * this check will usually be evaluated and eliminated at compile time.
 123         */
 124        if (len && len % 4)
 125                fp = fc_frame_alloc_fill(dev, len);
 126        else
 127                fp = _fc_frame_alloc(len);
 128        return fp;
 129}
 130
 131/*
 132 * Free the fc_frame structure and buffer.
 133 */
 134static inline void fc_frame_free(struct fc_frame *fp)
 135{
 136        kfree_skb(fp_skb(fp));
 137}
 138
 139static inline int fc_frame_is_linear(struct fc_frame *fp)
 140{
 141        return !skb_is_nonlinear(fp_skb(fp));
 142}
 143
 144/*
 145 * Get frame header from message in fc_frame structure.
 146 * This version doesn't do a length check.
 147 */
 148static inline
 149struct fc_frame_header *__fc_frame_header_get(const struct fc_frame *fp)
 150{
 151        return (struct fc_frame_header *)fr_hdr(fp);
 152}
 153
 154/*
 155 * Get frame header from message in fc_frame structure.
 156 * This hides a cast and provides a place to add some checking.
 157 */
 158static inline
 159struct fc_frame_header *fc_frame_header_get(const struct fc_frame *fp)
 160{
 161        WARN_ON(fr_len(fp) < sizeof(struct fc_frame_header));
 162        return __fc_frame_header_get(fp);
 163}
 164
 165/*
 166 * Get source FC_ID (S_ID) from frame header in message.
 167 */
 168static inline u32 fc_frame_sid(const struct fc_frame *fp)
 169{
 170        return ntoh24(__fc_frame_header_get(fp)->fh_s_id);
 171}
 172
 173/*
 174 * Get destination FC_ID (D_ID) from frame header in message.
 175 */
 176static inline u32 fc_frame_did(const struct fc_frame *fp)
 177{
 178        return ntoh24(__fc_frame_header_get(fp)->fh_d_id);
 179}
 180
 181/*
 182 * Get frame payload from message in fc_frame structure.
 183 * This hides a cast and provides a place to add some checking.
 184 * The len parameter is the minimum length for the payload portion.
 185 * Returns NULL if the frame is too short.
 186 *
 187 * This assumes the interesting part of the payload is in the first part
 188 * of the buffer for received data.  This may not be appropriate to use for
 189 * buffers being transmitted.
 190 */
 191static inline void *fc_frame_payload_get(const struct fc_frame *fp,
 192                                         size_t len)
 193{
 194        void *pp = NULL;
 195
 196        if (fr_len(fp) >= sizeof(struct fc_frame_header) + len)
 197                pp = fc_frame_header_get(fp) + 1;
 198        return pp;
 199}
 200
 201/*
 202 * Get frame payload opcode (first byte) from message in fc_frame structure.
 203 * This hides a cast and provides a place to add some checking. Return 0
 204 * if the frame has no payload.
 205 */
 206static inline u8 fc_frame_payload_op(const struct fc_frame *fp)
 207{
 208        u8 *cp;
 209
 210        cp = fc_frame_payload_get(fp, sizeof(u8));
 211        if (!cp)
 212                return 0;
 213        return *cp;
 214
 215}
 216
 217/*
 218 * Get FC class from frame.
 219 */
 220static inline enum fc_class fc_frame_class(const struct fc_frame *fp)
 221{
 222        return fc_sof_class(fr_sof(fp));
 223}
 224
 225/*
 226 * Check the CRC in a frame.
 227 * The CRC immediately follows the last data item *AFTER* the length.
 228 * The return value is zero if the CRC matches.
 229 */
 230u32 fc_frame_crc_check(struct fc_frame *);
 231
 232static inline u8 fc_frame_rctl(const struct fc_frame *fp)
 233{
 234        return fc_frame_header_get(fp)->fh_r_ctl;
 235}
 236
 237static inline bool fc_frame_is_cmd(const struct fc_frame *fp)
 238{
 239        return fc_frame_rctl(fp) == FC_RCTL_DD_UNSOL_CMD;
 240}
 241
 242/*
 243 * Check for leaks.
 244 * Print the frame header of any currently allocated frame, assuming there
 245 * should be none at this point.
 246 */
 247void fc_frame_leak_check(void);
 248
 249#endif /* _FC_FRAME_H_ */
 250