Merge tag 'v3.10.70' into update
authorStricted <info@stricted.net>
Wed, 21 Mar 2018 21:40:47 +0000 (22:40 +0100)
committerStricted <info@stricted.net>
Wed, 21 Mar 2018 21:40:47 +0000 (22:40 +0100)
This is the 3.10.70 stable release

1  2 
Makefile
include/net/ip.h
include/net/netns/ipv4.h
net/core/dev.c
net/core/rtnetlink.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/route.c
net/ipv4/tcp_ipv4.c
net/ipv6/datagram.c
net/ipv6/route.c

diff --combined Makefile
index b1245c2560e89ec29696a3093af74a2f47abb19d,402cbb7c27f17046523626ffd7b10e930d4cb4c4..2a4bac8516ebd5917544caf96ad2e92524280053
+++ b/Makefile
@@@ -1,6 -1,6 +1,6 @@@
  VERSION = 3
  PATCHLEVEL = 10
- SUBLEVEL = 69
+ SUBLEVEL = 70
  EXTRAVERSION =
  NAME = TOSSUG Baby Fish
  
@@@ -373,9 -373,7 +373,9 @@@ KBUILD_CFLAGS   := -Wall -Wundef -Wstri
                   -fno-strict-aliasing -fno-common \
                   -Werror-implicit-function-declaration \
                   -Wno-format-security \
 -                 -fno-delete-null-pointer-checks
 +                 -fno-delete-null-pointer-checks \
 +                 -w
 +
  KBUILD_AFLAGS_KERNEL :=
  KBUILD_CFLAGS_KERNEL :=
  KBUILD_AFLAGS   := -D__ASSEMBLY__
diff --combined include/net/ip.h
index 1f6794b2cac219a56a1416f8ac66c1dea3e8c3bf,0a62365149e2b3cf716882deb4aafdd413ac48da..fc62ae0a47d2932393d4ebf98bd2d3c9ffba6356
@@@ -37,11 -37,12 +37,12 @@@ struct inet_skb_parm 
        struct ip_options       opt;            /* Compiled IP options          */
        unsigned char           flags;
  
- #define IPSKB_FORWARDED               1
- #define IPSKB_XFRM_TUNNEL_SIZE        2
- #define IPSKB_XFRM_TRANSFORMED        4
- #define IPSKB_FRAG_COMPLETE   8
- #define IPSKB_REROUTED                16
+ #define IPSKB_FORWARDED               BIT(0)
+ #define IPSKB_XFRM_TUNNEL_SIZE        BIT(1)
+ #define IPSKB_XFRM_TRANSFORMED        BIT(2)
+ #define IPSKB_FRAG_COMPLETE   BIT(3)
+ #define IPSKB_REROUTED                BIT(4)
+ #define IPSKB_DOREDIRECT      BIT(5)
  
        u16                     frag_max_size;
  };
@@@ -153,7 -154,6 +154,7 @@@ struct ip_reply_arg 
                                /* -1 if not needed */ 
        int         bound_dev_if;
        u8          tos;
 +      kuid_t      uid;
  }; 
  
  #define IP_REPLY_ARG_NOSRCCHECK 1
@@@ -163,7 -163,7 +164,7 @@@ static inline __u8 ip_reply_arg_flowi_f
        return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0;
  }
  
- void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
+ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr,
                           __be32 saddr, const struct ip_reply_arg *arg,
                           unsigned int len);
  
