aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org>2013-03-25 04:26:24 -0400
committerDavid S. Miller <davem@davemloft.net>2013-03-26 12:32:13 -0400
commitcb6bf35502d53364d15737295bc64f804c4587ce (patch)
tree5b139f5beb784ea6f9956bec12f8c21a95d228ff /drivers/firewire
parent6752c8db8e0cfedb44ba62806dd15b383ed64000 (diff)
firewire net, ipv6: IPv6 over Firewire (RFC3146) support.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/Kconfig6
-rw-r--r--drivers/firewire/net.c79
2 files changed, 77 insertions, 8 deletions
diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig
index 7224533e8ca6..7a701a58bbf0 100644
--- a/drivers/firewire/Kconfig
+++ b/drivers/firewire/Kconfig
@@ -47,9 +47,9 @@ config FIREWIRE_NET
47 tristate "IP networking over 1394" 47 tristate "IP networking over 1394"
48 depends on FIREWIRE && INET 48 depends on FIREWIRE && INET
49 help 49 help
50 This enables IPv4 over IEEE 1394, providing IP connectivity with 50 This enables IPv4/IPv6 over IEEE 1394, providing IP connectivity
51 other implementations of RFC 2734 as found on several operating 51 with other implementations of RFC 2734/3146 as found on several
52 systems. Multicast support is currently limited. 52 operating systems. Multicast support is currently limited.
53 53
54 To compile this driver as a module, say M here: The module will be 54 To compile this driver as a module, say M here: The module will be
55 called firewire-net. 55 called firewire-net.
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 790017eb5051..56796330a162 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * IPv4 over IEEE 1394, per RFC 2734 2 * IPv4 over IEEE 1394, per RFC 2734
3 * IPv6 over IEEE 1394, per RFC 3146
3 * 4 *
4 * Copyright (C) 2009 Jay Fenlason <fenlason@redhat.com> 5 * Copyright (C) 2009 Jay Fenlason <fenlason@redhat.com>
5 * 6 *
@@ -46,6 +47,7 @@
46 47
47#define IANA_SPECIFIER_ID 0x00005eU 48#define IANA_SPECIFIER_ID 0x00005eU
48#define RFC2734_SW_VERSION 0x000001U 49#define RFC2734_SW_VERSION 0x000001U
50#define RFC3146_SW_VERSION 0x000002U
49 51
50#define IEEE1394_GASP_HDR_SIZE 8 52#define IEEE1394_GASP_HDR_SIZE 8
51 53
@@ -505,6 +507,9 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
505 switch (ether_type) { 507 switch (ether_type) {
506 case ETH_P_ARP: 508 case ETH_P_ARP:
507 case ETH_P_IP: 509 case ETH_P_IP:
510#if IS_ENABLED(CONFIG_IPV6)
511 case ETH_P_IPV6:
512#endif
508 break; 513 break;
509 default: 514 default:
510 goto err; 515 goto err;
@@ -768,7 +773,12 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
768 ver = be32_to_cpu(buf_ptr[1]) & 0xffffff; 773 ver = be32_to_cpu(buf_ptr[1]) & 0xffffff;
769 source_node_id = be32_to_cpu(buf_ptr[0]) >> 16; 774 source_node_id = be32_to_cpu(buf_ptr[0]) >> 16;
770 775
771 if (specifier_id == IANA_SPECIFIER_ID && ver == RFC2734_SW_VERSION) { 776 if (specifier_id == IANA_SPECIFIER_ID &&
777 (ver == RFC2734_SW_VERSION
778#if IS_ENABLED(CONFIG_IPV6)
779 || ver == RFC3146_SW_VERSION
780#endif
781 )) {
772 buf_ptr += 2; 782 buf_ptr += 2;
773 length -= IEEE1394_GASP_HDR_SIZE; 783 length -= IEEE1394_GASP_HDR_SIZE;
774 fwnet_incoming_packet(dev, buf_ptr, length, source_node_id, 784 fwnet_incoming_packet(dev, buf_ptr, length, source_node_id,
@@ -971,16 +981,27 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask)
971 u8 *p; 981 u8 *p;
972 int generation; 982 int generation;
973 int node_id; 983 int node_id;
984 unsigned int sw_version;
974 985
975 /* ptask->generation may not have been set yet */ 986 /* ptask->generation may not have been set yet */
976 generation = dev->card->generation; 987 generation = dev->card->generation;
977 smp_rmb(); 988 smp_rmb();
978 node_id = dev->card->node_id; 989 node_id = dev->card->node_id;
979 990
991 switch (ptask->skb->protocol) {
992 default:
993 sw_version = RFC2734_SW_VERSION;
994 break;
995#if IS_ENABLED(CONFIG_IPV6)
996 case htons(ETH_P_IPV6):
997 sw_version = RFC3146_SW_VERSION;
998#endif
999 }
1000
980 p = skb_push(ptask->skb, IEEE1394_GASP_HDR_SIZE); 1001 p = skb_push(ptask->skb, IEEE1394_GASP_HDR_SIZE);
981 put_unaligned_be32(node_id << 16 | IANA_SPECIFIER_ID >> 8, p); 1002 put_unaligned_be32(node_id << 16 | IANA_SPECIFIER_ID >> 8, p);
982 put_unaligned_be32((IANA_SPECIFIER_ID & 0xff) << 24 1003 put_unaligned_be32((IANA_SPECIFIER_ID & 0xff) << 24
983 | RFC2734_SW_VERSION, &p[4]); 1004 | sw_version, &p[4]);
984 1005
985 /* We should not transmit if broadcast_channel.valid == 0. */ 1006 /* We should not transmit if broadcast_channel.valid == 0. */
986 fw_send_request(dev->card, &ptask->transaction, 1007 fw_send_request(dev->card, &ptask->transaction,
@@ -1248,6 +1269,9 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
1248 switch (proto) { 1269 switch (proto) {
1249 case htons(ETH_P_ARP): 1270 case htons(ETH_P_ARP):
1250 case htons(ETH_P_IP): 1271 case htons(ETH_P_IP):
1272#if IS_ENABLED(CONFIG_IPV6)
1273 case htons(ETH_P_IPV6):
1274#endif
1251 break; 1275 break;
1252 default: 1276 default:
1253 goto fail; 1277 goto fail;
@@ -1490,7 +1514,7 @@ static int fwnet_probe(struct device *_dev)
1490 goto out; 1514 goto out;
1491 1515
1492 list_add_tail(&dev->dev_link, &fwnet_device_list); 1516 list_add_tail(&dev->dev_link, &fwnet_device_list);
1493 dev_notice(&net->dev, "IPv4 over IEEE 1394 on card %s\n", 1517 dev_notice(&net->dev, "IP over IEEE 1394 on card %s\n",
1494 dev_name(card->device)); 1518 dev_name(card->device));
1495 have_dev: 1519 have_dev:
1496 ret = fwnet_add_peer(dev, unit, device); 1520 ret = fwnet_add_peer(dev, unit, device);
@@ -1579,6 +1603,14 @@ static const struct ieee1394_device_id fwnet_id_table[] = {
1579 .specifier_id = IANA_SPECIFIER_ID, 1603 .specifier_id = IANA_SPECIFIER_ID,
1580 .version = RFC2734_SW_VERSION, 1604 .version = RFC2734_SW_VERSION,
1581 }, 1605 },
1606#if IS_ENABLED(CONFIG_IPV6)
1607 {
1608 .match_flags = IEEE1394_MATCH_SPECIFIER_ID |
1609 IEEE1394_MATCH_VERSION,
1610 .specifier_id = IANA_SPECIFIER_ID,
1611 .version = RFC3146_SW_VERSION,
1612 },
1613#endif
1582 { } 1614 { }
1583}; 1615};
1584 1616
@@ -1616,6 +1648,30 @@ static struct fw_descriptor rfc2374_unit_directory = {
1616 .data = rfc2374_unit_directory_data 1648 .data = rfc2374_unit_directory_data
1617}; 1649};
1618 1650
1651#if IS_ENABLED(CONFIG_IPV6)
1652static const u32 rfc3146_unit_directory_data[] = {
1653 0x00040000, /* directory_length */
1654 0x1200005e, /* unit_specifier_id: IANA */
1655 0x81000003, /* textual descriptor offset */
1656 0x13000002, /* unit_sw_version: RFC 3146 */
1657 0x81000005, /* textual descriptor offset */
1658 0x00030000, /* descriptor_length */
1659 0x00000000, /* text */
1660 0x00000000, /* minimal ASCII, en */
1661 0x49414e41, /* I A N A */
1662 0x00030000, /* descriptor_length */
1663 0x00000000, /* text */
1664 0x00000000, /* minimal ASCII, en */
1665 0x49507636, /* I P v 6 */
1666};
1667
1668static struct fw_descriptor rfc3146_unit_directory = {
1669 .length = ARRAY_SIZE(rfc3146_unit_directory_data),
1670 .key = (CSR_DIRECTORY | CSR_UNIT) << 24,
1671 .data = rfc3146_unit_directory_data
1672};
1673#endif
1674
1619static int __init fwnet_init(void) 1675static int __init fwnet_init(void)
1620{ 1676{
1621 int err; 1677 int err;
@@ -1624,11 +1680,17 @@ static int __init fwnet_init(void)
1624 if (err) 1680 if (err)
1625 return err; 1681 return err;
1626 1682
1683#if IS_ENABLED(CONFIG_IPV6)
1684 err = fw_core_add_descriptor(&rfc3146_unit_directory);
1685 if (err)
1686 goto out;
1687#endif
1688
1627 fwnet_packet_task_cache = kmem_cache_create("packet_task", 1689 fwnet_packet_task_cache = kmem_cache_create("packet_task",
1628 sizeof(struct fwnet_packet_task), 0, 0, NULL); 1690 sizeof(struct fwnet_packet_task), 0, 0, NULL);
1629 if (!fwnet_packet_task_cache) { 1691 if (!fwnet_packet_task_cache) {
1630 err = -ENOMEM; 1692 err = -ENOMEM;
1631 goto out; 1693 goto out2;
1632 } 1694 }
1633 1695
1634 err = driver_register(&fwnet_driver.driver); 1696 err = driver_register(&fwnet_driver.driver);
@@ -1636,7 +1698,11 @@ static int __init fwnet_init(void)
1636 return 0; 1698 return 0;
1637 1699
1638 kmem_cache_destroy(fwnet_packet_task_cache); 1700 kmem_cache_destroy(fwnet_packet_task_cache);
1701out2:
1702#if IS_ENABLED(CONFIG_IPV6)
1703 fw_core_remove_descriptor(&rfc3146_unit_directory);
1639out: 1704out:
1705#endif
1640 fw_core_remove_descriptor(&rfc2374_unit_directory); 1706 fw_core_remove_descriptor(&rfc2374_unit_directory);
1641 1707
1642 return err; 1708 return err;
@@ -1647,11 +1713,14 @@ static void __exit fwnet_cleanup(void)
1647{ 1713{
1648 driver_unregister(&fwnet_driver.driver); 1714 driver_unregister(&fwnet_driver.driver);
1649 kmem_cache_destroy(fwnet_packet_task_cache); 1715 kmem_cache_destroy(fwnet_packet_task_cache);
1716#if IS_ENABLED(CONFIG_IPV6)
1717 fw_core_remove_descriptor(&rfc3146_unit_directory);
1718#endif
1650 fw_core_remove_descriptor(&rfc2374_unit_directory); 1719 fw_core_remove_descriptor(&rfc2374_unit_directory);
1651} 1720}
1652module_exit(fwnet_cleanup); 1721module_exit(fwnet_cleanup);
1653 1722
1654MODULE_AUTHOR("Jay Fenlason <fenlason@redhat.com>"); 1723MODULE_AUTHOR("Jay Fenlason <fenlason@redhat.com>");
1655MODULE_DESCRIPTION("IPv4 over IEEE1394 as per RFC 2734"); 1724MODULE_DESCRIPTION("IP over IEEE1394 as per RFC 2734/3146");
1656MODULE_LICENSE("GPL"); 1725MODULE_LICENSE("GPL");
1657MODULE_DEVICE_TABLE(ieee1394, fwnet_id_table); 1726MODULE_DEVICE_TABLE(ieee1394, fwnet_id_table);