Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorDavid S. Miller <davem@davemloft.net>
Fri, 30 Dec 2011 18:04:14 +0000 (13:04 -0500)
committerDavid S. Miller <davem@davemloft.net>
Fri, 30 Dec 2011 18:04:14 +0000 (13:04 -0500)
1  2 
MAINTAINERS
net/netfilter/nf_conntrack_netlink.c
net/packet/af_packet.c
net/sched/sch_netem.c

diff --combined MAINTAINERS
@@@ -2700,7 -2700,7 +2700,7 @@@ FIREWIRE SUBSYSTE
  M:    Stefan Richter <stefanr@s5r6.in-berlin.de>
  L:    linux1394-devel@lists.sourceforge.net
  W:    http://ieee1394.wiki.kernel.org/
- T:    git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git
+ T:    git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394.git
  S:    Maintained
  F:    drivers/firewire/
  F:    include/linux/firewire*.h
@@@ -4855,14 -4855,6 +4855,14 @@@ S:    Maintaine
  T:    git git://openrisc.net/~jonas/linux
  F:    arch/openrisc
  
 +OPENVSWITCH
 +M:    Jesse Gross <jesse@nicira.com>
 +L:    dev@openvswitch.org
 +W:    http://openvswitch.org
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jesse/openvswitch.git
 +S:    Maintained
 +F:    net/openvswitch/
 +
  OPL4 DRIVER
  M:    Clemens Ladisch <clemens@ladisch.de>
  L:    alsa-devel@alsa-project.org (moderated for non-subscribers)
@@@ -5382,7 -5374,6 +5382,7 @@@ S:      Supporte
  F:    drivers/scsi/qla4xxx/
  
  QLOGIC QLA3XXX NETWORK DRIVER
 +M:    Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
  M:    Ron Mercer <ron.mercer@qlogic.com>
  M:    linux-driver@qlogic.com
  L:    netdev@vger.kernel.org
@@@ -5902,6 -5893,7 +5902,6 @@@ F:      drivers/net/ethernet/emulex/benet
  
  SFC NETWORK DRIVER
  M:    Solarflare linux maintainers <linux-net-drivers@solarflare.com>
 -M:    Steve Hodgson <shodgson@solarflare.com>
  M:    Ben Hutchings <bhutchings@solarflare.com>
  L:    netdev@vger.kernel.org
  S:    Supported
@@@ -6509,13 -6501,6 +6509,13 @@@ W:    http://tcp-lp-mod.sourceforge.net
  S:    Maintained
  F:    net/ipv4/tcp_lp.c
  
 +TEAM DRIVER
 +M:    Jiri Pirko <jpirko@redhat.com>
 +L:    netdev@vger.kernel.org
 +S:    Supported
 +F:    drivers/net/team/
 +F:    include/linux/if_team.h
 +
  TEGRA SUPPORT
  M:    Colin Cross <ccross@android.com>
  M:    Olof Johansson <olof@lixom.net>
@@@ -203,18 -203,25 +203,18 @@@ nla_put_failure
  }
  
  static int
 -ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
 -                      enum ip_conntrack_dir dir)
 +dump_counters(struct sk_buff *skb, u64 pkts, u64 bytes,
 +            enum ip_conntrack_dir dir)
  {
        enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
        struct nlattr *nest_count;
 -      const struct nf_conn_counter *acct;
 -
 -      acct = nf_conn_acct_find(ct);
 -      if (!acct)
 -              return 0;
  
        nest_count = nla_nest_start(skb, type | NLA_F_NESTED);
        if (!nest_count)
                goto nla_put_failure;
  
 -      NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS,
 -                   cpu_to_be64(acct[dir].packets));
 -      NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES,
 -                   cpu_to_be64(acct[dir].bytes));
 +      NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS, cpu_to_be64(pkts));
 +      NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES, cpu_to_be64(bytes));
  
        nla_nest_end(skb, nest_count);
  