@@@ -226,9 -226,6 +227,9 @@@ extern void ipfrag_init(void)
  
  extern void ip_static_sysctl_init(void);
  
 +#define IP4_REPLY_MARK(net, mark) \
 +      ((net)->ipv4.sysctl_fwmark_reflect ? (mark) : 0)
 +
  static inline bool ip_is_fragment(const struct iphdr *iph)
  {
        return (iph->frag_off & htons(IP_MF | IP_OFFSET)) != 0;
diff --combined include/net/netns/ipv4.h
index 0dd6f0b3eadb96119658697e949e50334dcd9434,03e6378d53535bdfb2bf377f274ede41027554aa..4f6c72095cf6c125fddcdd41e868f1e3ef1f5a64
@@@ -43,6 -43,7 +43,7 @@@ struct netns_ipv4 
        struct inet_peer_base   *peers;
        struct tcpm_hash_bucket *tcp_metrics_hash;
        unsigned int            tcp_metrics_hash_log;
+       struct sock  * __percpu *tcp_sk;
        struct netns_frags      frags;
  #ifdef CONFIG_NETFILTER
        struct xt_table         *iptable_filter;
@@@ -64,9 -65,6 +65,9 @@@
  
        int sysctl_tcp_ecn;
  
 +      int sysctl_fwmark_reflect;
 +      int sysctl_tcp_fwmark_accept;
 +
        kgid_t sysctl_ping_group_range[2];
        long sysctl_tcp_mem[3];
  
diff --combined net/core/dev.c
index 5f7f3a026062504a52563008649cee4b57899de8,c310440309bb6ec5c833b704e4d1d413f8b8cb51..a2b10bf466be4c88ca7c51491ff39b8a4188cd9a
  #include <linux/inetdevice.h>
  #include <linux/cpu_rmap.h>
  #include <linux/static_key.h>
 -
 +#include <net/udp.h>
  #include "net-sysfs.h"
  
 +#ifdef UDP_SKT_WIFI
 +#include <linux/ftrace_event.h>
 +#endif
 +
  /* Instead of increasing this, you should create a hash table. */
  #define MAX_GRO_SKBS 8
  
@@@ -2682,7 -2678,6 +2682,7 @@@ static inline int __dev_xmit_skb(struc
  
        spin_lock(root_lock);
        if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) {
 +              printk(KERN_WARNING "[mtk_net]__dev_xmit_skb drop skb_len = %d \n", skb->len);
                kfree_skb(skb);
                rc = NET_XMIT_DROP;
        } else if ((q->flags & TCQ_F_CAN_BYPASS) && !qdisc_qlen(q) &&
@@@ -2794,22 -2789,6 +2794,22 @@@ int dev_queue_xmit(struct sk_buff *skb
  
        skb_reset_mac_header(skb);
  
 +#ifdef UDP_SKT_WIFI
 +      
 +      if (unlikely((sysctl_met_is_enable == 1) && (sysctl_udp_met_port > 0)
 +               && (ip_hdr(skb)->protocol == IPPROTO_UDP) && skb->sk)) {
 +              
 +          if (sysctl_udp_met_port == ntohs((inet_sk(skb->sk))->inet_sport)) {
 +              struct udphdr * udp_iphdr = udp_hdr(skb);
 +              if (udp_iphdr && (ntohs(udp_iphdr->len) >= 12)) {
 +                __u16 * seq_id = (__u16 *)((char *)udp_iphdr + 10);
 +                  udp_event_trace_printk("F|%d|%s|%d\n", current->pid, *seq_id);
 +                  
 +              }
 +          }
 +      }
 +#endif
 +
        /* Disable soft irqs for various locks below. Also
         * stops preemption for RCU.
         */
@@@ -6036,10 -6015,20 +6036,20 @@@ static int dev_cpu_callback(struct noti
                oldsd->output_queue = NULL;
                oldsd->output_queue_tailp = &oldsd->output_queue;
        }
-       /* Append NAPI poll list from offline CPU. */
-       if (!list_empty(&oldsd->poll_list)) {
-               list_splice_init(&oldsd->poll_list, &sd->poll_list);
-               raise_softirq_irqoff(NET_RX_SOFTIRQ);
+       /* Append NAPI poll list from offline CPU, with one exception :
+        * process_backlog() must be called by cpu owning percpu backlog.
+        * We properly handle process_queue & input_pkt_queue later.
+        */
+       while (!list_empty(&oldsd->poll_list)) {
+               struct napi_struct *napi = list_first_entry(&oldsd->poll_list,
+                                                           struct napi_struct,
+                                                           poll_list);
+               list_del_init(&napi->poll_list);
+               if (napi->poll == process_backlog)
+                       napi->state = 0;
+               else
+                       ____napi_schedule(sd, napi);
        }
  
        raise_softirq_irqoff(NET_TX_SOFTIRQ);
                netif_rx(skb);
                input_queue_head_incr(oldsd);
        }
-       while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) {
+       while ((skb = skb_dequeue(&oldsd->input_pkt_queue))) {
                netif_rx(skb);
                input_queue_head_incr(oldsd);
        }
diff --combined net/core/rtnetlink.c
index 9fd4f8cdf39c62c2c9d844f6fbb461ff7872cb0a,279b5dcf09ae390e239ea363fbaf34c95c2dff03..1b068448d0ea9e63f04f6b634d244971bb15c406
@@@ -54,8 -54,6 +54,8 @@@
  #include <net/rtnetlink.h>
  #include <net/net_namespace.h>
  
 +#include <linux/xlog.h>
 +
  struct rtnl_link {
        rtnl_doit_func          doit;
        rtnl_dumpit_func        dumpit;
@@@ -66,22 -64,13 +66,22 @@@ static DEFINE_MUTEX(rtnl_mutex)
  
  void rtnl_lock(void)
  {
 +      #ifdef CONFIG_MTK_NET_LOGGING  
 +      printk(KERN_DEBUG "[mtk_net][rtnl_lock]rtnl_lock++\n");
 +      #endif
        mutex_lock(&rtnl_mutex);
 +      #ifdef CONFIG_MTK_NET_LOGGING  
 +      printk(KERN_DEBUG "[mtk_net][rtnl_lock]rtnl_lock--\n");
 +      #endif
  }
  EXPORT_SYMBOL(rtnl_lock);
  
  void __rtnl_unlock(void)
  {
        mutex_unlock(&rtnl_mutex);
 +      #ifdef CONFIG_MTK_NET_LOGGING  
 +      printk(KERN_DEBUG "[mtk_net][rtnl_lock]rtnl_unlock done\n");
 +      #endif
  }
  
  void rtnl_unlock(void)
@@@ -1988,10 -1977,7 +1988,10 @@@ void rtmsg_ifinfo(int type, struct net_
        struct sk_buff *skb;
        int err = -ENOBUFS;
        size_t if_info_size;
 -
 +      #ifdef CONFIG_MTK_NET_LOGGING  
 +    printk(KERN_INFO "[mtk_net][rtnetlink]rtmsg_ifinfo type:%d, dev:%s, change:%u, pid = %d", 
 +              type, dev->name, change, current->pid);
 +    #endif
        skb = nlmsg_new((if_info_size = if_nlmsg_size(dev, 0)), GFP_KERNEL);
        if (skb == NULL)
                goto errout;
@@@ -2491,12 -2477,16 +2491,16 @@@ static int rtnl_bridge_notify(struct ne
                        goto errout;
        }
  
+       if (!skb->len)
+               goto errout;
        rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
        return 0;
  errout:
        WARN_ON(err == -EMSGSIZE);
        kfree_skb(skb);
-       rtnl_set_sk_err(net, RTNLGRP_LINK, err);
+       if (err)
+               rtnl_set_sk_err(net, RTNLGRP_LINK, err);
        return err;
  }
  
diff --combined net/ipv4/ip_output.c
index 1bb117130e3ed599f319a6b986295d97fafcfbf7,def18547748ec087cb16d05fb9a72c7e0730e104..3ffc57f7afb6d42f350251a837735cbfbd2f59ca
@@@ -1454,23 -1454,8 +1454,8 @@@ static int ip_reply_glue_bits(void *dpt
  /*
   *    Generic function to send a packet as reply to another packet.
   *    Used to send some TCP resets/acks so far.
-  *
-  *    Use a fake percpu inet socket to avoid false sharing and contention.
   */
- static DEFINE_PER_CPU(struct inet_sock, unicast_sock) = {
-       .sk = {
-               .__sk_common = {
-                       .skc_refcnt = ATOMIC_INIT(1),
-               },
-               .sk_wmem_alloc  = ATOMIC_INIT(1),
-               .sk_allocation  = GFP_ATOMIC,
-               .sk_flags       = (1UL << SOCK_USE_WRITE_QUEUE),
-       },
-       .pmtudisc       = IP_PMTUDISC_WANT,
-       .uc_ttl         = -1,
- };
- void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
+ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr,
                           __be32 saddr, const struct ip_reply_arg *arg,
                           unsigned int len)
  {
        struct ipcm_cookie ipc;
        struct flowi4 fl4;
        struct rtable *rt = skb_rtable(skb);
+       struct net *net = sock_net(sk);
        struct sk_buff *nskb;
-       struct sock *sk;
-       struct inet_sock *inet;
        int err;
  
        if (ip_options_echo(&replyopts.opt.opt, skb))
                        daddr = replyopts.opt.opt.faddr;
        }
  
 -      flowi4_init_output(&fl4, arg->bound_dev_if, 0,
 +      flowi4_init_output(&fl4, arg->bound_dev_if,
 +                         IP4_REPLY_MARK(net, skb->mark),
                           RT_TOS(arg->tos),
                           RT_SCOPE_UNIVERSE, ip_hdr(skb)->protocol,
                           ip_reply_arg_flowi_flags(arg),
                           daddr, saddr,
 -                         tcp_hdr(skb)->source, tcp_hdr(skb)->dest);
 +                         tcp_hdr(skb)->source, tcp_hdr(skb)->dest,
 +                         arg->uid);
        security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
        rt = ip_route_output_key(net, &fl4);
        if (IS_ERR(rt))
                return;
  
-       inet = &get_cpu_var(unicast_sock);
+       inet_sk(sk)->tos = arg->tos;
  
-       inet->tos = arg->tos;
-       sk = &inet->sk;
        sk->sk_priority = skb->priority;
        sk->sk_protocol = ip_hdr(skb)->protocol;
        sk->sk_bound_dev_if = arg->bound_dev_if;
-       sock_net_set(sk, net);
-       __skb_queue_head_init(&sk->sk_write_queue);
        sk->sk_sndbuf = sysctl_wmem_default;
        err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base,
                             len, 0, &ipc, &rt, MSG_DONTWAIT);
                          arg->csumoffset) = csum_fold(csum_add(nskb->csum,
                                                                arg->csum));
                nskb->ip_summed = CHECKSUM_NONE;
-               skb_orphan(nskb);
                skb_set_queue_mapping(nskb, skb_get_queue_mapping(skb));
                ip_push_pending_frames(sk, &fl4);
        }
  out:
-       put_cpu_var(unicast_sock);
        ip_rt_put(rt);
  }
  
