Merge branches 'acpi-resources', 'acpi-battery', 'acpi-doc' and 'acpi-pnp'
[linux-2.6-block.git] / net / core / rtnetlink.c
index ee0608bb3bc087212d12bac729677bf454053560..666e0928ba404b85cf210749e505a2c205e5ee3f 100644 (file)
@@ -818,7 +818,8 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev,
                         nla_total_size(sizeof(struct ifla_vf_vlan)) +
                         nla_total_size(sizeof(struct ifla_vf_spoofchk)) +
                         nla_total_size(sizeof(struct ifla_vf_rate)) +
-                        nla_total_size(sizeof(struct ifla_vf_link_state)));
+                        nla_total_size(sizeof(struct ifla_vf_link_state)) +
+                        nla_total_size(sizeof(struct ifla_vf_rss_query_en)));
                return size;
        } else
                return 0;
@@ -982,6 +983,24 @@ static int rtnl_phys_port_id_fill(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
+static int rtnl_phys_port_name_fill(struct sk_buff *skb, struct net_device *dev)
+{
+       char name[IFNAMSIZ];
+       int err;
+
+       err = dev_get_phys_port_name(dev, name, sizeof(name));
+       if (err) {
+               if (err == -EOPNOTSUPP)
+                       return 0;
+               return err;
+       }
+
+       if (nla_put(skb, IFLA_PHYS_PORT_NAME, strlen(name), name))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
 static int rtnl_phys_switch_id_fill(struct sk_buff *skb, struct net_device *dev)
 {
        int err;
@@ -1037,8 +1056,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 #ifdef CONFIG_RPS
            nla_put_u32(skb, IFLA_NUM_RX_QUEUES, dev->num_rx_queues) ||
 #endif
-           (dev->ifindex != dev->iflink &&
-            nla_put_u32(skb, IFLA_LINK, dev->iflink)) ||
+           (dev->ifindex != dev_get_iflink(dev) &&
+            nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))) ||
            (upper_dev &&
             nla_put_u32(skb, IFLA_MASTER, upper_dev->ifindex)) ||
            nla_put_u8(skb, IFLA_CARRIER, netif_carrier_ok(dev)) ||
@@ -1072,6 +1091,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
        if (rtnl_phys_port_id_fill(skb, dev))
                goto nla_put_failure;
 
+       if (rtnl_phys_port_name_fill(skb, dev))
+               goto nla_put_failure;
+
        if (rtnl_phys_switch_id_fill(skb, dev))
                goto nla_put_failure;
 
@@ -1111,14 +1133,16 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                        struct ifla_vf_tx_rate vf_tx_rate;
                        struct ifla_vf_spoofchk vf_spoofchk;
                        struct ifla_vf_link_state vf_linkstate;
+                       struct ifla_vf_rss_query_en vf_rss_query_en;
 
                        /*
                         * Not all SR-IOV capable drivers support the
-                        * spoofcheck query.  Preset to -1 so the user
-                        * space tool can detect that the driver didn't
-                        * report anything.
+                        * spoofcheck and "RSS query enable" query.  Preset to
+                        * -1 so the user space tool can detect that the driver
+                        * didn't report anything.
                         */
                        ivi.spoofchk = -1;
+                       ivi.rss_query_en = -1;
                        memset(ivi.mac, 0, sizeof(ivi.mac));
                        /* The default value for VF link state is "auto"
                         * IFLA_VF_LINK_STATE_AUTO which equals zero
@@ -1131,7 +1155,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                                vf_rate.vf =
                                vf_tx_rate.vf =
                                vf_spoofchk.vf =
-                               vf_linkstate.vf = ivi.vf;
+                               vf_linkstate.vf =
+                               vf_rss_query_en.vf = ivi.vf;
 
                        memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac));
                        vf_vlan.vlan = ivi.vlan;
@@ -1141,6 +1166,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                        vf_rate.max_tx_rate = ivi.max_tx_rate;
                        vf_spoofchk.setting = ivi.spoofchk;
                        vf_linkstate.link_state = ivi.linkstate;
+                       vf_rss_query_en.setting = ivi.rss_query_en;
                        vf = nla_nest_start(skb, IFLA_VF_INFO);
                        if (!vf) {
                                nla_nest_cancel(skb, vfinfo);
@@ -1155,7 +1181,10 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                            nla_put(skb, IFLA_VF_SPOOFCHK, sizeof(vf_spoofchk),
                                    &vf_spoofchk) ||
                            nla_put(skb, IFLA_VF_LINK_STATE, sizeof(vf_linkstate),
-                                   &vf_linkstate))
+                                   &vf_linkstate) ||
+                           nla_put(skb, IFLA_VF_RSS_QUERY_EN,
+                                   sizeof(vf_rss_query_en),
+                                   &vf_rss_query_en))
                                goto nla_put_failure;
                        nla_nest_end(skb, vf);
                }
@@ -1269,6 +1298,7 @@ static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
        [IFLA_VF_SPOOFCHK]      = { .len = sizeof(struct ifla_vf_spoofchk) },
        [IFLA_VF_RATE]          = { .len = sizeof(struct ifla_vf_rate) },
        [IFLA_VF_LINK_STATE]    = { .len = sizeof(struct ifla_vf_link_state) },
+       [IFLA_VF_RSS_QUERY_EN]  = { .len = sizeof(struct ifla_vf_rss_query_en) },
 };
 
 static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = {
@@ -1479,6 +1509,17 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr *attr)
                                                                 ivl->link_state);
                        break;
                }
+               case IFLA_VF_RSS_QUERY_EN: {
+                       struct ifla_vf_rss_query_en *ivrssq_en;
+
+                       ivrssq_en = nla_data(vf);
+                       err = -EOPNOTSUPP;
+                       if (ops->ndo_set_vf_rss_query_en)
+                               err = ops->ndo_set_vf_rss_query_en(dev,
+                                                           ivrssq_en->vf,
+                                                           ivrssq_en->setting);
+                       break;
+               }
                default:
                        err = -EINVAL;
                        break;
@@ -1815,6 +1856,42 @@ errout:
        return err;
 }
 
+static int rtnl_group_dellink(const struct net *net, int group)
+{
+       struct net_device *dev, *aux;
+       LIST_HEAD(list_kill);
+       bool found = false;
+
+       if (!group)
+               return -EPERM;
+
+       for_each_netdev(net, dev) {
+               if (dev->group == group) {
+                       const struct rtnl_link_ops *ops;
+
+                       found = true;
+                       ops = dev->rtnl_link_ops;
+                       if (!ops || !ops->dellink)
+                               return -EOPNOTSUPP;
+               }
+       }
+
+       if (!found)
+               return -ENODEV;
+
+       for_each_netdev_safe(net, dev, aux) {
+               if (dev->group == group) {
+                       const struct rtnl_link_ops *ops;
+
+                       ops = dev->rtnl_link_ops;
+                       ops->dellink(dev, &list_kill);
+               }
+       }
+       unregister_netdevice_many(&list_kill);
+
+       return 0;
+}
+
 static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
        struct net *net = sock_net(skb->sk);
@@ -1838,6 +1915,8 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh)
                dev = __dev_get_by_index(net, ifm->ifi_index);
        else if (tb[IFLA_IFNAME])
                dev = __dev_get_by_name(net, ifname);
+       else if (tb[IFLA_GROUP])
+               return rtnl_group_dellink(net, nla_get_u32(tb[IFLA_GROUP]));
        else
                return -EINVAL;
 
@@ -1873,7 +1952,7 @@ int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm)
 EXPORT_SYMBOL(rtnl_configure_link);
 
 struct net_device *rtnl_create_link(struct net *net,
-       char *ifname, unsigned char name_assign_type,
+       const char *ifname, unsigned char name_assign_type,
        const struct rtnl_link_ops *ops, struct nlattr *tb[])
 {
        int err;
@@ -1932,10 +2011,10 @@ static int rtnl_group_changelink(const struct sk_buff *skb,
                struct ifinfomsg *ifm,
                struct nlattr **tb)
 {
-       struct net_device *dev;
+       struct net_device *dev, *aux;
        int err;
 
-       for_each_netdev(net, dev) {
+       for_each_netdev_safe(net, dev, aux) {
                if (dev->group == group) {
                        err = do_setlink(skb, dev, ifm, tb, NULL, 0);
                        if (err < 0)
@@ -2345,7 +2424,7 @@ EXPORT_SYMBOL(rtmsg_ifinfo);
 
 static int nlmsg_populate_fdb_fill(struct sk_buff *skb,
                                   struct net_device *dev,
-                                  u8 *addr, u32 pid, u32 seq,
+                                  u8 *addr, u16 vid, u32 pid, u32 seq,
                                   int type, unsigned int flags,
                                   int nlflags)
 {
@@ -2367,6 +2446,9 @@ static int nlmsg_populate_fdb_fill(struct sk_buff *skb,
 
        if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr))
                goto nla_put_failure;
+       if (vid)
+               if (nla_put(skb, NDA_VLAN, sizeof(u16), &vid))
+                       goto nla_put_failure;
 
        nlmsg_end(skb, nlh);
        return 0;
@@ -2381,7 +2463,7 @@ static inline size_t rtnl_fdb_nlmsg_size(void)
        return NLMSG_ALIGN(sizeof(struct ndmsg)) + nla_total_size(ETH_ALEN);
 }
 
-static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, int type)
+static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, u16 vid, int type)
 {
        struct net *net = dev_net(dev);
        struct sk_buff *skb;
@@ -2391,7 +2473,8 @@ static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, int type)
        if (!skb)
                goto errout;
 
-       err = nlmsg_populate_fdb_fill(skb, dev, addr, 0, 0, type, NTF_SELF, 0);
+       err = nlmsg_populate_fdb_fill(skb, dev, addr, vid,
+                                     0, 0, type, NTF_SELF, 0);
        if (err < 0) {
                kfree_skb(skb);
                goto errout;
@@ -2526,7 +2609,7 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh)
                                               nlh->nlmsg_flags);
 
                if (!err) {
-                       rtnl_fdb_notify(dev, addr, RTM_NEWNEIGH);
+                       rtnl_fdb_notify(dev, addr, vid, RTM_NEWNEIGH);
                        ndm->ndm_flags &= ~NTF_SELF;
                }
        }
@@ -2627,7 +2710,7 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh)
                        err = ndo_dflt_fdb_del(ndm, tb, dev, addr, vid);
 
                if (!err) {
-                       rtnl_fdb_notify(dev, addr, RTM_DELNEIGH);
+                       rtnl_fdb_notify(dev, addr, vid, RTM_DELNEIGH);
                        ndm->ndm_flags &= ~NTF_SELF;
                }
        }
@@ -2652,7 +2735,7 @@ static int nlmsg_populate_fdb(struct sk_buff *skb,
                if (*idx < cb->args[0])
                        goto skip;
 
-               err = nlmsg_populate_fdb_fill(skb, dev, ha->addr,
+               err = nlmsg_populate_fdb_fill(skb, dev, ha->addr, 0,
                                              portid, seq,
                                              RTM_NEWNEIGH, NTF_SELF,
                                              NLM_F_MULTI);
@@ -2695,7 +2778,6 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
 {
        struct net_device *dev;
        struct nlattr *tb[IFLA_MAX+1];
-       struct net_device *bdev = NULL;
        struct net_device *br_dev = NULL;
        const struct net_device_ops *ops = NULL;
        const struct net_device_ops *cops = NULL;
@@ -2719,7 +2801,6 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
                        return -ENODEV;
 
                ops = br_dev->netdev_ops;
-               bdev = br_dev;
        }
 
        for_each_netdev(net, dev) {
@@ -2732,7 +2813,6 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
                                cops = br_dev->netdev_ops;
                        }
 
-                       bdev = dev;
                } else {
                        if (dev != br_dev &&
                            !(dev->priv_flags & IFF_BRIDGE_PORT))
@@ -2742,7 +2822,6 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
                            !(dev->priv_flags & IFF_EBRIDGE))
                                continue;
 
-                       bdev = br_dev;
                        cops = ops;
                }
 
@@ -2775,7 +2854,7 @@ static int brport_nla_put_flag(struct sk_buff *skb, u32 flags, u32 mask,
 
 int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
                            struct net_device *dev, u16 mode,
-                           u32 flags, u32 mask)
+                           u32 flags, u32 mask, int nlflags)
 {
        struct nlmsghdr *nlh;
        struct ifinfomsg *ifm;
@@ -2784,7 +2863,7 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
        u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
        struct net_device *br_dev = netdev_master_upper_dev_get(dev);
 
-       nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), NLM_F_MULTI);
+       nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), nlflags);
        if (nlh == NULL)
                return -EMSGSIZE;
 
@@ -2804,8 +2883,8 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
             nla_put_u32(skb, IFLA_MASTER, br_dev->ifindex)) ||
            (dev->addr_len &&
             nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
-           (dev->ifindex != dev->iflink &&
-            nla_put_u32(skb, IFLA_LINK, dev->iflink)))
+           (dev->ifindex != dev_get_iflink(dev) &&
+            nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))))
                goto nla_put_failure;
 
        br_afspec = nla_nest_start(skb, IFLA_AF_SPEC);
@@ -2890,7 +2969,8 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
                if (br_dev && br_dev->netdev_ops->ndo_bridge_getlink) {
                        if (idx >= cb->args[0] &&
                            br_dev->netdev_ops->ndo_bridge_getlink(
-                                   skb, portid, seq, dev, filter_mask) < 0)
+                                   skb, portid, seq, dev, filter_mask,
+                                   NLM_F_MULTI) < 0)
                                break;
                        idx++;
                }
@@ -2898,7 +2978,8 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
                if (ops->ndo_bridge_getlink) {
                        if (idx >= cb->args[0] &&
                            ops->ndo_bridge_getlink(skb, portid, seq, dev,
-                                                   filter_mask) < 0)
+                                                   filter_mask,
+                                                   NLM_F_MULTI) < 0)
                                break;
                        idx++;
                }
@@ -2939,7 +3020,7 @@ static int rtnl_bridge_notify(struct net_device *dev)
                goto errout;
        }
 
-       err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0);
+       err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0, 0);
        if (err < 0)
                goto errout;