diff options
author | YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org> | 2013-03-25 04:26:24 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-03-26 12:32:13 -0400 |
commit | cb6bf35502d53364d15737295bc64f804c4587ce (patch) | |
tree | 5b139f5beb784ea6f9956bec12f8c21a95d228ff /drivers/firewire | |
parent | 6752c8db8e0cfedb44ba62806dd15b383ed64000 (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/Kconfig | 6 | ||||
-rw-r--r-- | drivers/firewire/net.c | 79 |
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) | ||
1652 | static 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 | |||
1668 | static 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 | |||
1619 | static int __init fwnet_init(void) | 1675 | static 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); |
1701 | out2: | ||
1702 | #if IS_ENABLED(CONFIG_IPV6) | ||
1703 | fw_core_remove_descriptor(&rfc3146_unit_directory); | ||
1639 | out: | 1704 | out: |
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 | } |
1652 | module_exit(fwnet_cleanup); | 1721 | module_exit(fwnet_cleanup); |
1653 | 1722 | ||
1654 | MODULE_AUTHOR("Jay Fenlason <fenlason@redhat.com>"); | 1723 | MODULE_AUTHOR("Jay Fenlason <fenlason@redhat.com>"); |
1655 | MODULE_DESCRIPTION("IPv4 over IEEE1394 as per RFC 2734"); | 1724 | MODULE_DESCRIPTION("IP over IEEE1394 as per RFC 2734/3146"); |
1656 | MODULE_LICENSE("GPL"); | 1725 | MODULE_LICENSE("GPL"); |
1657 | MODULE_DEVICE_TABLE(ieee1394, fwnet_id_table); | 1726 | MODULE_DEVICE_TABLE(ieee1394, fwnet_id_table); |