diff --combined net/ipv4/ip_sockglue.c
index 1c688f7403f709f35b8b96e9393d34c9df51eaa5,f6603142cb33c7c2e211414c4f193835297f9fe5..a2ef76c45cd395e973ec4c17cd9c3bddadc956f1
@@@ -410,15 -410,11 +410,11 @@@ int ip_recv_error(struct sock *sk, stru
  
        memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
        sin = &errhdr.offender;
-       sin->sin_family = AF_UNSPEC;
+       memset(sin, 0, sizeof(*sin));
        if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP) {
-               struct inet_sock *inet = inet_sk(sk);
                sin->sin_family = AF_INET;
                sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
-               sin->sin_port = 0;
-               memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
-               if (inet->cmsg_flags)
+               if (inet_sk(sk)->cmsg_flags)
                        ip_cmsg_recv(msg, skb);
        }
  
@@@ -1046,13 -1042,6 +1042,13 @@@ void ipv4_pktinfo_prepare(struct sk_buf
                pktinfo->ipi_ifindex = 0;
                pktinfo->ipi_spec_dst.s_addr = 0;
        }
 +      /* We need to keep the dst for __ip_options_echo()
 +       * We could restrict the test to opt.ts_needtime || opt.srr,
 +       * but the following is good enough as IP options are not often used.
 +       */
 +      if (unlikely(IPCB(skb)->opt.optlen))
 +              skb_dst_force(skb);
 +      else
        skb_dst_drop(skb);
  }
  
