Beispiel #1
0
/**
 * 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;
}
Beispiel #2
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;
}