Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2012 Mellanox Technologies. -  All rights reserved.
0003  *
0004  * This software is available to you under a choice of one of two
0005  * licenses.  You may choose to be licensed under the terms of the GNU
0006  * General Public License (GPL) Version 2, available from the file
0007  * COPYING in the main directory of this source tree, or the
0008  * OpenIB.org BSD license below:
0009  *
0010  *     Redistribution and use in source and binary forms, with or
0011  *     without modification, are permitted provided that the following
0012  *     conditions are met:
0013  *
0014  *      - Redistributions of source code must retain the above
0015  *        copyright notice, this list of conditions and the following
0016  *        disclaimer.
0017  *
0018  *      - Redistributions in binary form must reproduce the above
0019  *        copyright notice, this list of conditions and the following
0020  *        disclaimer in the documentation and/or other materials
0021  *        provided with the distribution.
0022  *
0023  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0024  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0025  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0026  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
0027  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0028  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0029  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0030  * SOFTWARE.
0031  */
0032 
0033 #include <linux/netdevice.h>
0034 #include <linux/if_arp.h>      /* For ARPHRD_xxx */
0035 #include <net/rtnetlink.h>
0036 #include "ipoib.h"
0037 
0038 static const struct nla_policy ipoib_policy[IFLA_IPOIB_MAX + 1] = {
0039     [IFLA_IPOIB_PKEY]   = { .type = NLA_U16 },
0040     [IFLA_IPOIB_MODE]   = { .type = NLA_U16 },
0041     [IFLA_IPOIB_UMCAST] = { .type = NLA_U16 },
0042 };
0043 
0044 static int ipoib_fill_info(struct sk_buff *skb, const struct net_device *dev)
0045 {
0046     struct ipoib_dev_priv *priv = ipoib_priv(dev);
0047     u16 val;
0048 
0049     if (nla_put_u16(skb, IFLA_IPOIB_PKEY, priv->pkey))
0050         goto nla_put_failure;
0051 
0052     val = test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
0053     if (nla_put_u16(skb, IFLA_IPOIB_MODE, val))
0054         goto nla_put_failure;
0055 
0056     val = test_bit(IPOIB_FLAG_UMCAST, &priv->flags);
0057     if (nla_put_u16(skb, IFLA_IPOIB_UMCAST, val))
0058         goto nla_put_failure;
0059 
0060     return 0;
0061 
0062 nla_put_failure:
0063     return -EMSGSIZE;
0064 }
0065 
0066 static int ipoib_changelink(struct net_device *dev, struct nlattr *tb[],
0067                 struct nlattr *data[],
0068                 struct netlink_ext_ack *extack)
0069 {
0070     u16 mode, umcast;
0071     int ret = 0;
0072 
0073     if (data[IFLA_IPOIB_MODE]) {
0074         mode  = nla_get_u16(data[IFLA_IPOIB_MODE]);
0075         if (mode == IPOIB_MODE_DATAGRAM)
0076             ret = ipoib_set_mode(dev, "datagram\n");
0077         else if (mode == IPOIB_MODE_CONNECTED)
0078             ret = ipoib_set_mode(dev, "connected\n");
0079         else
0080             ret = -EINVAL;
0081 
0082         if (ret < 0)
0083             goto out_err;
0084     }
0085 
0086     if (data[IFLA_IPOIB_UMCAST]) {
0087         umcast = nla_get_u16(data[IFLA_IPOIB_UMCAST]);
0088         ipoib_set_umcast(dev, umcast);
0089     }
0090 
0091 out_err:
0092     return ret;
0093 }
0094 
0095 static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
0096                 struct nlattr *tb[], struct nlattr *data[],
0097                 struct netlink_ext_ack *extack)
0098 {
0099     struct net_device *pdev;
0100     struct ipoib_dev_priv *ppriv;
0101     u16 child_pkey;
0102     int err;
0103 
0104     if (!tb[IFLA_LINK])
0105         return -EINVAL;
0106 
0107     pdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
0108     if (!pdev || pdev->type != ARPHRD_INFINIBAND)
0109         return -ENODEV;
0110 
0111     ppriv = ipoib_priv(pdev);
0112 
0113     if (test_bit(IPOIB_FLAG_SUBINTERFACE, &ppriv->flags)) {
0114         ipoib_warn(ppriv, "child creation disallowed for child devices\n");
0115         return -EINVAL;
0116     }
0117 
0118     if (!data || !data[IFLA_IPOIB_PKEY]) {
0119         ipoib_dbg(ppriv, "no pkey specified, using parent pkey\n");
0120         child_pkey  = ppriv->pkey;
0121     } else
0122         child_pkey  = nla_get_u16(data[IFLA_IPOIB_PKEY]);
0123 
0124     err = ipoib_intf_init(ppriv->ca, ppriv->port, dev->name, dev);
0125     if (err) {
0126         ipoib_warn(ppriv, "failed to initialize pkey device\n");
0127         return err;
0128     }
0129 
0130     err = __ipoib_vlan_add(ppriv, ipoib_priv(dev),
0131                    child_pkey, IPOIB_RTNL_CHILD);
0132     if (err)
0133         return err;
0134 
0135     if (data) {
0136         err = ipoib_changelink(dev, tb, data, extack);
0137         if (err) {
0138             unregister_netdevice(dev);
0139             return err;
0140         }
0141     }
0142 
0143     return 0;
0144 }
0145 
0146 static void ipoib_del_child_link(struct net_device *dev, struct list_head *head)
0147 {
0148     struct ipoib_dev_priv *priv = ipoib_priv(dev);
0149 
0150     if (!priv->parent)
0151         return;
0152 
0153     unregister_netdevice_queue(dev, head);
0154 }
0155 
0156 static size_t ipoib_get_size(const struct net_device *dev)
0157 {
0158     return nla_total_size(2) +  /* IFLA_IPOIB_PKEY   */
0159         nla_total_size(2) + /* IFLA_IPOIB_MODE   */
0160         nla_total_size(2);  /* IFLA_IPOIB_UMCAST */
0161 }
0162 
0163 static struct rtnl_link_ops ipoib_link_ops __read_mostly = {
0164     .kind       = "ipoib",
0165     .netns_refund   = true,
0166     .maxtype    = IFLA_IPOIB_MAX,
0167     .policy     = ipoib_policy,
0168     .priv_size  = sizeof(struct ipoib_dev_priv),
0169     .setup      = ipoib_setup_common,
0170     .newlink    = ipoib_new_child_link,
0171     .dellink    = ipoib_del_child_link,
0172     .changelink = ipoib_changelink,
0173     .get_size   = ipoib_get_size,
0174     .fill_info  = ipoib_fill_info,
0175 };
0176 
0177 struct rtnl_link_ops *ipoib_get_link_ops(void)
0178 {
0179     return &ipoib_link_ops;
0180 }
0181 
0182 int __init ipoib_netlink_init(void)
0183 {
0184     return rtnl_link_register(&ipoib_link_ops);
0185 }
0186 
0187 void __exit ipoib_netlink_fini(void)
0188 {
0189     rtnl_link_unregister(&ipoib_link_ops);
0190 }
0191 
0192 MODULE_ALIAS_RTNL_LINK("ipoib");