@@@ -225,27 -232,6 +225,27 @@@ nla_put_failure
  }
  
  static int
 +ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
 +                      enum ip_conntrack_dir dir, int type)
 +{
 +      struct nf_conn_counter *acct;
 +      u64 pkts, bytes;
 +
 +      acct = nf_conn_acct_find(ct);
 +      if (!acct)
 +              return 0;
 +
 +      if (type == IPCTNL_MSG_CT_GET_CTRZERO) {
 +              pkts = atomic64_xchg(&acct[dir].packets, 0);
 +              bytes = atomic64_xchg(&acct[dir].bytes, 0);
 +      } else {
 +              pkts = atomic64_read(&acct[dir].packets);
 +              bytes = atomic64_read(&acct[dir].bytes);
 +      }
 +      return dump_counters(skb, pkts, bytes, dir);
 +}
 +
 +static int
  ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct)
  {
        struct nlattr *nest_count;
@@@ -407,15 -393,15 +407,15 @@@ nla_put_failure
  }
  
  static int
 -ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
 -                  int event, struct nf_conn *ct)
 +ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type,
 +                  struct nf_conn *ct)
  {
        struct nlmsghdr *nlh;
        struct nfgenmsg *nfmsg;
        struct nlattr *nest_parms;
 -      unsigned int flags = pid ? NLM_F_MULTI : 0;
 +      unsigned int flags = pid ? NLM_F_MULTI : 0, event;
  
 -      event |= NFNL_SUBSYS_CTNETLINK << 8;
 +      event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_NEW);
        nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags);
        if (nlh == NULL)
                goto nlmsg_failure;
  
        if (ctnetlink_dump_status(skb, ct) < 0 ||
            ctnetlink_dump_timeout(skb, ct) < 0 ||
 -          ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
 -          ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 ||
 +          ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL, type) < 0 ||
 +          ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY, type) < 0 ||
            ctnetlink_dump_timestamp(skb, ct) < 0 ||
            ctnetlink_dump_protoinfo(skb, ct) < 0 ||
            ctnetlink_dump_helpinfo(skb, ct) < 0 ||
@@@ -626,10 -612,8 +626,10 @@@ ctnetlink_conntrack_event(unsigned int 
                goto nla_put_failure;
  
        if (events & (1 << IPCT_DESTROY)) {
 -              if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
 -                  ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 ||
 +              if (ctnetlink_dump_counters(skb, ct,
 +                                          IP_CT_DIR_ORIGINAL, type) < 0 ||
 +                  ctnetlink_dump_counters(skb, ct,
 +                                          IP_CT_DIR_REPLY, type) < 0 ||
                    ctnetlink_dump_timestamp(skb, ct) < 0)
                        goto nla_put_failure;
        } else {
@@@ -725,13 -709,20 +725,13 @@@ restart
                        }
                        if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
                                                cb->nlh->nlmsg_seq,
 -                                              IPCTNL_MSG_CT_NEW, ct) < 0) {
 +                                              NFNL_MSG_TYPE(
 +                                                      cb->nlh->nlmsg_type),
 +                                              ct) < 0) {
                                nf_conntrack_get(&ct->ct_general);
                                cb->args[1] = (unsigned long)ct;
                                goto out;
                        }
 -
 -                      if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) ==
 -                                              IPCTNL_MSG_CT_GET_CTRZERO) {
 -                              struct nf_conn_counter *acct;
 -
 -                              acct = nf_conn_acct_find(ct);
 -                              if (acct)
 -                                      memset(acct, 0, sizeof(struct nf_conn_counter[IP_CT_DIR_MAX]));
 -                      }
                }
                if (cb->args[1]) {
                        cb->args[1] = 0;
@@@ -1010,7 -1001,7 +1010,7 @@@ ctnetlink_get_conntrack(struct sock *ct
  
        rcu_read_lock();
        err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq,
 -                                IPCTNL_MSG_CT_NEW, ct);
 +                                NFNL_MSG_TYPE(nlh->nlmsg_type), ct);
        rcu_read_unlock();
        nf_ct_put(ct);
        if (err <= 0)