diff --combined net/ipv4/route.c
index 271732355ee98538ec40e96f8f4962b93c65c4b8,e23c5f64286b6c1611b5b7ebd5126b5064e2ce94..577801102a70c799156a4614e942d7a1d071876b
@@@ -515,7 -515,7 +515,7 @@@ void __ip_select_ident(struct iphdr *ip
  }
  EXPORT_SYMBOL(__ip_select_ident);
  
 -static void __build_flow_key(struct flowi4 *fl4, const struct sock *sk,
 +static void __build_flow_key(struct flowi4 *fl4, struct sock *sk,
                             const struct iphdr *iph,
                             int oif, u8 tos,
                             u8 prot, u32 mark, int flow_flags)
        flowi4_init_output(fl4, oif, mark, tos,
                           RT_SCOPE_UNIVERSE, prot,
                           flow_flags,
 -                         iph->daddr, iph->saddr, 0, 0);
 +                         iph->daddr, iph->saddr, 0, 0,
 +                         sk ? sock_i_uid(sk) : 0);
  }
  
  static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb,
 -                             const struct sock *sk)
 +                             struct sock *sk)
  {
        const struct iphdr *iph = ip_hdr(skb);
        int oif = skb->dev->ifindex;
        __build_flow_key(fl4, sk, iph, oif, tos, prot, mark, 0);
  }
  
 -static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
 +static void build_sk_flow_key(struct flowi4 *fl4, struct sock *sk)
  {
        const struct inet_sock *inet = inet_sk(sk);
        const struct ip_options_rcu *inet_opt;
                           RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
                           inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
                           inet_sk_flowi_flags(sk),
 -                         daddr, inet->inet_saddr, 0, 0);
 +                         daddr, inet->inet_saddr, 0, 0,
 +                         sock_i_uid(sk));
        rcu_read_unlock();
  }
  
 -static void ip_rt_build_flow_key(struct flowi4 *fl4, const struct sock *sk,
 +static void ip_rt_build_flow_key(struct flowi4 *fl4, struct sock *sk,
                                 const struct sk_buff *skb)
  {
        if (skb)
@@@ -973,9 -971,6 +973,9 @@@ void ipv4_update_pmtu(struct sk_buff *s
        struct flowi4 fl4;
        struct rtable *rt;
  
 +      if (!mark)
 +              mark = IP4_REPLY_MARK(net, skb->mark);
 +
        __build_flow_key(&fl4, NULL, iph, oif,
                         RT_TOS(iph->tos), protocol, mark, flow_flags);
        rt = __ip_route_output_key(net, &fl4);
@@@ -993,10 -988,6 +993,10 @@@ static void __ipv4_sk_update_pmtu(struc
        struct rtable *rt;
  
        __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
 +
 +      if (!fl4.flowi4_mark)
 +              fl4.flowi4_mark = IP4_REPLY_MARK(sock_net(sk), skb->mark);
 +
        rt = __ip_route_output_key(sock_net(sk), &fl4);
        if (!IS_ERR(rt)) {
                __ip_rt_update_pmtu(rt, &fl4, mtu);
@@@ -1523,11 -1514,10 +1523,10 @@@ static int __mkroute_input(struct sk_bu
  
        do_cache = res->fi && !itag;
        if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) &&
+           skb->protocol == htons(ETH_P_IP) &&
            (IN_DEV_SHARED_MEDIA(out_dev) ||
-            inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) {
-               flags |= RTCF_DOREDIRECT;
-               do_cache = false;
-       }
+            inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res))))
+               IPCB(skb)->flags |= IPSKB_DOREDIRECT;
  
        if (skb->protocol != htons(ETH_P_IP)) {
                /* Not IP (i.e. ARP). Do not create route, if it is
@@@ -2264,6 -2254,8 +2263,8 @@@ static int rt_fill_info(struct net *net
        r->rtm_flags    = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED;
        if (rt->rt_flags & RTCF_NOTIFY)
                r->rtm_flags |= RTM_F_NOTIFY;
+       if (IPCB(skb)->flags & IPSKB_DOREDIRECT)
+               r->rtm_flags |= RTCF_DOREDIRECT;
  
        if (nla_put_be32(skb, RTA_DST, dst))
                goto nla_put_failure;
            nla_put_u32(skb, RTA_MARK, fl4->flowi4_mark))
                goto nla_put_failure;
  
 +      if (!uid_eq(fl4->flowi4_uid, INVALID_UID) &&
 +          nla_put_u32(skb, RTA_UID,
 +                      from_kuid_munged(current_user_ns(), fl4->flowi4_uid)))
 +              goto nla_put_failure;
 +
        error = rt->dst.error;
  
        if (rt_is_input_route(rt)) {
@@@ -2363,7 -2350,6 +2364,7 @@@ static int inet_rtm_getroute(struct sk_
        int err;
        int mark;
        struct sk_buff *skb;
 +      kuid_t uid;
  
        err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy);
        if (err < 0)
        dst = tb[RTA_DST] ? nla_get_be32(tb[RTA_DST]) : 0;
        iif = tb[RTA_IIF] ? nla_get_u32(tb[RTA_IIF]) : 0;
        mark = tb[RTA_MARK] ? nla_get_u32(tb[RTA_MARK]) : 0;
 +      if (tb[RTA_UID])
 +              uid = make_kuid(current_user_ns(), nla_get_u32(tb[RTA_UID]));
 +      else
 +              uid = (iif ? INVALID_UID : current_uid());
  
        memset(&fl4, 0, sizeof(fl4));
        fl4.daddr = dst;
        fl4.flowi4_tos = rtm->rtm_tos;
        fl4.flowi4_oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0;
        fl4.flowi4_mark = mark;
 +      fl4.flowi4_uid = uid;
  
        if (iif) {
                struct net_device *dev;
diff --combined net/ipv4/tcp_ipv4.c
index 35c01585cdeb2d0cb30986166b32168e079d7f5b,cce35e5a7ee693e074716dc9bef8ad89c96fbb03..7edf30cdda202876c0c1e3a352a4a84c9674bdbd
@@@ -233,7 -233,7 +233,7 @@@ int tcp_v4_connect(struct sock *sk, str
        /* OK, now commit destination to socket.  */
        sk->sk_gso_type = SKB_GSO_TCPV4;
        sk_setup_caps(sk, &rt->dst);
 -
 +        printk(KERN_INFO "[socket_conn]IPV4 socket[%lu] sport:%u \n", SOCK_INODE(sk->sk_socket)->i_ino, ntohs(inet->inet_sport));
        if (!tp->write_seq && likely(!tp->repair))
                tp->write_seq = secure_tcp_sequence_number(inet->inet_saddr,
                                                           inet->inet_daddr,
@@@ -446,7 -446,7 +446,7 @@@ void tcp_v4_err(struct sk_buff *icmp_sk
  
                if (remaining) {
                        inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
 -                                                remaining, TCP_RTO_MAX);
 +                                                remaining, sysctl_tcp_rto_max);
                } else {
                        /* RTO revert clocked out retransmission.
                         * Will retransmit now */
@@@ -707,7 -707,8 +707,8 @@@ static void tcp_v4_send_reset(struct so
  
        net = dev_net(skb_dst(skb)->dev);
        arg.tos = ip_hdr(skb)->tos;
-       ip_send_unicast_reply(net, skb, ip_hdr(skb)->saddr,
+       ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
+                             skb, ip_hdr(skb)->saddr,
                              ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len);
  
        TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
@@@ -790,7 -791,8 +791,8 @@@ static void tcp_v4_send_ack(struct sk_b
        if (oif)
                arg.bound_dev_if = oif;
        arg.tos = tos;
-       ip_send_unicast_reply(net, skb, ip_hdr(skb)->saddr,
+       ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
+                             skb, ip_hdr(skb)->saddr,
                              ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len);
  
        TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
@@@ -1424,7 -1426,7 +1426,7 @@@ static int tcp_v4_conn_req_fastopen(str
         * because it's been added to the accept queue directly.
         */
        inet_csk_reset_xmit_timer(child, ICSK_TIME_RETRANS,
 -          TCP_TIMEOUT_INIT, TCP_RTO_MAX);
 +          TCP_TIMEOUT_INIT, sysctl_tcp_rto_max);
  
        /* Add the child socket directly into the accept queue */
        inet_csk_reqsk_queue_add(sk, req, child);
@@@ -1528,7 -1530,6 +1530,7 @@@ int tcp_v4_conn_request(struct sock *sk
        ireq->rmt_addr = saddr;
        ireq->no_srccheck = inet_sk(sk)->transparent;
        ireq->opt = tcp_v4_save_options(skb);
 +      ireq->ir_mark = inet_request_mark(sk, skb);
  
        if (security_inet_conn_request(sk, skb, req))
                goto drop_and_free;
@@@ -1950,7 -1951,7 +1952,7 @@@ bool tcp_prequeue(struct sock *sk, stru
                if (!inet_csk_ack_scheduled(sk))
                        inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
                                                  (3 * tcp_rto_min(sk)) / 4,
 -                                                TCP_RTO_MAX);
 +                                                sysctl_tcp_rto_max);
        }
        return true;
  }
@@@ -2164,7 -2165,6 +2166,7 @@@ static int tcp_v4_init_sock(struct soc
        struct inet_connection_sock *icsk = inet_csk(sk);
  
        tcp_init_sock(sk);
 +        icsk->icsk_MMSRB = 0;
  
        icsk->icsk_af_ops = &ipv4_specific;
  
@@@ -2220,115 -2220,6 +2222,115 @@@ void tcp_v4_destroy_sock(struct sock *s
  }
  EXPORT_SYMBOL(tcp_v4_destroy_sock);
  
 +void tcp_v4_handle_retrans_time_by_uid(struct uid_err uid_e)
 +{
 +    unsigned int bucket;
 +    uid_t skuid = (uid_t)(uid_e.appuid);
 +      struct inet_connection_sock *icsk = NULL;//inet_csk(sk);
 +
 +
 +    for (bucket = 0; bucket < tcp_hashinfo.ehash_mask; bucket++) {
 +        struct hlist_nulls_node *node;
 +        struct sock *sk;
 +        spinlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, bucket);
 +    
 +        spin_lock_bh(lock);
 +        sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[bucket].chain) {
 +    
 +            if (sysctl_ip_dynaddr && sk->sk_state == TCP_SYN_SENT)
 +                continue;
 +            if (sock_flag(sk, SOCK_DEAD))
 +                continue;
 +    
 +            if(sk->sk_socket){
 +                if(SOCK_INODE(sk->sk_socket)->i_uid != skuid)
 +                    continue;
 +                else
 +                    printk("[mmspb] tcp_v4_handle_retrans_time_by_uid socket uid(%d) match!",
 +                        SOCK_INODE(sk->sk_socket)->i_uid);
 +            } else{
 +                continue;
 +          }
 +
 +                sock_hold(sk);
 +                spin_unlock_bh(lock);
 +    
 +                local_bh_disable();
 +                bh_lock_sock(sk);
 +
 +                // update sk time out value
 +              icsk = inet_csk(sk);
 +              printk("[mmspb] tcp_v4_handle_retrans_time_by_uid update timer\n");
 +                                      
 +              sk_reset_timer(sk, &icsk->icsk_retransmit_timer, jiffies + 2);
 +              icsk->icsk_rto = sysctl_tcp_rto_min * 30;       
 +              icsk->icsk_MMSRB = 1;
 +                              
 +                bh_unlock_sock(sk);
 +                local_bh_enable();
 +              spin_lock_bh(lock);
 +                sock_put(sk);
 +
 +            }
 +            spin_unlock_bh(lock);
 +        }
 +
 +}
 +
 +
 +/*
 + * tcp_v4_nuke_addr_by_uid - destroy all sockets of spcial uid
 + */
 +void tcp_v4_reset_connections_by_uid(struct uid_err uid_e)
 +{
 +    unsigned int bucket;
 +    uid_t skuid = (uid_t)(uid_e.appuid);
 +
 +    for (bucket = 0; bucket < tcp_hashinfo.ehash_mask; bucket++) {
 +        struct hlist_nulls_node *node;
 +        struct sock *sk;
 +        spinlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, bucket);
 +    
 +restart:
 +        spin_lock_bh(lock);
 +        sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[bucket].chain) {
 +    
 +            if (sysctl_ip_dynaddr && sk->sk_state == TCP_SYN_SENT)
 +                continue;
 +            if (sock_flag(sk, SOCK_DEAD))
 +                continue;
 +    
 +            if(sk->sk_socket){
 +                if(SOCK_INODE(sk->sk_socket)->i_uid != skuid)
 +                    continue;
 +                else
 +                    printk(KERN_INFO "SIOCKILLSOCK socket uid(%d) match!",
 +                        SOCK_INODE(sk->sk_socket)->i_uid);
 +            } else{
 +                continue;
 +          }
 +
 +                sock_hold(sk);
 +                spin_unlock_bh(lock);
 +    
 +                local_bh_disable();
 +                bh_lock_sock(sk);
 +                sk->sk_err = uid_e.errNum;
 +                printk(KERN_INFO "SIOCKILLSOCK set sk err == %d!! \n", sk->sk_err);
 +                sk->sk_error_report(sk);
 +    
 +                tcp_done(sk);
 +                bh_unlock_sock(sk);
 +                local_bh_enable();
 +                sock_put(sk);
 +
 +                goto restart;
 +            }
 +            spin_unlock_bh(lock);
 +        }
 +}
 +
 +
  #ifdef CONFIG_PROC_FS
  /* Proc filesystem TCP sock list dumping. */
  
