diff options
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 49 | ||||
-rw-r--r-- | net/ipv6/sit.c | 33 |
2 files changed, 53 insertions, 29 deletions
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index fb828e9fe8e0..a14f28b280f5 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -74,6 +74,10 @@ MODULE_ALIAS_NETDEV("ip6tnl0"); | |||
74 | #define HASH_SIZE_SHIFT 5 | 74 | #define HASH_SIZE_SHIFT 5 |
75 | #define HASH_SIZE (1 << HASH_SIZE_SHIFT) | 75 | #define HASH_SIZE (1 << HASH_SIZE_SHIFT) |
76 | 76 | ||
77 | static bool log_ecn_error = true; | ||
78 | module_param(log_ecn_error, bool, 0644); | ||
79 | MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); | ||
80 | |||
77 | static u32 HASH(const struct in6_addr *addr1, const struct in6_addr *addr2) | 81 | static u32 HASH(const struct in6_addr *addr1, const struct in6_addr *addr2) |
78 | { | 82 | { |
79 | u32 hash = ipv6_addr_hash(addr1) ^ ipv6_addr_hash(addr2); | 83 | u32 hash = ipv6_addr_hash(addr1) ^ ipv6_addr_hash(addr2); |
@@ -683,28 +687,26 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
683 | return 0; | 687 | return 0; |
684 | } | 688 | } |
685 | 689 | ||
686 | static void ip4ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t, | 690 | static int ip4ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t, |
687 | const struct ipv6hdr *ipv6h, | 691 | const struct ipv6hdr *ipv6h, |
688 | struct sk_buff *skb) | 692 | struct sk_buff *skb) |
689 | { | 693 | { |
690 | __u8 dsfield = ipv6_get_dsfield(ipv6h) & ~INET_ECN_MASK; | 694 | __u8 dsfield = ipv6_get_dsfield(ipv6h) & ~INET_ECN_MASK; |
691 | 695 | ||
692 | if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) | 696 | if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) |
693 | ipv4_change_dsfield(ip_hdr(skb), INET_ECN_MASK, dsfield); | 697 | ipv4_change_dsfield(ip_hdr(skb), INET_ECN_MASK, dsfield); |
694 | 698 | ||
695 | if (INET_ECN_is_ce(dsfield)) | 699 | return IP6_ECN_decapsulate(ipv6h, skb); |
696 | IP_ECN_set_ce(ip_hdr(skb)); | ||
697 | } | 700 | } |
698 | 701 | ||
699 | static void ip6ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t, | 702 | static int ip6ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t, |
700 | const struct ipv6hdr *ipv6h, | 703 | const struct ipv6hdr *ipv6h, |
701 | struct sk_buff *skb) | 704 | struct sk_buff *skb) |
702 | { | 705 | { |
703 | if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) | 706 | if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) |
704 | ipv6_copy_dscp(ipv6_get_dsfield(ipv6h), ipv6_hdr(skb)); | 707 | ipv6_copy_dscp(ipv6_get_dsfield(ipv6h), ipv6_hdr(skb)); |
705 | 708 | ||
706 | if (INET_ECN_is_ce(ipv6_get_dsfield(ipv6h))) | 709 | return IP6_ECN_decapsulate(ipv6h, skb); |
707 | IP6_ECN_set_ce(ipv6_hdr(skb)); | ||
708 | } | 710 | } |
709 | 711 | ||
710 | __u32 ip6_tnl_get_cap(struct ip6_tnl *t, | 712 | __u32 ip6_tnl_get_cap(struct ip6_tnl *t, |
@@ -768,12 +770,13 @@ EXPORT_SYMBOL_GPL(ip6_tnl_rcv_ctl); | |||
768 | 770 | ||
769 | static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, | 771 | static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, |
770 | __u8 ipproto, | 772 | __u8 ipproto, |
771 | void (*dscp_ecn_decapsulate)(const struct ip6_tnl *t, | 773 | int (*dscp_ecn_decapsulate)(const struct ip6_tnl *t, |
772 | const struct ipv6hdr *ipv6h, | 774 | const struct ipv6hdr *ipv6h, |
773 | struct sk_buff *skb)) | 775 | struct sk_buff *skb)) |
774 | { | 776 | { |
775 | struct ip6_tnl *t; | 777 | struct ip6_tnl *t; |
776 | const struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 778 | const struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
779 | int err; | ||
777 | 780 | ||
778 | rcu_read_lock(); | 781 | rcu_read_lock(); |
779 | 782 | ||
@@ -803,14 +806,26 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, | |||
803 | skb->pkt_type = PACKET_HOST; | 806 | skb->pkt_type = PACKET_HOST; |
804 | memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); | 807 | memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); |
805 | 808 | ||
809 | __skb_tunnel_rx(skb, t->dev); | ||
810 | |||
811 | err = dscp_ecn_decapsulate(t, ipv6h, skb); | ||
812 | if (unlikely(err)) { | ||
813 | if (log_ecn_error) | ||
814 | net_info_ratelimited("non-ECT from %pI6 with dsfield=%#x\n", | ||
815 | &ipv6h->saddr, | ||
816 | ipv6_get_dsfield(ipv6h)); | ||
817 | if (err > 1) { | ||
818 | ++t->dev->stats.rx_frame_errors; | ||
819 | ++t->dev->stats.rx_errors; | ||
820 | rcu_read_unlock(); | ||
821 | goto discard; | ||
822 | } | ||
823 | } | ||
824 | |||
806 | tstats = this_cpu_ptr(t->dev->tstats); | 825 | tstats = this_cpu_ptr(t->dev->tstats); |
807 | tstats->rx_packets++; | 826 | tstats->rx_packets++; |
808 | tstats->rx_bytes += skb->len; | 827 | tstats->rx_bytes += skb->len; |
809 | 828 | ||
810 | __skb_tunnel_rx(skb, t->dev); | ||
811 | |||
812 | dscp_ecn_decapsulate(t, ipv6h, skb); | ||
813 | |||
814 | netif_rx(skb); | 829 | netif_rx(skb); |
815 | 830 | ||
816 | rcu_read_unlock(); | 831 | rcu_read_unlock(); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 80cb3829831c..cfba99b2c2a4 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -65,6 +65,10 @@ | |||
65 | #define HASH_SIZE 16 | 65 | #define HASH_SIZE 16 |
66 | #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) | 66 | #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) |
67 | 67 | ||
68 | static bool log_ecn_error = true; | ||
69 | module_param(log_ecn_error, bool, 0644); | ||
70 | MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); | ||
71 | |||
68 | static int ipip6_tunnel_init(struct net_device *dev); | 72 | static int ipip6_tunnel_init(struct net_device *dev); |
69 | static void ipip6_tunnel_setup(struct net_device *dev); | 73 | static void ipip6_tunnel_setup(struct net_device *dev); |
70 | static void ipip6_dev_free(struct net_device *dev); | 74 | static void ipip6_dev_free(struct net_device *dev); |
@@ -106,6 +110,7 @@ static struct rtnl_link_stats64 *ipip6_get_stats64(struct net_device *dev, | |||
106 | } | 110 | } |
107 | 111 | ||
108 | tot->rx_errors = dev->stats.rx_errors; | 112 | tot->rx_errors = dev->stats.rx_errors; |
113 | tot->rx_frame_errors = dev->stats.rx_frame_errors; | ||
109 | tot->tx_fifo_errors = dev->stats.tx_fifo_errors; | 114 | tot->tx_fifo_errors = dev->stats.tx_fifo_errors; |
110 | tot->tx_carrier_errors = dev->stats.tx_carrier_errors; | 115 | tot->tx_carrier_errors = dev->stats.tx_carrier_errors; |
111 | tot->tx_dropped = dev->stats.tx_dropped; | 116 | tot->tx_dropped = dev->stats.tx_dropped; |
@@ -585,16 +590,11 @@ out: | |||
585 | return err; | 590 | return err; |
586 | } | 591 | } |
587 | 592 | ||
588 | static inline void ipip6_ecn_decapsulate(const struct iphdr *iph, struct sk_buff *skb) | ||
589 | { | ||
590 | if (INET_ECN_is_ce(iph->tos)) | ||
591 | IP6_ECN_set_ce(ipv6_hdr(skb)); | ||
592 | } | ||
593 | |||
594 | static int ipip6_rcv(struct sk_buff *skb) | 593 | static int ipip6_rcv(struct sk_buff *skb) |
595 | { | 594 | { |
596 | const struct iphdr *iph; | 595 | const struct iphdr *iph; |
597 | struct ip_tunnel *tunnel; | 596 | struct ip_tunnel *tunnel; |
597 | int err; | ||
598 | 598 | ||
599 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 599 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
600 | goto out; | 600 | goto out; |
@@ -616,18 +616,27 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
616 | if ((tunnel->dev->priv_flags & IFF_ISATAP) && | 616 | if ((tunnel->dev->priv_flags & IFF_ISATAP) && |
617 | !isatap_chksrc(skb, iph, tunnel)) { | 617 | !isatap_chksrc(skb, iph, tunnel)) { |
618 | tunnel->dev->stats.rx_errors++; | 618 | tunnel->dev->stats.rx_errors++; |
619 | kfree_skb(skb); | 619 | goto out; |
620 | return 0; | 620 | } |
621 | |||
622 | __skb_tunnel_rx(skb, tunnel->dev); | ||
623 | |||
624 | err = IP_ECN_decapsulate(iph, skb); | ||
625 | if (unlikely(err)) { | ||
626 | if (log_ecn_error) | ||
627 | net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n", | ||
628 | &iph->saddr, iph->tos); | ||
629 | if (err > 1) { | ||
630 | ++tunnel->dev->stats.rx_frame_errors; | ||
631 | ++tunnel->dev->stats.rx_errors; | ||
632 | goto out; | ||
633 | } | ||
621 | } | 634 | } |
622 | 635 | ||
623 | tstats = this_cpu_ptr(tunnel->dev->tstats); | 636 | tstats = this_cpu_ptr(tunnel->dev->tstats); |
624 | tstats->rx_packets++; | 637 | tstats->rx_packets++; |
625 | tstats->rx_bytes += skb->len; | 638 | tstats->rx_bytes += skb->len; |
626 | 639 | ||
627 | __skb_tunnel_rx(skb, tunnel->dev); | ||
628 | |||
629 | ipip6_ecn_decapsulate(iph, skb); | ||
630 | |||
631 | netif_rx(skb); | 640 | netif_rx(skb); |
632 | 641 | ||
633 | return 0; | 642 | return 0; |