@@@ -1096,14 -1087,14 +1096,14 @@@ ctnetlink_change_nat(struct nf_conn *ct
  
        if (cda[CTA_NAT_DST]) {
                ret = ctnetlink_parse_nat_setup(ct,
 -                                              IP_NAT_MANIP_DST,
 +                                              NF_NAT_MANIP_DST,
                                                cda[CTA_NAT_DST]);
                if (ret < 0)
                        return ret;
        }
        if (cda[CTA_NAT_SRC]) {
                ret = ctnetlink_parse_nat_setup(ct,
 -                                              IP_NAT_MANIP_SRC,
 +                                              NF_NAT_MANIP_SRC,
                                                cda[CTA_NAT_SRC]);
                if (ret < 0)
                        return ret;
@@@ -1367,12 -1358,15 +1367,15 @@@ ctnetlink_create_conntrack(struct net *
                                                    nf_ct_protonum(ct));
                if (helper == NULL) {
                        rcu_read_unlock();
+                       spin_unlock_bh(&nf_conntrack_lock);
  #ifdef CONFIG_MODULES
                        if (request_module("nfct-helper-%s", helpname) < 0) {
+                               spin_lock_bh(&nf_conntrack_lock);
                                err = -EOPNOTSUPP;
                                goto err1;
                        }
  
+                       spin_lock_bh(&nf_conntrack_lock);
                        rcu_read_lock();
                        helper = __nf_conntrack_helper_find(helpname,
                                                            nf_ct_l3num(ct),
@@@ -1856,9 -1850,7 +1859,9 @@@ ctnetlink_get_expect(struct sock *ctnl
        if (err < 0)
                return err;
  
 -      if (cda[CTA_EXPECT_MASTER])
 +      if (cda[CTA_EXPECT_TUPLE])
 +              err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
 +      else if (cda[CTA_EXPECT_MASTER])
                err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3);
        else
                return -EINVAL;
  
        err = -ENOMEM;
        skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-       if (skb2 == NULL)
+       if (skb2 == NULL) {
+               nf_ct_expect_put(exp);
                goto out;
+       }
  
        rcu_read_lock();
        err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid,
                                      nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, exp);
        rcu_read_unlock();
+       nf_ct_expect_put(exp);
        if (err <= 0)
                goto free;
  
-       nf_ct_expect_put(exp);
+       err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
+       if (err < 0)
+               goto out;
  
-       return netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
+       return 0;
  
  free:
        kfree_skb(skb2);
  out:
-       nf_ct_expect_put(exp);
-       return err;
+       /* this avoids a loop in nfnetlink. */
+       return err == -EAGAIN ? -ENOBUFS : err;
  }
  
  static int
@@@ -2034,10 -2031,6 +2042,10 @@@ ctnetlink_create_expect(struct net *net
        }
        help = nfct_help(ct);
        if (!help) {
 +              err = -EOPNOTSUPP;
 +              goto out;
 +      }
 +      if (test_bit(IPS_USERSPACE_HELPER_BIT, &ct->status)) {
                if (!cda[CTA_EXPECT_TIMEOUT]) {
                        err = -EINVAL;
                        goto out;
@@@ -2262,6 -2255,7 +2270,6 @@@ static void __exit ctnetlink_exit(void
  {
        pr_info("ctnetlink: unregistering from nfnetlink.\n");
  
 -      nf_ct_remove_userspace_expectations();
        unregister_pernet_subsys(&ctnetlink_net_ops);
        nfnetlink_subsys_unregister(&ctnl_exp_subsys);
        nfnetlink_subsys_unregister(&ctnl_subsys);
diff --combined net/packet/af_packet.c
@@@ -1499,11 -1499,10 +1499,11 @@@ retry
  
        if (!skb) {
                size_t reserved = LL_RESERVED_SPACE(dev);
 +              int tlen = dev->needed_tailroom;
                unsigned int hhlen = dev->header_ops ? dev->hard_header_len : 0;
  
                rcu_read_unlock();
 -              skb = sock_wmalloc(sk, len + reserved, 0, GFP_KERNEL);
 +              skb = sock_wmalloc(sk, len + reserved + tlen, 0, GFP_KERNEL);
                if (skb == NULL)
                        return -ENOBUFS;
                /* FIXME: Save some space for broken drivers that write a hard
@@@ -1943,7 -1942,7 +1943,7 @@@ static void tpacket_destruct_skb(struc
  
  static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
                void *frame, struct net_device *dev, int size_max,
 -              __be16 proto, unsigned char *addr)
 +              __be16 proto, unsigned char *addr, int hlen)
  {
        union {
                struct tpacket_hdr *h1;
                return -EMSGSIZE;
        }
  
 -      skb_reserve(skb, LL_RESERVED_SPACE(dev));
 +      skb_reserve(skb, hlen);
        skb_reset_network_header(skb);
  
        data = ph.raw + po->tp_hdrlen - sizeof(struct sockaddr_ll);
@@@ -2052,7 -2051,6 +2052,7 @@@ static int tpacket_snd(struct packet_so
        unsigned char *addr;
        int len_sum = 0;
        int status = 0;
 +      int hlen, tlen;
  
        mutex_lock(&po->pg_vec_lock);
  
                }
  
                status = TP_STATUS_SEND_REQUEST;
 +              hlen = LL_RESERVED_SPACE(dev);
 +              tlen = dev->needed_tailroom;
                skb = sock_alloc_send_skb(&po->sk,
 -                              LL_ALLOCATED_SPACE(dev)
 -                              + sizeof(struct sockaddr_ll),
 +                              hlen + tlen + sizeof(struct sockaddr_ll),
                                0, &err);
  
                if (unlikely(skb == NULL))
                        goto out_status;
  
                tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto,
 -                              addr);
 +                              addr, hlen);
  
                if (unlikely(tp_len < 0)) {
                        if (po->tp_loss) {
@@@ -2208,7 -2205,6 +2208,7 @@@ static int packet_snd(struct socket *so
        int vnet_hdr_len;
        struct packet_sock *po = pkt_sk(sk);
        unsigned short gso_type = 0;
 +      int hlen, tlen;
  
        /*
         *      Get and verify the address.
                goto out_unlock;
  
        err = -ENOBUFS;
 -      skb = packet_alloc_skb(sk, LL_ALLOCATED_SPACE(dev),
 -                             LL_RESERVED_SPACE(dev), len, vnet_hdr.hdr_len,
 +      hlen = LL_RESERVED_SPACE(dev);
 +      tlen = dev->needed_tailroom;
 +      skb = packet_alloc_skb(sk, hlen + tlen, hlen, len, vnet_hdr.hdr_len,
                               msg->msg_flags & MSG_DONTWAIT, &err);
        if (skb == NULL)
                goto out_unlock;
@@@ -2453,8 -2448,12 +2453,12 @@@ static int packet_do_bind(struct sock *
  {
        struct packet_sock *po = pkt_sk(sk);
  
-       if (po->fanout)
+       if (po->fanout) {
+               if (dev)
+                       dev_put(dev);
                return -EINVAL;
+       }
  
        lock_sock(sk);
  
diff --combined net/sched/sch_netem.c
@@@ -22,7 -22,6 +22,7 @@@
  #include <linux/skbuff.h>
  #include <linux/vmalloc.h>
  #include <linux/rtnetlink.h>
 +#include <linux/reciprocal_div.h>
  
  #include <net/netlink.h>
  #include <net/pkt_sched.h>
@@@ -80,11 -79,6 +80,11 @@@ struct netem_sched_data 
        u32 duplicate;
        u32 reorder;
        u32 corrupt;
 +      u32 rate;
 +      s32 packet_overhead;
 +      u32 cell_size;
 +      u32 cell_size_reciprocal;
 +      s32 cell_overhead;
  
        struct crndstate {
                u32 last;
@@@ -304,26 -298,6 +304,26 @@@ static psched_tdiff_t tabledist(psched_
        return  x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu;
  }
  
 +static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sched_data *q)
 +{
 +      u64 ticks;
 +
 +      len += q->packet_overhead;
 +
 +      if (q->cell_size) {
 +              u32 cells = reciprocal_divide(len, q->cell_size_reciprocal);
 +
 +              if (len > cells * q->cell_size) /* extra cell needed for remainder */
 +                      cells++;
 +              len = cells * (q->cell_size + q->cell_overhead);
 +      }
 +
 +      ticks = (u64)len * NSEC_PER_SEC;
 +
 +      do_div(ticks, q->rate);
 +      return PSCHED_NS2TICKS(ticks);
 +}
 +
  /*
   * Insert one skb into qdisc.
   * Note: parent depends on return value to account for queue length.
@@@ -397,24 -371,6 +397,24 @@@ static int netem_enqueue(struct sk_buf
                                  &q->delay_cor, q->delay_dist);
  
                now = psched_get_time();
 +
 +              if (q->rate) {
 +                      struct sk_buff_head *list = &q->qdisc->q;
 +
 +                      delay += packet_len_2_sched_time(skb->len, q);
 +
 +                      if (!skb_queue_empty(list)) {
 +                              /*
 +                               * Last packet in queue is reference point (now).
 +                               * First packet in queue is already in flight,
 +                               * calculate this time bonus and substract
 +                               * from delay.
 +                               */
 +                              delay -= now - netem_skb_cb(skb_peek(list))->time_to_send;
 +                              now = netem_skb_cb(skb_peek_tail(list))->time_to_send;
 +                      }
 +              }
 +
                cb->time_to_send = now + delay;
                ++q->counter;
                ret = qdisc_enqueue(skb, q->qdisc);
@@@ -532,7 -488,7 +532,7 @@@ static int get_dist_table(struct Qdisc 
                return -EINVAL;
  
        s = sizeof(struct disttable) + n * sizeof(s16);
-       d = kmalloc(s, GFP_KERNEL);
+       d = kmalloc(s, GFP_KERNEL | __GFP_NOWARN);
        if (!d)
                d = vmalloc(s);
        if (!d)
        root_lock = qdisc_root_sleeping_lock(sch);
  
        spin_lock_bh(root_lock);
-       dist_free(q->delay_dist);
-       q->delay_dist = d;
+       swap(q->delay_dist, d);
        spin_unlock_bh(root_lock);
+       dist_free(d);
        return 0;
  }
  
@@@ -579,19 -536,6 +580,19 @@@ static void get_corrupt(struct Qdisc *s
        init_crandom(&q->corrupt_cor, r->correlation);
  }
  
 +static void get_rate(struct Qdisc *sch, const struct nlattr *attr)
 +{
 +      struct netem_sched_data *q = qdisc_priv(sch);
 +      const struct tc_netem_rate *r = nla_data(attr);
 +
 +      q->rate = r->rate;
 +      q->packet_overhead = r->packet_overhead;
 +      q->cell_size = r->cell_size;
 +      if (q->cell_size)
 +              q->cell_size_reciprocal = reciprocal_value(q->cell_size);
 +      q->cell_overhead = r->cell_overhead;
 +}
 +
  static int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr)
  {
        struct netem_sched_data *q = qdisc_priv(sch);
                case NETEM_LOSS_GI: {
                        const struct tc_netem_gimodel *gi = nla_data(la);
  
 -                      if (nla_len(la) != sizeof(struct tc_netem_gimodel)) {
 +                      if (nla_len(la) < sizeof(struct tc_netem_gimodel)) {
                                pr_info("netem: incorrect gi model size\n");
                                return -EINVAL;
                        }
                case NETEM_LOSS_GE: {
                        const struct tc_netem_gemodel *ge = nla_data(la);
  
 -                      if (nla_len(la) != sizeof(struct tc_netem_gemodel)) {
 -                              pr_info("netem: incorrect gi model size\n");
 +                      if (nla_len(la) < sizeof(struct tc_netem_gemodel)) {
 +                              pr_info("netem: incorrect ge model size\n");
                                return -EINVAL;
                        }
  
@@@ -651,7 -595,6 +652,7 @@@ static const struct nla_policy netem_po
        [TCA_NETEM_CORR]        = { .len = sizeof(struct tc_netem_corr) },
        [TCA_NETEM_REORDER]     = { .len = sizeof(struct tc_netem_reorder) },
        [TCA_NETEM_CORRUPT]     = { .len = sizeof(struct tc_netem_corrupt) },
 +      [TCA_NETEM_RATE]        = { .len = sizeof(struct tc_netem_rate) },
        [TCA_NETEM_LOSS]        = { .type = NLA_NESTED },
  };
  
@@@ -724,9 -667,6 +725,9 @@@ static int netem_change(struct Qdisc *s
        if (tb[TCA_NETEM_CORRUPT])
                get_corrupt(sch, tb[TCA_NETEM_CORRUPT]);
  
 +      if (tb[TCA_NETEM_RATE])
 +              get_rate(sch, tb[TCA_NETEM_RATE]);
 +
        q->loss_model = CLG_RANDOM;
        if (tb[TCA_NETEM_LOSS])
                ret = get_loss_clg(sch, tb[TCA_NETEM_LOSS]);
@@@ -907,7 -847,6 +908,7 @@@ static int netem_dump(struct Qdisc *sch
        struct tc_netem_corr cor;
        struct tc_netem_reorder reorder;
        struct tc_netem_corrupt corrupt;
 +      struct tc_netem_rate rate;
  
        qopt.latency = q->latency;
        qopt.jitter = q->jitter;
        corrupt.correlation = q->corrupt_cor.rho;
        NLA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt);
  
 +      rate.rate = q->rate;
 +      rate.packet_overhead = q->packet_overhead;
 +      rate.cell_size = q->cell_size;
 +      rate.cell_overhead = q->cell_overhead;
 +      NLA_PUT(skb, TCA_NETEM_RATE, sizeof(rate), &rate);
 +
        if (dump_loss_model(q, skb) != 0)
                goto nla_put_failure;