@@@ -3009,14 -2900,39 +3011,39 @@@ struct proto tcp_prot = 
  };
  EXPORT_SYMBOL(tcp_prot);
  
+ static void __net_exit tcp_sk_exit(struct net *net)
+ {
+       int cpu;
+       for_each_possible_cpu(cpu)
+               inet_ctl_sock_destroy(*per_cpu_ptr(net->ipv4.tcp_sk, cpu));
+       free_percpu(net->ipv4.tcp_sk);
+ }
  static int __net_init tcp_sk_init(struct net *net)
  {
+       int res, cpu;
+       net->ipv4.tcp_sk = alloc_percpu(struct sock *);
+       if (!net->ipv4.tcp_sk)
+               return -ENOMEM;
+       for_each_possible_cpu(cpu) {
+               struct sock *sk;
+               res = inet_ctl_sock_create(&sk, PF_INET, SOCK_RAW,
+                                          IPPROTO_TCP, net);
+               if (res)
+                       goto fail;
+               *per_cpu_ptr(net->ipv4.tcp_sk, cpu) = sk;
+       }
        net->ipv4.sysctl_tcp_ecn = 2;
        return 0;
- }
  
- static void __net_exit tcp_sk_exit(struct net *net)
- {
+ fail:
+       tcp_sk_exit(net);
+       return res;
  }
  
  static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list)
