Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 368675
b: refs/heads/master
c: 6752c8d
h: refs/heads/master
i:
  368673: e710e63
  368671: f563e24
v: v3
  • Loading branch information
YOSHIFUJI Hideaki / 吉藤英明 authored and David S. Miller committed Mar 26, 2013
1 parent 75d1900 commit 61d38cc
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 136 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 61a7839a19c157d11930fe69697a4c90884bf7c4
refs/heads/master: 6752c8db8e0cfedb44ba62806dd15b383ed64000
153 changes: 26 additions & 127 deletions trunk/drivers/firewire/net.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include <asm/unaligned.h>
#include <net/arp.h>
#include <net/firewire.h>

/* rx limits */
#define FWNET_MAX_FRAGMENTS 30 /* arbitrary, > TX queue depth */
Expand Down Expand Up @@ -57,33 +58,6 @@
#define RFC2374_HDR_LASTFRAG 2 /* last fragment */
#define RFC2374_HDR_INTFRAG 3 /* interior fragment */

#define RFC2734_HW_ADDR_LEN 16

struct rfc2734_arp {
__be16 hw_type; /* 0x0018 */
__be16 proto_type; /* 0x0806 */
u8 hw_addr_len; /* 16 */
u8 ip_addr_len; /* 4 */
__be16 opcode; /* ARP Opcode */
/* Above is exactly the same format as struct arphdr */

__be64 s_uniq_id; /* Sender's 64bit EUI */
u8 max_rec; /* Sender's max packet size */
u8 sspd; /* Sender's max speed */
__be16 fifo_hi; /* hi 16bits of sender's FIFO addr */
__be32 fifo_lo; /* lo 32bits of sender's FIFO addr */
__be32 sip; /* Sender's IP Address */
__be32 tip; /* IP Address of requested hw addr */
} __packed;

/* This header format is specific to this driver implementation. */
#define FWNET_ALEN 8
#define FWNET_HLEN 10
struct fwnet_header {
u8 h_dest[FWNET_ALEN]; /* destination address */
__be16 h_proto; /* packet type ID field */
} __packed;

