diff options
author | David S. Miller <davem@davemloft.net> | 2014-10-30 20:01:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-10-30 20:01:27 -0400 |
commit | c1304b217c7cefa5718fab9d36c59ba0d0133c6e (patch) | |
tree | d4f4a4497056c8bbf9dd7435356e45f9bcbf9796 | |
parent | 39bb5e62867de82b269b07df900165029b928359 (diff) | |
parent | 5188cd44c55db3e92cd9e77a40b5baa7ed4340f7 (diff) |
Merge branch 'ufo-fix'
Ben Hutchings says:
====================
drivers/net,ipv6: Fix IPv6 fragment ID selection for virtio
The virtio net protocol supports UFO but does not provide for passing a
fragment ID for fragmentation of IPv6 packets. We used to generate a
fragment ID wherever such a packet was fragmented, but currently we
always use ID=0!
v2: Add blank lines after declarations
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/macvtap.c | 16 | ||||
-rw-r--r-- | drivers/net/tun.c | 25 | ||||
-rw-r--r-- | drivers/net/virtio_net.c | 24 | ||||
-rw-r--r-- | include/net/ipv6.h | 2 | ||||
-rw-r--r-- | net/ipv6/output_core.c | 34 |
5 files changed, 74 insertions, 27 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 65e2892342bd..6f226de655a4 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/idr.h> | 16 | #include <linux/idr.h> |
17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
18 | 18 | ||
19 | #include <net/ipv6.h> | ||
19 | #include <net/net_namespace.h> | 20 | #include <net/net_namespace.h> |
20 | #include <net/rtnetlink.h> | 21 | #include <net/rtnetlink.h> |
21 | #include <net/sock.h> | 22 | #include <net/sock.h> |
@@ -65,7 +66,7 @@ static struct cdev macvtap_cdev; | |||
65 | static const struct proto_ops macvtap_socket_ops; | 66 | static const struct proto_ops macvtap_socket_ops; |
66 | 67 | ||
67 | #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \ | 68 | #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \ |
68 | NETIF_F_TSO6 | NETIF_F_UFO) | 69 | NETIF_F_TSO6) |
69 | #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO) | 70 | #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO) |
70 | #define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG) | 71 | #define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG) |
71 | 72 | ||
@@ -569,7 +570,11 @@ static int macvtap_skb_from_vnet_hdr(struct sk_buff *skb, | |||
569 | gso_type = SKB_GSO_TCPV6; | 570 | gso_type = SKB_GSO_TCPV6; |
570 | break; | 571 | break; |
571 | case VIRTIO_NET_HDR_GSO_UDP: | 572 | case VIRTIO_NET_HDR_GSO_UDP: |
573 | pr_warn_once("macvtap: %s: using disabled UFO feature; please fix this program\n", | ||
574 | current->comm); | ||
572 | gso_type = SKB_GSO_UDP; | 575 | gso_type = SKB_GSO_UDP; |
576 | if (skb->protocol == htons(ETH_P_IPV6)) | ||
577 | ipv6_proxy_select_ident(skb); | ||
573 | break; | 578 | break; |
574 | default: | 579 | default: |
575 | return -EINVAL; | 580 | return -EINVAL; |
@@ -614,8 +619,6 @@ static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, | |||
614 | vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; | 619 | vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; |
615 | else if (sinfo->gso_type & SKB_GSO_TCPV6) | 620 | else if (sinfo->gso_type & SKB_GSO_TCPV6) |
616 | vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; | 621 | vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; |
617 | else if (sinfo->gso_type & SKB_GSO_UDP) | ||
618 | vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP; | ||
619 | else | 622 | else |
620 | BUG(); | 623 | BUG(); |
621 | if (sinfo->gso_type & SKB_GSO_TCP_ECN) | 624 | if (sinfo->gso_type & SKB_GSO_TCP_ECN) |
@@ -950,9 +953,6 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg) | |||
950 | if (arg & TUN_F_TSO6) | 953 | if (arg & TUN_F_TSO6) |
951 | feature_mask |= NETIF_F_TSO6; | 954 | feature_mask |= NETIF_F_TSO6; |
952 | } | 955 | } |
953 | |||
954 | if (arg & TUN_F_UFO) | ||
955 | feature_mask |= NETIF_F_UFO; | ||
956 | } | 956 | } |
957 | 957 | ||
958 | /* tun/tap driver inverts the usage for TSO offloads, where | 958 | /* tun/tap driver inverts the usage for TSO offloads, where |
@@ -963,7 +963,7 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg) | |||
963 | * When user space turns off TSO, we turn off GSO/LRO so that | 963 | * When user space turns off TSO, we turn off GSO/LRO so that |
964 | * user-space will not receive TSO frames. | 964 | * user-space will not receive TSO frames. |
965 | */ | 965 | */ |
966 | if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO)) | 966 | if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6)) |
967 | features |= RX_OFFLOADS; | 967 | features |= RX_OFFLOADS; |
968 | else | 968 | else |
969 | features &= ~RX_OFFLOADS; | 969 | features &= ~RX_OFFLOADS; |
@@ -1064,7 +1064,7 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, | |||
1064 | case TUNSETOFFLOAD: | 1064 | case TUNSETOFFLOAD: |
1065 | /* let the user check for future flags */ | 1065 | /* let the user check for future flags */ |
1066 | if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | | 1066 | if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | |
1067 | TUN_F_TSO_ECN | TUN_F_UFO)) | 1067 | TUN_F_TSO_ECN)) |
1068 | return -EINVAL; | 1068 | return -EINVAL; |
1069 | 1069 | ||
1070 | rtnl_lock(); | 1070 | rtnl_lock(); |
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 186ce541c657..7302398f0b1f 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -65,6 +65,7 @@ | |||
65 | #include <linux/nsproxy.h> | 65 | #include <linux/nsproxy.h> |
66 | #include <linux/virtio_net.h> | 66 | #include <linux/virtio_net.h> |
67 | #include <linux/rcupdate.h> | 67 | #include <linux/rcupdate.h> |
68 | #include <net/ipv6.h> | ||
68 | #include <net/net_namespace.h> | 69 | #include <net/net_namespace.h> |
69 | #include <net/netns/generic.h> | 70 | #include <net/netns/generic.h> |
70 | #include <net/rtnetlink.h> | 71 | #include <net/rtnetlink.h> |
@@ -174,7 +175,7 @@ struct tun_struct { | |||
174 | struct net_device *dev; | 175 | struct net_device *dev; |
175 | netdev_features_t set_features; | 176 | netdev_features_t set_features; |
176 | #define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ | 177 | #define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ |
177 | NETIF_F_TSO6|NETIF_F_UFO) | 178 | NETIF_F_TSO6) |
178 | 179 | ||
179 | int vnet_hdr_sz; | 180 | int vnet_hdr_sz; |
180 | int sndbuf; | 181 | int sndbuf; |
@@ -1139,6 +1140,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1139 | break; | 1140 | break; |
1140 | } | 1141 | } |
1141 | 1142 | ||
1143 | skb_reset_network_header(skb); | ||
1144 | |||
1142 | if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) { | 1145 | if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) { |
1143 | pr_debug("GSO!\n"); | 1146 | pr_debug("GSO!\n"); |
1144 | switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { | 1147 | switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { |
@@ -1149,8 +1152,20 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1149 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; | 1152 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; |
1150 | break; | 1153 | break; |
1151 | case VIRTIO_NET_HDR_GSO_UDP: | 1154 | case VIRTIO_NET_HDR_GSO_UDP: |
1155 | { | ||
1156 | static bool warned; | ||
1157 | |||
1158 | if (!warned) { | ||
1159 | warned = true; | ||
1160 | netdev_warn(tun->dev, | ||
1161 | "%s: using disabled UFO feature; please fix this program\n", | ||
1162 | current->comm); | ||
1163 | } | ||
1152 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; | 1164 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; |
1165 | if (skb->protocol == htons(ETH_P_IPV6)) | ||
1166 | ipv6_proxy_select_ident(skb); | ||
1153 | break; | 1167 | break; |
1168 | } | ||
1154 | default: | 1169 | default: |
1155 | tun->dev->stats.rx_frame_errors++; | 1170 | tun->dev->stats.rx_frame_errors++; |
1156 | kfree_skb(skb); | 1171 | kfree_skb(skb); |
@@ -1179,7 +1194,6 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1179 | skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; | 1194 | skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; |
1180 | } | 1195 | } |
1181 | 1196 | ||
1182 | skb_reset_network_header(skb); | ||
1183 | skb_probe_transport_header(skb, 0); | 1197 | skb_probe_transport_header(skb, 0); |
1184 | 1198 | ||
1185 | rxhash = skb_get_hash(skb); | 1199 | rxhash = skb_get_hash(skb); |
@@ -1251,8 +1265,6 @@ static ssize_t tun_put_user(struct tun_struct *tun, | |||
1251 | gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; | 1265 | gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; |
1252 | else if (sinfo->gso_type & SKB_GSO_TCPV6) | 1266 | else if (sinfo->gso_type & SKB_GSO_TCPV6) |
1253 | gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; | 1267 | gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; |
1254 | else if (sinfo->gso_type & SKB_GSO_UDP) | ||
1255 | gso.gso_type = VIRTIO_NET_HDR_GSO_UDP; | ||
1256 | else { | 1268 | else { |
1257 | pr_err("unexpected GSO type: " | 1269 | pr_err("unexpected GSO type: " |
1258 | "0x%x, gso_size %d, hdr_len %d\n", | 1270 | "0x%x, gso_size %d, hdr_len %d\n", |
@@ -1762,11 +1774,6 @@ static int set_offload(struct tun_struct *tun, unsigned long arg) | |||
1762 | features |= NETIF_F_TSO6; | 1774 | features |= NETIF_F_TSO6; |
1763 | arg &= ~(TUN_F_TSO4|TUN_F_TSO6); | 1775 | arg &= ~(TUN_F_TSO4|TUN_F_TSO6); |
1764 | } | 1776 | } |
1765 | |||
1766 | if (arg & TUN_F_UFO) { | ||
1767 | features |= NETIF_F_UFO; | ||
1768 | arg &= ~TUN_F_UFO; | ||
1769 | } | ||
1770 | } | 1777 | } |
1771 | 1778 | ||
1772 | /* This gives the user a way to test for new features in future by | 1779 | /* This gives the user a way to test for new features in future by |
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index d75256bd1a6a..ec2a8b41ed41 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -491,8 +491,17 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) | |||
491 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; | 491 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; |
492 | break; | 492 | break; |
493 | case VIRTIO_NET_HDR_GSO_UDP: | 493 | case VIRTIO_NET_HDR_GSO_UDP: |
494 | { | ||
495 | static bool warned; | ||
496 | |||
497 | if (!warned) { | ||
498 | warned = true; | ||
499 | netdev_warn(dev, | ||
500 | "host using disabled UFO feature; please fix it\n"); | ||
501 | } | ||
494 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; | 502 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; |
495 | break; | 503 | break; |
504 | } | ||
496 | case VIRTIO_NET_HDR_GSO_TCPV6: | 505 | case VIRTIO_NET_HDR_GSO_TCPV6: |
497 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; | 506 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; |
498 | break; | 507 | break; |
@@ -881,8 +890,6 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) | |||
881 | hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; | 890 | hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; |
882 | else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) | 891 | else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) |
883 | hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; | 892 | hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; |
884 | else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) | ||
885 | hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_UDP; | ||
886 | else | 893 | else |
887 | BUG(); | 894 | BUG(); |
888 | if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN) | 895 | if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN) |
@@ -1705,7 +1712,7 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
1705 | dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; | 1712 | dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; |
1706 | 1713 | ||
1707 | if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) { | 1714 | if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) { |
1708 | dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO | 1715 | dev->hw_features |= NETIF_F_TSO |
1709 | | NETIF_F_TSO_ECN | NETIF_F_TSO6; | 1716 | | NETIF_F_TSO_ECN | NETIF_F_TSO6; |
1710 | } | 1717 | } |
1711 | /* Individual feature bits: what can host handle? */ | 1718 | /* Individual feature bits: what can host handle? */ |
@@ -1715,11 +1722,9 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
1715 | dev->hw_features |= NETIF_F_TSO6; | 1722 | dev->hw_features |= NETIF_F_TSO6; |
1716 | if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN)) | 1723 | if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN)) |
1717 | dev->hw_features |= NETIF_F_TSO_ECN; | 1724 | dev->hw_features |= NETIF_F_TSO_ECN; |
1718 | if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO)) | ||
1719 | dev->hw_features |= NETIF_F_UFO; | ||
1720 | 1725 | ||
1721 | if (gso) | 1726 | if (gso) |
1722 | dev->features |= dev->hw_features & (NETIF_F_ALL_TSO|NETIF_F_UFO); | 1727 | dev->features |= dev->hw_features & NETIF_F_ALL_TSO; |
1723 | /* (!csum && gso) case will be fixed by register_netdev() */ | 1728 | /* (!csum && gso) case will be fixed by register_netdev() */ |
1724 | } | 1729 | } |
1725 | if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM)) | 1730 | if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM)) |
@@ -1757,8 +1762,7 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
1757 | /* If we can receive ANY GSO packets, we must allocate large ones. */ | 1762 | /* If we can receive ANY GSO packets, we must allocate large ones. */ |
1758 | if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) || | 1763 | if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) || |
1759 | virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) || | 1764 | virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) || |
1760 | virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN) || | 1765 | virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN)) |
1761 | virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UFO)) | ||
1762 | vi->big_packets = true; | 1766 | vi->big_packets = true; |
1763 | 1767 | ||
1764 | if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) | 1768 | if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) |
@@ -1952,9 +1956,9 @@ static struct virtio_device_id id_table[] = { | |||
1952 | static unsigned int features[] = { | 1956 | static unsigned int features[] = { |
1953 | VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, | 1957 | VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, |
1954 | VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC, | 1958 | VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC, |
1955 | VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, | 1959 | VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_TSO6, |
1956 | VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, | 1960 | VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, |
1957 | VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO, | 1961 | VIRTIO_NET_F_GUEST_ECN, |
1958 | VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, | 1962 | VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, |
1959 | VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, | 1963 | VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, |
1960 | VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, | 1964 | VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, |
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 97f472012438..4292929392b0 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
@@ -671,6 +671,8 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add | |||
671 | return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr)); | 671 | return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr)); |
672 | } | 672 | } |
673 | 673 | ||
674 | void ipv6_proxy_select_ident(struct sk_buff *skb); | ||
675 | |||
674 | int ip6_dst_hoplimit(struct dst_entry *dst); | 676 | int ip6_dst_hoplimit(struct dst_entry *dst); |
675 | 677 | ||
676 | static inline int ip6_sk_dst_hoplimit(struct ipv6_pinfo *np, struct flowi6 *fl6, | 678 | static inline int ip6_sk_dst_hoplimit(struct ipv6_pinfo *np, struct flowi6 *fl6, |
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index fc24c390af05..97f41a3e68d9 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c | |||
@@ -3,11 +3,45 @@ | |||
3 | * not configured or static. These functions are needed by GSO/GRO implementation. | 3 | * not configured or static. These functions are needed by GSO/GRO implementation. |
4 | */ | 4 | */ |
5 | #include <linux/export.h> | 5 | #include <linux/export.h> |
6 | #include <net/ip.h> | ||
6 | #include <net/ipv6.h> | 7 | #include <net/ipv6.h> |
7 | #include <net/ip6_fib.h> | 8 | #include <net/ip6_fib.h> |
8 | #include <net/addrconf.h> | 9 | #include <net/addrconf.h> |
9 | #include <net/secure_seq.h> | 10 | #include <net/secure_seq.h> |
10 | 11 | ||
12 | /* This function exists only for tap drivers that must support broken | ||
13 | * clients requesting UFO without specifying an IPv6 fragment ID. | ||
14 | * | ||
15 | * This is similar to ipv6_select_ident() but we use an independent hash | ||
16 | * seed to limit information leakage. | ||
17 | * | ||
18 | * The network header must be set before calling this. | ||
19 | */ | ||
20 | void ipv6_proxy_select_ident(struct sk_buff *skb) | ||
21 | { | ||
22 | static u32 ip6_proxy_idents_hashrnd __read_mostly; | ||
23 | struct in6_addr buf[2]; | ||
24 | struct in6_addr *addrs; | ||
25 | u32 hash, id; | ||
26 | |||
27 | addrs = skb_header_pointer(skb, | ||
28 | skb_network_offset(skb) + | ||
29 | offsetof(struct ipv6hdr, saddr), | ||
30 | sizeof(buf), buf); | ||
31 | if (!addrs) | ||
32 | return; | ||
33 | |||
34 | net_get_random_once(&ip6_proxy_idents_hashrnd, | ||
35 | sizeof(ip6_proxy_idents_hashrnd)); | ||
36 | |||
37 | hash = __ipv6_addr_jhash(&addrs[1], ip6_proxy_idents_hashrnd); | ||
38 | hash = __ipv6_addr_jhash(&addrs[0], hash); | ||
39 | |||
40 | id = ip_idents_reserve(hash, 1); | ||
41 | skb_shinfo(skb)->ip6_frag_id = htonl(id); | ||
42 | } | ||
43 | EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident); | ||
44 | |||
11 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | 45 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) |
12 | { | 46 | { |
13 | u16 offset = sizeof(struct ipv6hdr); | 47 | u16 offset = sizeof(struct ipv6hdr); |