aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/net.c
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org>2013-03-25 04:26:16 -0400
committerDavid S. Miller <davem@davemloft.net>2013-03-26 12:32:13 -0400
commit6752c8db8e0cfedb44ba62806dd15b383ed64000 (patch)
tree96272aed0ff52f72a1d97d8a8d86d90f5f47809e /drivers/firewire/net.c
parent61a7839a19c157d11930fe69697a4c90884bf7c4 (diff)
firewire net, ipv4 arp: Extend hardware address and remove driver-level packet inspection.
Inspection of upper layer protocol is considered harmful, especially if it is about ARP or other stateful upper layer protocol; driver cannot (and should not) have full state of them. IPv4 over Firewire module used to inspect ARP (both in sending path and in receiving path), and record peer's GUID, max packet size, max speed and fifo address. This patch removes such inspection by extending our "hardware address" definition to include other information as well: max packet size, max speed and fifo. By doing this, The neighbour module in networking subsystem can cache them. Note: As we have started ignoring sspd and max_rec in ARP/NDP, those information will not be used in the driver when sending. When a packet is being sent, the IP layer fills our pseudo header with the extended "hardware address", including GUID and fifo. The driver can look-up node-id (the real but rather volatile low-level address) by GUID, and then the module can send the packet to the wire using parameters provided in the extendedn hardware address. This approach is realistic because IP over IEEE1394 (RFC2734) and IPv6 over IEEE1394 (RFC3146) share same "hardware address" format in their address resolution protocols. Here, extended "hardware address" is defined as follows: union fwnet_hwaddr { u8 u[16]; 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; }; Note that Hardware address is declared as union, so that we can map full IP address into this, when implementing MCAP (Multicast Cannel Allocation Protocol) for IPv6, but IP and ARP subsystem do not need to know this format in detail. One difference between original ARP (RFC826) and 1394 ARP (RFC2734) is that 1394 ARP Request/Reply do not contain the target hardware address field (aka ar$tha). This difference is handled in the ARP subsystem. CC: Stephan Gatzka <stephan.gatzka@gmail.com> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/firewire/net.c')
-rw-r--r--drivers/firewire/net.c153
1 files changed, 26 insertions, 127 deletions
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index cb8aa865ff88..790017eb5051 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -28,6 +28,7 @@
28 28
29#include <asm/unaligned.h> 29#include <asm/unaligned.h>
30#include <net/arp.h> 30#include <net/arp.h>
31#include <net/firewire.h>
31 32
32/* rx limits */ 33/* rx limits */
33#define FWNET_MAX_FRAGMENTS 30 /* arbitrary, > TX queue depth */ 34#define FWNET_MAX_FRAGMENTS 30 /* arbitrary, > TX queue depth */
@@ -57,33 +58,6 @@
57#define RFC2374_HDR_LASTFRAG 2 /* last fragment */ 58#define RFC2374_HDR_LASTFRAG 2 /* last fragment */
58#define RFC2374_HDR_INTFRAG 3 /* interior fragment */ 59#define RFC2374_HDR_INTFRAG 3 /* interior fragment */
59 60
60#define RFC2734_HW_ADDR_LEN 16
61
62struct rfc2734_arp {
63 __be16 hw_type; /* 0x0018 */
64 __be16 proto_type; /* 0x0806 */
65 u8 hw_addr_len; /* 16 */
66 u8 ip_addr_len; /* 4 */
67 __be16 opcode; /* ARP Opcode */
68 /* Above is exactly the same format as struct arphdr */
69
70 __be64 s_uniq_id; /* Sender's 64bit EUI */
71 u8 max_rec; /* Sender's max packet size */
72 u8 sspd; /* Sender's max speed */
73 __be16 fifo_hi; /* hi 16bits of sender's FIFO addr */
74 __be32 fifo_lo; /* lo 32bits of sender's FIFO addr */
75 __be32 sip; /* Sender's IP Address */
76 __be32 tip; /* IP Address of requested hw addr */
77} __packed;
78
79/* This header format is specific to this driver implementation. */
80#define FWNET_ALEN 8
81#define FWNET_HLEN 10
82struct fwnet_header {
83 u8 h_dest[FWNET_ALEN]; /* destination address */
84 __be16 h_proto; /* packet type ID field */
85} __packed;
86
87static bool fwnet_hwaddr_is_multicast(u8 *ha) 61static bool fwnet_hwaddr_is_multicast(u8 *ha)
88{ 62{
89 return !!(*ha & 1); 63 return !!(*ha & 1);
@@ -196,8 +170,6 @@ struct fwnet_peer {
196 struct list_head peer_link; 170 struct list_head peer_link;
197 struct fwnet_device *dev; 171 struct fwnet_device *dev;
198 u64 guid; 172 u64 guid;
199 u64 fifo;
200 __be32 ip;
201 173
202 /* guarded by dev->lock */ 174 /* guarded by dev->lock */
203 struct list_head pd_list; /* received partial datagrams */ 175 struct list_head pd_list; /* received partial datagrams */
@@ -227,6 +199,15 @@ struct fwnet_packet_task {
227}; 199};
228 200
229/* 201/*
202 * Get fifo address embedded in hwaddr
203 */
204static __u64 fwnet_hwaddr_fifo(union fwnet_hwaddr *ha)
205{
206 return (u64)get_unaligned_be16(&ha->uc.fifo_hi) << 32
207 | get_unaligned_be32(&ha->uc.fifo_lo);
208}
209
210/*
230 * saddr == NULL means use device source address. 211 * saddr == NULL means use device source address.
231 * daddr == NULL means leave destination address (eg unresolved arp). 212 * daddr == NULL means leave destination address (eg unresolved arp).
232 */ 213 */
@@ -518,7 +499,6 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
518 bool is_broadcast, u16 ether_type) 499 bool is_broadcast, u16 ether_type)
519{ 500{
520 struct fwnet_device *dev; 501 struct fwnet_device *dev;
521 static const __be64 broadcast_hw = cpu_to_be64(~0ULL);
522 int status; 502 int status;
523 __be64 guid; 503 __be64 guid;
524 504
@@ -537,76 +517,11 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
537 517
538 /* 518 /*
539 * Parse the encapsulation header. This actually does the job of 519 * Parse the encapsulation header. This actually does the job of
540 * converting to an ethernet frame header, as well as arp 520 * converting to an ethernet-like pseudo frame header.
541 * conversion if needed. ARP conversion is easier in this
542 * direction, since we are using ethernet as our backend.
543 */
544 /*
545 * If this is an ARP packet, convert it. First, we want to make
546 * use of some of the fields, since they tell us a little bit
547 * about the sending machine.
548 */ 521 */
549 if (ether_type == ETH_P_ARP) {
550 struct rfc2734_arp *arp1394;
551 struct arphdr *arp;
552 unsigned char *arp_ptr;
553 u64 fifo_addr;
554 u64 peer_guid;
555 struct fwnet_peer *peer;
556 unsigned long flags;
557
558 arp1394 = (struct rfc2734_arp *)skb->data;
559 arp = (struct arphdr *)skb->data;
560 arp_ptr = (unsigned char *)(arp + 1);
561 peer_guid = get_unaligned_be64(&arp1394->s_uniq_id);
562 fifo_addr = (u64)get_unaligned_be16(&arp1394->fifo_hi) << 32
563 | get_unaligned_be32(&arp1394->fifo_lo);
564
565 spin_lock_irqsave(&dev->lock, flags);
566 peer = fwnet_peer_find_by_guid(dev, peer_guid);
567 if (peer) {
568 peer->fifo = fifo_addr;
569 peer->ip = arp1394->sip;
570 }
571 spin_unlock_irqrestore(&dev->lock, flags);
572
573 if (!peer) {
574 dev_notice(&net->dev,
575 "no peer for ARP packet from %016llx\n",
576 (unsigned long long)peer_guid);
577 goto no_peer;
578 }
579
580 /*
581 * Now that we're done with the 1394 specific stuff, we'll
582 * need to alter some of the data. Believe it or not, all
583 * that needs to be done is sender_IP_address needs to be
584 * moved, the destination hardware address get stuffed
585 * in and the hardware address length set to 8.
586 *
587 * IMPORTANT: The code below overwrites 1394 specific data
588 * needed above so keep the munging of the data for the
589 * higher level IP stack last.
590 */
591
592 arp->ar_hln = 8;
593 /* skip over sender unique id */
594 arp_ptr += arp->ar_hln;
595 /* move sender IP addr */
596 put_unaligned(arp1394->sip, (u32 *)arp_ptr);
597 /* skip over sender IP addr */
598 arp_ptr += arp->ar_pln;
599
600 if (arp->ar_op == htons(ARPOP_REQUEST))
601 memset(arp_ptr, 0, sizeof(u64));
602 else
603 memcpy(arp_ptr, net->dev_addr, sizeof(u64));
604 }
605
606 /* Now add the ethernet header. */
607 guid = cpu_to_be64(dev->card->guid); 522 guid = cpu_to_be64(dev->card->guid);
608 if (dev_hard_header(skb, net, ether_type, 523 if (dev_hard_header(skb, net, ether_type,
609 is_broadcast ? &broadcast_hw : &guid, 524 is_broadcast ? net->broadcast : net->dev_addr,
610 NULL, skb->len) >= 0) { 525 NULL, skb->len) >= 0) {
611 struct fwnet_header *eth; 526 struct fwnet_header *eth;
612 u16 *rawp; 527 u16 *rawp;
@@ -649,7 +564,6 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
649 564
650 return 0; 565 return 0;
651 566
652 no_peer:
653 err: 567 err:
654 net->stats.rx_errors++; 568 net->stats.rx_errors++;
655 net->stats.rx_dropped++; 569 net->stats.rx_dropped++;
@@ -1355,11 +1269,12 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
1355 ptask->dest_node = IEEE1394_ALL_NODES; 1269 ptask->dest_node = IEEE1394_ALL_NODES;
1356 ptask->speed = SCODE_100; 1270 ptask->speed = SCODE_100;
1357 } else { 1271 } else {
1358 __be64 guid = get_unaligned((__be64 *)hdr_buf.h_dest); 1272 union fwnet_hwaddr *ha = (union fwnet_hwaddr *)hdr_buf.h_dest;
1273 __be64 guid = get_unaligned(&ha->uc.uniq_id);
1359 u8 generation; 1274 u8 generation;
1360 1275
1361 peer = fwnet_peer_find_by_guid(dev, be64_to_cpu(guid)); 1276 peer = fwnet_peer_find_by_guid(dev, be64_to_cpu(guid));
1362 if (!peer || peer->fifo == FWNET_NO_FIFO_ADDR) 1277 if (!peer)
1363 goto fail; 1278 goto fail;
1364 1279
1365 generation = peer->generation; 1280 generation = peer->generation;
@@ -1367,32 +1282,12 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
1367 max_payload = peer->max_payload; 1282 max_payload = peer->max_payload;
1368 datagram_label_ptr = &peer->datagram_label; 1283 datagram_label_ptr = &peer->datagram_label;
1369 1284
1370 ptask->fifo_addr = peer->fifo; 1285 ptask->fifo_addr = fwnet_hwaddr_fifo(ha);
1371 ptask->generation = generation; 1286 ptask->generation = generation;
1372 ptask->dest_node = dest_node; 1287 ptask->dest_node = dest_node;
1373 ptask->speed = peer->speed; 1288 ptask->speed = peer->speed;
1374 } 1289 }
1375 1290
1376 /* If this is an ARP packet, convert it */
1377 if (proto == htons(ETH_P_ARP)) {
1378 struct arphdr *arp = (struct arphdr *)skb->data;
1379 unsigned char *arp_ptr = (unsigned char *)(arp + 1);
1380 struct rfc2734_arp *arp1394 = (struct rfc2734_arp *)skb->data;
1381 __be32 ipaddr;
1382
1383 ipaddr = get_unaligned((__be32 *)(arp_ptr + FWNET_ALEN));
1384
1385 arp1394->hw_addr_len = RFC2734_HW_ADDR_LEN;
1386 arp1394->max_rec = dev->card->max_receive;
1387 arp1394->sspd = dev->card->link_speed;
1388
1389 put_unaligned_be16(dev->local_fifo >> 32,
1390 &arp1394->fifo_hi);
1391 put_unaligned_be32(dev->local_fifo & 0xffffffff,
1392 &arp1394->fifo_lo);
1393 put_unaligned(ipaddr, &arp1394->sip);
1394 }
1395
1396 ptask->hdr.w0 = 0; 1291 ptask->hdr.w0 = 0;
1397 ptask->hdr.w1 = 0; 1292 ptask->hdr.w1 = 0;
1398 ptask->skb = skb; 1293 ptask->skb = skb;
@@ -1507,8 +1402,6 @@ static int fwnet_add_peer(struct fwnet_device *dev,
1507 1402
1508 peer->dev = dev; 1403 peer->dev = dev;
1509 peer->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4]; 1404 peer->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
1510 peer->fifo = FWNET_NO_FIFO_ADDR;
1511 peer->ip = 0;
1512 INIT_LIST_HEAD(&peer->pd_list); 1405 INIT_LIST_HEAD(&peer->pd_list);
1513 peer->pdg_size = 0; 1406 peer->pdg_size = 0;
1514 peer->datagram_label = 0; 1407 peer->datagram_label = 0;
@@ -1538,6 +1431,7 @@ static int fwnet_probe(struct device *_dev)
1538 struct fwnet_device *dev; 1431 struct fwnet_device *dev;
1539 unsigned max_mtu; 1432 unsigned max_mtu;
1540 int ret; 1433 int ret;
1434 union fwnet_hwaddr *ha;
1541 1435
1542 mutex_lock(&fwnet_device_mutex); 1436 mutex_lock(&fwnet_device_mutex);
1543 1437
@@ -1582,8 +1476,15 @@ static int fwnet_probe(struct device *_dev)
1582 net->mtu = min(1500U, max_mtu); 1476 net->mtu = min(1500U, max_mtu);
1583 1477
1584 /* Set our hardware address while we're at it */ 1478 /* Set our hardware address while we're at it */
1585 put_unaligned_be64(card->guid, net->dev_addr); 1479 ha = (union fwnet_hwaddr *)net->dev_addr;
1586 put_unaligned_be64(~0ULL, net->broadcast); 1480 put_unaligned_be64(card->guid, &ha->uc.uniq_id);
1481 ha->uc.max_rec = dev->card->max_receive;
1482 ha->uc.sspd = dev->card->link_speed;
1483 put_unaligned_be16(dev->local_fifo >> 32, &ha->uc.fifo_hi);
1484 put_unaligned_be32(dev->local_fifo & 0xffffffff, &ha->uc.fifo_lo);
1485
1486 memset(net->broadcast, -1, net->addr_len);
1487
1587 ret = register_netdev(net); 1488 ret = register_netdev(net);
1588 if (ret) 1489 if (ret)
1589 goto out; 1490 goto out;
@@ -1632,8 +1533,6 @@ static int fwnet_remove(struct device *_dev)
1632 mutex_lock(&fwnet_device_mutex); 1533 mutex_lock(&fwnet_device_mutex);
1633 1534
1634 net = dev->netdev; 1535 net = dev->netdev;
1635 if (net && peer->ip)
1636 arp_invalidate(net, peer->ip);
1637 1536
1638 fwnet_remove_peer(peer, dev); 1537 fwnet_remove_peer(peer, dev);
1639 1538