diff --combined net/ipv6/datagram.c
index 41a353bbfa286c8b0354d39a6936cdde14cf6f08,ce17d3da9b2bcd41c44318b663d3fe0e5078f933..5a2c0de79f1f92fefcdd16d8afdb208171c1f815
@@@ -162,7 -162,6 +162,7 @@@ ipv4_connected
        fl6.flowi6_mark = sk->sk_mark;
        fl6.fl6_dport = inet->inet_dport;
        fl6.fl6_sport = inet->inet_sport;
 +      fl6.flowi6_uid = sock_i_uid(sk);
  
        if (!fl6.flowi6_oif && (addr_type&IPV6_ADDR_MULTICAST))
                fl6.flowi6_oif = np->mcast_oif;
@@@ -375,11 -374,10 +375,10 @@@ int ipv6_recv_error(struct sock *sk, st
  
        memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
        sin = &errhdr.offender;
-       sin->sin6_family = AF_UNSPEC;
+       memset(sin, 0, sizeof(*sin));
        if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) {
                sin->sin6_family = AF_INET6;
-               sin->sin6_flowinfo = 0;
-               sin->sin6_port = 0;
                if (skb->protocol == htons(ETH_P_IPV6)) {
                        sin->sin6_addr = ipv6_hdr(skb)->saddr;
                        if (np->rxopt.all)
                                ipv6_iface_scope_id(&sin->sin6_addr,
                                                    IP6CB(skb)->iif);
                } else {
-                       struct inet_sock *inet = inet_sk(sk);
                        ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr,
                                               &sin->sin6_addr);
-                       sin->sin6_scope_id = 0;
-                       if (inet->cmsg_flags)
+                       if (inet_sk(sk)->cmsg_flags)
                                ip_cmsg_recv(msg, skb);
                }
        }
