예제 #1
0
static void qedf_process_l2_frame_compl(struct qedf_rport *fcport,
					struct fc_frame *fp,
					u16 l2_oxid)
{
	struct fc_lport *lport = fcport->qedf->lport;
	struct fc_frame_header *fh;
	u32 crc;

	fh = (struct fc_frame_header *)fc_frame_header_get(fp);

	/* Set the OXID we return to what libfc used */
	if (l2_oxid != FC_XID_UNKNOWN)
		fh->fh_ox_id = htons(l2_oxid);

	/* Setup header fields */
	fh->fh_r_ctl = FC_RCTL_ELS_REP;
	fh->fh_type = FC_TYPE_ELS;
	/* Last sequence, end sequence */
	fh->fh_f_ctl[0] = 0x98;
	hton24(fh->fh_d_id, lport->port_id);
	hton24(fh->fh_s_id, fcport->rdata->ids.port_id);
	fh->fh_rx_id = 0xffff;

	/* Set frame attributes */
	crc = fcoe_fc_crc(fp);
	fc_frame_init(fp);
	fr_dev(fp) = lport;
	fr_sof(fp) = FC_SOF_I3;
	fr_eof(fp) = FC_EOF_T;
	fr_crc(fp) = cpu_to_le32(~crc);

	/* Send completed request to libfc */
	fc_exch_recv(lport, fp);
}
예제 #2
0
/*
 * Allocate a frame intended to be sent via fcoe_xmit.
 * Get an sk_buff for the frame and set the length.
 */
struct fc_frame *__fc_frame_alloc(size_t len)
{
	struct fc_frame *fp;
	struct sk_buff *skb;

	WARN_ON((len % sizeof(u32)) != 0);
	len += sizeof(struct fc_frame_header);
	skb = dev_alloc_skb(len + FC_FRAME_HEADROOM + FC_FRAME_TAILROOM);
	if (!skb)
		return NULL;
	fp = (struct fc_frame *) skb;
	fc_frame_init(fp);
	skb_reserve(skb, FC_FRAME_HEADROOM);
	skb_put(skb, len);
	return fp;
}
예제 #3
0
/*
 * Allocate a frame intended to be sent via fcoe_xmit.
 * Get an sk_buff for the frame and set the length.
 */
struct fc_frame *_fc_frame_alloc(size_t len)
{
	struct fc_frame *fp;
	struct sk_buff *skb;

	WARN_ON((len % sizeof(u32)) != 0);
	len += sizeof(struct fc_frame_header);
	skb = alloc_skb_fclone(len + FC_FRAME_HEADROOM + FC_FRAME_TAILROOM +
			       NET_SKB_PAD, GFP_ATOMIC);
	if (!skb)
		return NULL;
	skb_reserve(skb, NET_SKB_PAD + FC_FRAME_HEADROOM);
	fp = (struct fc_frame *) skb;
	fc_frame_init(fp);
	skb_put(skb, len);
	return fp;
}
예제 #4
0
파일: fnic_fcs.c 프로젝트: AiWinters/linux
/**
 * fnic_import_rq_eth_pkt() - handle received FCoE or FIP frame.
 * @fnic:	fnic instance.
 * @skb:	Ethernet Frame.
 */
static inline int fnic_import_rq_eth_pkt(struct fnic *fnic, struct sk_buff *skb)
{
	struct fc_frame *fp;
	struct ethhdr *eh;
	struct fcoe_hdr *fcoe_hdr;
	struct fcoe_crc_eof *ft;

	/*
	 * Undo VLAN encapsulation if present.
	 */
	eh = (struct ethhdr *)skb->data;
	if (eh->h_proto == htons(ETH_P_8021Q)) {
		memmove((u8 *)eh + VLAN_HLEN, eh, ETH_ALEN * 2);
		eh = (struct ethhdr *)skb_pull(skb, VLAN_HLEN);
		skb_reset_mac_header(skb);
	}
	if (eh->h_proto == htons(ETH_P_FIP)) {
		skb_pull(skb, sizeof(*eh));
		fcoe_ctlr_recv(&fnic->ctlr, skb);
		return 1;		/* let caller know packet was used */
	}
	if (eh->h_proto != htons(ETH_P_FCOE))
		goto drop;
	skb_set_network_header(skb, sizeof(*eh));
	skb_pull(skb, sizeof(*eh));

	fcoe_hdr = (struct fcoe_hdr *)skb->data;
	if (FC_FCOE_DECAPS_VER(fcoe_hdr) != FC_FCOE_VER)
		goto drop;

	fp = (struct fc_frame *)skb;
	fc_frame_init(fp);
	fr_sof(fp) = fcoe_hdr->fcoe_sof;
	skb_pull(skb, sizeof(struct fcoe_hdr));
	skb_reset_transport_header(skb);

	ft = (struct fcoe_crc_eof *)(skb->data + skb->len - sizeof(*ft));
	fr_eof(fp) = ft->fcoe_eof;
	skb_trim(skb, skb->len - sizeof(*ft));
	return 0;
drop:
	dev_kfree_skb_irq(skb);
	return -1;
}
예제 #5
0
static inline int fnic_import_rq_eth_pkt(struct sk_buff *skb, u32 len)
{
	struct fc_frame *fp;
	struct ethhdr *eh;
	struct vlan_ethhdr *vh;
	struct fcoe_hdr *fcoe_hdr;
	struct fcoe_crc_eof *ft;
	u32    transport_len = 0;

	eh = (struct ethhdr *)skb->data;
	vh = (struct vlan_ethhdr *)skb->data;
	if (vh->h_vlan_proto == htons(ETH_P_8021Q) &&
	    vh->h_vlan_encapsulated_proto == htons(ETH_P_FCOE)) {
		skb_pull(skb, sizeof(struct vlan_ethhdr));
		transport_len += sizeof(struct vlan_ethhdr);
	} else if (eh->h_proto == htons(ETH_P_FCOE)) {
		transport_len += sizeof(struct ethhdr);
		skb_pull(skb, sizeof(struct ethhdr));
	} else
		return -1;

	fcoe_hdr = (struct fcoe_hdr *)skb->data;
	if (FC_FCOE_DECAPS_VER(fcoe_hdr) != FC_FCOE_VER)
		return -1;

	fp = (struct fc_frame *)skb;
	fc_frame_init(fp);
	fr_sof(fp) = fcoe_hdr->fcoe_sof;
	skb_pull(skb, sizeof(struct fcoe_hdr));
	transport_len += sizeof(struct fcoe_hdr);

	ft = (struct fcoe_crc_eof *)(skb->data + len -
				     transport_len - sizeof(*ft));
	fr_eof(fp) = ft->fcoe_eof;
	skb_trim(skb, len - transport_len - sizeof(*ft));
	return 0;
}