xref: /openbmc/linux/net/802/fc.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*2874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * NET3:	Fibre Channel device handling subroutines
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  *		Vineet Abraham <vma@iol.unh.edu>
61da177e4SLinus Torvalds  *		v 1.0 03/22/99
71da177e4SLinus Torvalds  */
81da177e4SLinus Torvalds 
97c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
101da177e4SLinus Torvalds #include <linux/types.h>
111da177e4SLinus Torvalds #include <linux/kernel.h>
121da177e4SLinus Torvalds #include <linux/string.h>
131da177e4SLinus Torvalds #include <linux/mm.h>
141da177e4SLinus Torvalds #include <linux/socket.h>
151da177e4SLinus Torvalds #include <linux/in.h>
161da177e4SLinus Torvalds #include <linux/inet.h>
171da177e4SLinus Torvalds #include <linux/netdevice.h>
181da177e4SLinus Torvalds #include <linux/fcdevice.h>
191da177e4SLinus Torvalds #include <linux/skbuff.h>
201da177e4SLinus Torvalds #include <linux/errno.h>
211da177e4SLinus Torvalds #include <linux/timer.h>
221da177e4SLinus Torvalds #include <linux/net.h>
231da177e4SLinus Torvalds #include <linux/proc_fs.h>
241da177e4SLinus Torvalds #include <linux/init.h>
25bc3b2d7fSPaul Gortmaker #include <linux/export.h>
261da177e4SLinus Torvalds #include <net/arp.h>
271da177e4SLinus Torvalds 
281da177e4SLinus Torvalds /*
291da177e4SLinus Torvalds  *	Put the headers on a Fibre Channel packet.
301da177e4SLinus Torvalds  */
311da177e4SLinus Torvalds 
fc_header(struct sk_buff * skb,struct net_device * dev,unsigned short type,const void * daddr,const void * saddr,unsigned int len)321da177e4SLinus Torvalds static int fc_header(struct sk_buff *skb, struct net_device *dev,
331da177e4SLinus Torvalds 		     unsigned short type,
3495c96174SEric Dumazet 		     const void *daddr, const void *saddr, unsigned int len)
351da177e4SLinus Torvalds {
361da177e4SLinus Torvalds 	struct fch_hdr *fch;
371da177e4SLinus Torvalds 	int hdr_len;
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds 	/*
401da177e4SLinus Torvalds 	 * Add the 802.2 SNAP header if IP as the IPv4 code calls
411da177e4SLinus Torvalds 	 * dev->hard_header directly.
421da177e4SLinus Torvalds 	 */
431da177e4SLinus Torvalds 	if (type == ETH_P_IP || type == ETH_P_ARP)
441da177e4SLinus Torvalds 	{
451da177e4SLinus Torvalds 		struct fcllc *fcllc;
461da177e4SLinus Torvalds 
471da177e4SLinus Torvalds 		hdr_len = sizeof(struct fch_hdr) + sizeof(struct fcllc);
48d58ff351SJohannes Berg 		fch = skb_push(skb, hdr_len);
491da177e4SLinus Torvalds 		fcllc = (struct fcllc *)(fch+1);
501da177e4SLinus Torvalds 		fcllc->dsap = fcllc->ssap = EXTENDED_SAP;
511da177e4SLinus Torvalds 		fcllc->llc = UI_CMD;
521da177e4SLinus Torvalds 		fcllc->protid[0] = fcllc->protid[1] = fcllc->protid[2] = 0x00;
531da177e4SLinus Torvalds 		fcllc->ethertype = htons(type);
541da177e4SLinus Torvalds 	}
551da177e4SLinus Torvalds 	else
561da177e4SLinus Torvalds 	{
571da177e4SLinus Torvalds 		hdr_len = sizeof(struct fch_hdr);
58d58ff351SJohannes Berg 		fch = skb_push(skb, hdr_len);
591da177e4SLinus Torvalds 	}
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds 	if(saddr)
621da177e4SLinus Torvalds 		memcpy(fch->saddr,saddr,dev->addr_len);
631da177e4SLinus Torvalds 	else
641da177e4SLinus Torvalds 		memcpy(fch->saddr,dev->dev_addr,dev->addr_len);
651da177e4SLinus Torvalds 
661da177e4SLinus Torvalds 	if(daddr)
671da177e4SLinus Torvalds 	{
681da177e4SLinus Torvalds 		memcpy(fch->daddr,daddr,dev->addr_len);
69a02cec21SEric Dumazet 		return hdr_len;
701da177e4SLinus Torvalds 	}
711da177e4SLinus Torvalds 	return -hdr_len;
721da177e4SLinus Torvalds }
731da177e4SLinus Torvalds 
743b04dddeSStephen Hemminger static const struct header_ops fc_header_ops = {
753b04dddeSStephen Hemminger 	.create	 = fc_header,
763b04dddeSStephen Hemminger };
773b04dddeSStephen Hemminger 
fc_setup(struct net_device * dev)781da177e4SLinus Torvalds static void fc_setup(struct net_device *dev)
791da177e4SLinus Torvalds {
803b04dddeSStephen Hemminger 	dev->header_ops		= &fc_header_ops;
811da177e4SLinus Torvalds 	dev->type		= ARPHRD_IEEE802;
821da177e4SLinus Torvalds 	dev->hard_header_len	= FC_HLEN;
831da177e4SLinus Torvalds 	dev->mtu		= 2024;
841da177e4SLinus Torvalds 	dev->addr_len		= FC_ALEN;
851da177e4SLinus Torvalds 	dev->tx_queue_len	= 100; /* Long queues on fc */
861da177e4SLinus Torvalds 	dev->flags		= IFF_BROADCAST;
871da177e4SLinus Torvalds 
881da177e4SLinus Torvalds 	memset(dev->broadcast, 0xFF, FC_ALEN);
891da177e4SLinus Torvalds }
901da177e4SLinus Torvalds 
911da177e4SLinus Torvalds /**
921da177e4SLinus Torvalds  * alloc_fcdev - Register fibre channel device
931da177e4SLinus Torvalds  * @sizeof_priv: Size of additional driver-private structure to be allocated
941da177e4SLinus Torvalds  *	for this fibre channel device
951da177e4SLinus Torvalds  *
961da177e4SLinus Torvalds  * Fill in the fields of the device structure with fibre channel-generic values.
971da177e4SLinus Torvalds  *
981da177e4SLinus Torvalds  * Constructs a new net device, complete with a private data area of
991da177e4SLinus Torvalds  * size @sizeof_priv.  A 32-byte (not bit) alignment is enforced for
1001da177e4SLinus Torvalds  * this private data area.
1011da177e4SLinus Torvalds  */
alloc_fcdev(int sizeof_priv)1021da177e4SLinus Torvalds struct net_device *alloc_fcdev(int sizeof_priv)
1031da177e4SLinus Torvalds {
104c835a677STom Gundersen 	return alloc_netdev(sizeof_priv, "fc%d", NET_NAME_UNKNOWN, fc_setup);
1051da177e4SLinus Torvalds }
1061da177e4SLinus Torvalds EXPORT_SYMBOL(alloc_fcdev);
107