static bool fwnet_hwaddr_is_multicast(u8 *ha)
{
return !!(*ha & 1);
Expand Down Expand Up @@ -196,8 +170,6 @@ struct fwnet_peer {
struct list_head peer_link;
struct fwnet_device *dev;
u64 guid;
u64 fifo;
__be32 ip;

/* guarded by dev->lock */
struct list_head pd_list; /* received partial datagrams */
Expand Down Expand Up @@ -226,6 +198,15 @@ struct fwnet_packet_task {
u8 enqueued;
};

/*
* Get fifo address embedded in hwaddr
*/
static __u64 fwnet_hwaddr_fifo(union fwnet_hwaddr *ha)
{
return (u64)get_unaligned_be16(&ha->uc.fifo_hi) << 32
| get_unaligned_be32(&ha->uc.fifo_lo);
}

/*
* saddr == NULL means use device source address.
* daddr == NULL means leave destination address (eg unresolved arp).
Expand Down Expand Up @@ -518,7 +499,6 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
bool is_broadcast, u16 ether_type)
{
struct fwnet_device *dev;
static const __be64 broadcast_hw = cpu_to_be64(~0ULL);
int status;
__be64 guid;

Expand All @@ -537,76 +517,11 @@ static int fwnet_finish_incoming_packet(struct net_device *net,

/*
* Parse the encapsulation header. This actually does the job of
* converting to an ethernet frame header, as well as arp
* conversion if needed. ARP conversion is easier in this
* direction, since we are using ethernet as our backend.
*/
/*
* If this is an ARP packet, convert it. First, we want to make
* use of some of the fields, since they tell us a little bit
* about the sending machine.
* converting to an ethernet-like pseudo frame header.
*/
if (ether_type == ETH_P_ARP) {
struct rfc2734_arp *arp1394;
struct arphdr *arp;
unsigned char *arp_ptr;
u64 fifo_addr;
u64 peer_guid;
struct fwnet_peer *peer;
unsigned long flags;

arp1394 = (struct rfc2734_arp *)skb->data;
arp = (struct arphdr *)skb->data;
arp_ptr = (unsigned char *)(arp + 1);
peer_guid = get_unaligned_be64(&arp1394->s_uniq_id);
fifo_addr = (u64)get_unaligned_be16(&arp1394->fifo_hi) << 32
| get_unaligned_be32(&arp1394->fifo_lo);

spin_lock_irqsave(&dev->lock, flags);
peer = fwnet_peer_find_by_guid(dev, peer_guid);
if (peer) {
peer->fifo = fifo_addr;
peer->ip = arp1394->sip;
}
spin_unlock_irqrestore(&dev->lock, flags);

if (!peer) {
dev_notice(&net->dev,
"no peer for ARP packet from %016llx\n",
(unsigned long long)peer_guid);
goto no_peer;
}

/*
* Now that we're done with the 1394 specific stuff, we'll
* need to alter some of the data. Believe it or not, all
* that needs to be done is sender_IP_address needs to be
* moved, the destination hardware address get stuffed
* in and the hardware address length set to 8.
*
* IMPORTANT: The code below overwrites 1394 specific data
* needed above so keep the munging of the data for the
* higher level IP stack last.
*/

arp->ar_hln = 8;
/* skip over sender unique id */
arp_ptr += arp->ar_hln;
/* move sender IP addr */
put_unaligned(arp1394->sip, (u32 *)arp_ptr);
/* skip over sender IP addr */
arp_ptr += arp->ar_pln;

if (arp->ar_op == htons(ARPOP_REQUEST))
memset(arp_ptr, 0, sizeof(u64));
else
memcpy(arp_ptr, net->dev_addr, sizeof(u64));
}

/* Now add the ethernet header. */
guid = cpu_to_be64(dev->card->guid);
if (dev_hard_header(skb, net, ether_type,
is_broadcast ? &broadcast_hw : &guid,
is_broadcast ? net->broadcast : net->dev_addr,
NULL, skb->len) >= 0) {
struct fwnet_header *eth;
u16 *rawp;
Expand Down Expand Up @@ -649,7 +564,6 @@ static int fwnet_finish_incoming_packet(struct net_device *net,

return 0;

no_peer:
err:
net->stats.rx_errors++;
net->stats.rx_dropped++;
Expand Down Expand Up @@ -1355,44 +1269,25 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
ptask->dest_node = IEEE1394_ALL_NODES;
ptask->speed = SCODE_100;
} else {
__be64 guid = get_unaligned((__be64 *)hdr_buf.h_dest);
union fwnet_hwaddr *ha = (union fwnet_hwaddr *)hdr_buf.h_dest;
__be64 guid = get_unaligned(&ha->uc.uniq_id);
u8 generation;

peer = fwnet_peer_find_by_guid(dev, be64_to_cpu(guid));
if (!peer || peer->fifo == FWNET_NO_FIFO_ADDR)
if (!peer)
goto fail;

generation = peer->generation;
dest_node = peer->node_id;
max_payload = peer->max_payload;
datagram_label_ptr = &peer->datagram_label;

ptask->fifo_addr = peer->fifo;
ptask->fifo_addr = fwnet_hwaddr_fifo(ha);
ptask->generation = generation;
ptask->dest_node = dest_node;
ptask->speed = peer->speed;
}

/* If this is an ARP packet, convert it */
if (proto == htons(ETH_P_ARP)) {
struct arphdr *arp = (struct arphdr *)skb->data;
unsigned char *arp_ptr = (unsigned char *)(arp + 1);
struct rfc2734_arp *arp1394 = (struct rfc2734_arp *)skb->data;
__be32 ipaddr;

ipaddr = get_unaligned((__be32 *)(arp_ptr + FWNET_ALEN));

arp1394->hw_addr_len = RFC2734_HW_ADDR_LEN;
arp1394->max_rec = dev->card->max_receive;
arp1394->sspd = dev->card->link_speed;

put_unaligned_be16(dev->local_fifo >> 32,
&arp1394->fifo_hi);
put_unaligned_be32(dev->local_fifo & 0xffffffff,
&arp1394->fifo_lo);
put_unaligned(ipaddr, &arp1394->sip);
}

ptask->hdr.w0 = 0;
ptask->hdr.w1 = 0;
ptask->skb = skb;
Expand Down Expand Up @@ -1507,8 +1402,6 @@ static int fwnet_add_peer(struct fwnet_device *dev,

peer->dev = dev;
peer->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
peer->fifo = FWNET_NO_FIFO_ADDR;
peer->ip = 0;
INIT_LIST_HEAD(&peer->pd_list);
peer->pdg_size = 0;
peer->datagram_label = 0;
Expand Down Expand Up @@ -1538,6 +1431,7 @@ static int fwnet_probe(struct device *_dev)
struct fwnet_device *dev;
unsigned max_mtu;
int ret;
union fwnet_hwaddr *ha;

mutex_lock(&fwnet_device_mutex);

Expand Down Expand Up @@ -1582,8 +1476,15 @@ static int fwnet_probe(struct device *_dev)
net->mtu = min(1500U, max_mtu);

/* Set our hardware address while we're at it */
put_unaligned_be64(card->guid, net->dev_addr);
put_unaligned_be64(~0ULL, net->broadcast);
ha = (union fwnet_hwaddr *)net->dev_addr;
put_unaligned_be64(card->guid, &ha->uc.uniq_id);
ha->uc.max_rec = dev->card->max_receive;
ha->uc.sspd = dev->card->link_speed;
put_unaligned_be16(dev->local_fifo >> 32, &ha->uc.fifo_hi);
put_unaligned_be32(dev->local_fifo & 0xffffffff, &ha->uc.fifo_lo);

memset(net->broadcast, -1, net->addr_len);

ret = register_netdev(net);
if (ret)
goto out;
Expand Down Expand Up @@ -1632,8 +1533,6 @@ static int fwnet_remove(struct device *_dev)
mutex_lock(&fwnet_device_mutex);

net = dev->netdev;
if (net && peer->ip)
arp_invalidate(net, peer->ip);

fwnet_remove_peer(peer, dev);

Expand Down
12 changes: 10 additions & 2 deletions trunk/include/linux/if_arp.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,15 @@ static inline struct arphdr *arp_hdr(const struct sk_buff *skb)

static inline int arp_hdr_len(struct net_device *dev)
{
/* ARP header, plus 2 device addresses, plus 2 IP addresses. */
return sizeof(struct arphdr) + (dev->addr_len + sizeof(u32)) * 2;
switch (dev->type) {
#if IS_ENABLED(CONFIG_FIREWIRE_NET)
case ARPHRD_IEEE1394:
/* ARP header, device address and 2 IP addresses */
return sizeof(struct arphdr) + dev->addr_len + sizeof(u32) * 2;
#endif
default:
/* ARP header, plus 2 device addresses, plus 2 IP addresses. */
return sizeof(struct arphdr) + (dev->addr_len + sizeof(u32)) * 2;
}
}
#endif /* _LINUX_IF_ARP_H */
25 changes: 25 additions & 0 deletions trunk/include/net/firewire.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef _NET_FIREWIRE_H
#define _NET_FIREWIRE_H

/* Pseudo L2 address */
#define FWNET_ALEN 16
union fwnet_hwaddr {
u8 u[FWNET_ALEN];
/* "Hardware address" defined in RFC2734/RF3146 */
struct {
__be64 uniq_id; /* EUI-64 */
u8 max_rec; /* max packet size */
u8 sspd; /* max speed */
__be16 fifo_hi; /* hi 16bits of FIFO addr */
__be32 fifo_lo; /* lo 32bits of FIFO addr */
} __packed uc;
};

/* Pseudo L2 Header */
#define FWNET_HLEN 18
struct fwnet_header {
u8 h_dest[FWNET_ALEN]; /* destination address */
__be16 h_proto; /* packet type ID field */
} __packed;

#endif
27 changes: 21 additions & 6 deletions trunk/net/ipv4/arp.c
Original file line number Diff line number Diff line change
Expand Up @@ -654,11 +654,19 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
arp_ptr += dev->addr_len;
memcpy(arp_ptr, &src_ip, 4);
arp_ptr += 4;
if (target_hw != NULL)
memcpy(arp_ptr, target_hw, dev->addr_len);
else
memset(arp_ptr, 0, dev->addr_len);
arp_ptr += dev->addr_len;

switch (dev->type) {
#if IS_ENABLED(CONFIG_FIREWIRE_NET)
case ARPHRD_IEEE1394:
break;
#endif
default:
if (target_hw != NULL)
memcpy(arp_ptr, target_hw, dev->addr_len);
else
memset(arp_ptr, 0, dev->addr_len);
arp_ptr += dev->addr_len;
}
memcpy(arp_ptr, &dest_ip, 4);

return skb;
Expand Down Expand Up @@ -781,7 +789,14 @@ static int arp_process(struct sk_buff *skb)
arp_ptr += dev->addr_len;
memcpy(&sip, arp_ptr, 4);
arp_ptr += 4;
arp_ptr += dev->addr_len;
switch (dev_type) {
#if IS_ENABLED(CONFIG_FIREWIRE_NET)
case ARPHRD_IEEE1394:
break;
#endif
default:
arp_ptr += dev->addr_len;
}
memcpy(&tip, arp_ptr, 4);
/*
* Check for bad requests for 127.x.x.x and requests for multicast
Expand Down

0 comments on commit 61d38cc

Please sign in to comment.