@@@ -884,30 -879,3 +880,30 @@@ exit_f
        return err;
  }
  EXPORT_SYMBOL_GPL(ip6_datagram_send_ctl);
 +
 +void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
 +                           __u16 srcp, __u16 destp, int bucket)
 +{
 +      struct ipv6_pinfo *np = inet6_sk(sp);
 +      const struct in6_addr *dest, *src;
 +
 +      dest  = &np->daddr;
 +      src   = &np->rcv_saddr;
 +      seq_printf(seq,
 +                 "%5d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
 +                 "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d\n",
 +                 bucket,
 +                 src->s6_addr32[0], src->s6_addr32[1],
 +                 src->s6_addr32[2], src->s6_addr32[3], srcp,
 +                 dest->s6_addr32[0], dest->s6_addr32[1],
 +                 dest->s6_addr32[2], dest->s6_addr32[3], destp,
 +                 sp->sk_state,
 +                 sk_wmem_alloc_get(sp),
 +                 sk_rmem_alloc_get(sp),
 +                 0, 0L, 0,
 +                 from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
 +                 0,
 +                 sock_i_ino(sp),
 +                 atomic_read(&sp->sk_refcnt), sp,
 +                 atomic_read(&sp->sk_drops));
 +}
diff --combined net/ipv6/route.c
index 03b1e6fde278509719cdde2a993ef80f7e598ca1,92274796eb71fb341fab1d646eec1483d1106f96..ee84a3a3b69deadb0532043e5537a66b7e0e0057
@@@ -93,12 -93,13 +93,12 @@@ static void                rt6_do_redirect(struct dst
                                        struct sk_buff *skb);
  
  #ifdef CONFIG_IPV6_ROUTE_INFO
 -static struct rt6_info *rt6_add_route_info(struct net *net,
 +static struct rt6_info *rt6_add_route_info(struct net_device *dev,
                                           const struct in6_addr *prefix, int prefixlen,
 -                                         const struct in6_addr *gwaddr, int ifindex,
 -                                         unsigned int pref);
 -static struct rt6_info *rt6_get_route_info(struct net *net,
 +                                         const struct in6_addr *gwaddr, unsigned int pref);
 +static struct rt6_info *rt6_get_route_info(struct net_device *dev,
                                           const struct in6_addr *prefix, int prefixlen,
 -                                         const struct in6_addr *gwaddr, int ifindex);
 +                                         const struct in6_addr *gwaddr);
  #endif
  
  static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
@@@ -684,6 -685,7 +684,6 @@@ static struct rt6_info *rt6_select(stru
  int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
                  const struct in6_addr *gwaddr)
  {
 -      struct net *net = dev_net(dev);
        struct route_info *rinfo = (struct route_info *) opt;
        struct in6_addr prefix_buf, *prefix;
        unsigned int pref;
        if (rinfo->prefix_len == 0)
                rt = rt6_get_dflt_router(gwaddr, dev);
        else
 -              rt = rt6_get_route_info(net, prefix, rinfo->prefix_len,
 -                                      gwaddr, dev->ifindex);
 +              rt = rt6_get_route_info(dev, prefix, rinfo->prefix_len, gwaddr);
  
        if (rt && !lifetime) {
                ip6_del_rt(rt);
        }
  
        if (!rt && lifetime)
 -              rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr, dev->ifindex,
 -                                      pref);
 +              rt = rt6_add_route_info(dev, prefix, rinfo->prefix_len, gwaddr, pref);
        else if (rt)
                rt->rt6i_flags = RTF_ROUTEINFO |
                                 (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
@@@ -1137,19 -1141,16 +1137,16 @@@ static void ip6_rt_update_pmtu(struct d
                struct net *net = dev_net(dst->dev);
  
                rt6->rt6i_flags |= RTF_MODIFIED;
-               if (mtu < IPV6_MIN_MTU) {
-                       u32 features = dst_metric(dst, RTAX_FEATURES);
+               if (mtu < IPV6_MIN_MTU)
                        mtu = IPV6_MIN_MTU;
-                       features |= RTAX_FEATURE_ALLFRAG;
-                       dst_metric_set(dst, RTAX_FEATURES, features);
-               }
                dst_metric_set(dst, RTAX_MTU, mtu);
                rt6_update_expires(rt6, net->ipv6.sysctl.ip6_rt_mtu_expires);
        }
  }
  
  void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
 -                   int oif, u32 mark)
 +                   int oif, u32 mark, kuid_t uid)
  {
        const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
        struct dst_entry *dst;
  
        memset(&fl6, 0, sizeof(fl6));
        fl6.flowi6_oif = oif;
 -      fl6.flowi6_mark = mark;
 +      fl6.flowi6_mark = mark ? mark : IP6_REPLY_MARK(net, skb->mark);
        fl6.flowi6_flags = 0;
        fl6.daddr = iph->daddr;
        fl6.saddr = iph->saddr;
        fl6.flowlabel = ip6_flowinfo(iph);
 +      fl6.flowi6_uid = uid;
  
        dst = ip6_route_output(net, NULL, &fl6);
        if (!dst->error)
@@@ -1174,7 -1174,7 +1171,7 @@@ EXPORT_SYMBOL_GPL(ip6_update_pmtu)
  void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
  {
        ip6_update_pmtu(skb, sock_net(sk), mtu,
 -                      sk->sk_bound_dev_if, sk->sk_mark);
 +                      sk->sk_bound_dev_if, sk->sk_mark, sock_i_uid(sk));
  }
  EXPORT_SYMBOL_GPL(ip6_sk_update_pmtu);
  
@@@ -1849,16 -1849,15 +1846,16 @@@ static struct rt6_info *ip6_rt_copy(str
  }
  
  #ifdef CONFIG_IPV6_ROUTE_INFO
 -static struct rt6_info *rt6_get_route_info(struct net *net,
 +static struct rt6_info *rt6_get_route_info(struct net_device *dev,
                                           const struct in6_addr *prefix, int prefixlen,
 -                                         const struct in6_addr *gwaddr, int ifindex)
 +                                         const struct in6_addr *gwaddr)
  {
        struct fib6_node *fn;
        struct rt6_info *rt = NULL;
        struct fib6_table *table;
  
 -      table = fib6_get_table(net, RT6_TABLE_INFO);
 +      table = fib6_get_table(dev_net(dev),
 +                             addrconf_rt_table(dev, RT6_TABLE_INFO));
        if (!table)
                return NULL;
  
                goto out;
  
        for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
 -              if (rt->dst.dev->ifindex != ifindex)
 +              if (rt->dst.dev->ifindex != dev->ifindex)
                        continue;
                if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY))
                        continue;
        return rt;
  }
  
 -static struct rt6_info *rt6_add_route_info(struct net *net,
 +static struct rt6_info *rt6_add_route_info(struct net_device *dev,
                                           const struct in6_addr *prefix, int prefixlen,
 -                                         const struct in6_addr *gwaddr, int ifindex,
 -                                         unsigned int pref)
 +                                         const struct in6_addr *gwaddr, unsigned int pref)
  {
        struct fib6_config cfg = {
 -              .fc_table       = RT6_TABLE_INFO,
 +              .fc_table       = addrconf_rt_table(dev, RT6_TABLE_INFO),
                .fc_metric      = IP6_RT_PRIO_USER,
 -              .fc_ifindex     = ifindex,
 +              .fc_ifindex     = dev->ifindex,
                .fc_dst_len     = prefixlen,
                .fc_flags       = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
                                  RTF_UP | RTF_PREF(pref),
                .fc_nlinfo.portid = 0,
                .fc_nlinfo.nlh = NULL,
 -              .fc_nlinfo.nl_net = net,
 +              .fc_nlinfo.nl_net = dev_net(dev),
        };
  
        cfg.fc_dst = *prefix;
  
        ip6_route_add(&cfg);
  
 -      return rt6_get_route_info(net, prefix, prefixlen, gwaddr, ifindex);
 +      return rt6_get_route_info(dev, prefix, prefixlen, gwaddr);
  }
  #endif
  
@@@ -1916,8 -1916,7 +1913,8 @@@ struct rt6_info *rt6_get_dflt_router(co
        struct rt6_info *rt;
        struct fib6_table *table;
  
 -      table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT);
 +      table = fib6_get_table(dev_net(dev),
 +                             addrconf_rt_table(dev, RT6_TABLE_MAIN));
        if (!table)
                return NULL;
  
@@@ -1939,7 -1938,7 +1936,7 @@@ struct rt6_info *rt6_add_dflt_router(co
                                     unsigned int pref)
  {
        struct fib6_config cfg = {
 -              .fc_table       = RT6_TABLE_DFLT,
 +              .fc_table       = addrconf_rt_table(dev, RT6_TABLE_DFLT),
                .fc_metric      = IP6_RT_PRIO_USER,
                .fc_ifindex     = dev->ifindex,
                .fc_flags       = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
        return rt6_get_dflt_router(gwaddr, dev);
  }
  
 -void rt6_purge_dflt_routers(struct net *net)
 -{
 -      struct rt6_info *rt;
 -      struct fib6_table *table;
  
 -      /* NOTE: Keep consistent with rt6_get_dflt_router */
 -      table = fib6_get_table(net, RT6_TABLE_DFLT);
 -      if (!table)
 -              return;
 +int rt6_addrconf_purge(struct rt6_info *rt, void *arg) {
 +      if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) &&
 +          (!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2))
 +              return -1;
 +      return 0;
 +}
  
 -restart:
 -      read_lock_bh(&table->tb6_lock);
 -      for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) {
 -              if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) &&
 -                  (!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2)) {
 -                      dst_hold(&rt->dst);
 -                      read_unlock_bh(&table->tb6_lock);
 -                      ip6_del_rt(rt);
 -                      goto restart;
 -              }
 -      }
 -      read_unlock_bh(&table->tb6_lock);
 +void rt6_purge_dflt_routers(struct net *net)
 +{
 +      fib6_clean_all(net, rt6_addrconf_purge, 0, NULL);
  }
  
  static void rtmsg_to_fib6_config(struct net *net,
@@@ -2251,7 -2261,6 +2248,7 @@@ static const struct nla_policy rtm_ipv6
        [RTA_PRIORITY]          = { .type = NLA_U32 },
        [RTA_METRICS]           = { .type = NLA_NESTED },
        [RTA_MULTIPATH]         = { .len = sizeof(struct rtnexthop) },
 +      [RTA_UID]               = { .type = NLA_U32 },
  };
  
  static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
@@@ -2638,12 -2647,6 +2635,12 @@@ static int inet6_rtm_getroute(struct sk
        if (tb[RTA_OIF])
                oif = nla_get_u32(tb[RTA_OIF]);
  
 +      if (tb[RTA_UID])
 +              fl6.flowi6_uid = make_kuid(current_user_ns(),
 +                                         nla_get_u32(tb[RTA_UID]));
 +      else
 +              fl6.flowi6_uid = iif ? INVALID_UID : current_uid();
 +
        if (iif) {
                struct net_device *dev;
                int flags = 0;