net/core: Add VF link state control
authorRony Efraim <ronye@mellanox.com>
Thu, 13 Jun 2013 10:19:10 +0000 (13:19 +0300)
committerDavid S. Miller <davem@davemloft.net>
Fri, 14 Jun 2013 00:51:04 +0000 (17:51 -0700)
Add netlink directives and ndo entry to allow for controling
VF link, which can be in one of three states:

Auto - VF link state reflects the PF link state (default)

Up - VF link state is up, traffic from VF to VF works even if
the actual PF link is down

Down - VF link state is down, no traffic from/to this VF, can be of
use while configuring the VF

Signed-off-by: Rony Efraim <ronye@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/if_link.h
include/linux/netdevice.h
include/uapi/linux/if_link.h
net/core/rtnetlink.c

index c3f817c3eb451091e5b02fc6c8f22e7af5d1126a..a86784dec3d34fcafb7e5d1b377a9d73b2d7717e 100644 (file)
@@ -12,5 +12,6 @@ struct ifla_vf_info {
        __u32 qos;
        __u32 tx_rate;
        __u32 spoofchk;
+       __u32 linkstate;
 };
 #endif /* _LINUX_IF_LINK_H */
index 8c9fcc42502a197b2c3a0ea783c91c22c40c2d6d..09b4188c1ea79cc0fa3eed0f4a668d71b930ea55 100644 (file)
@@ -829,6 +829,7 @@ struct netdev_fcoe_hbainfo {
  * int (*ndo_set_vf_spoofchk)(struct net_device *dev, int vf, bool setting);
  * int (*ndo_get_vf_config)(struct net_device *dev,
  *                         int vf, struct ifla_vf_info *ivf);
+ * int (*ndo_set_vf_link_state)(struct net_device *dev, int vf, int link_state);
  * int (*ndo_set_vf_port)(struct net_device *dev, int vf,
  *                       struct nlattr *port[]);
  * int (*ndo_get_vf_port)(struct net_device *dev, int vf, struct sk_buff *skb);
@@ -986,6 +987,8 @@ struct net_device_ops {
        int                     (*ndo_get_vf_config)(struct net_device *dev,
                                                     int vf,
                                                     struct ifla_vf_info *ivf);
+       int                     (*ndo_set_vf_link_state)(struct net_device *dev,
+                                                        int vf, int link_state);
        int                     (*ndo_set_vf_port)(struct net_device *dev,
                                                   int vf,
                                                   struct nlattr *port[]);
index da05a2698cb5c67f32c11f5dd73743c2d2429e56..03f6170ab3372f443c0989c7c5a503b00ef0c308 100644 (file)
@@ -338,6 +338,7 @@ enum {
        IFLA_VF_VLAN,
        IFLA_VF_TX_RATE,        /* TX Bandwidth Allocation */
        IFLA_VF_SPOOFCHK,       /* Spoof Checking on/off switch */
+       IFLA_VF_LINK_STATE,     /* link state enable/disable/auto switch */
        __IFLA_VF_MAX,
 };
 
@@ -364,6 +365,18 @@ struct ifla_vf_spoofchk {
        __u32 setting;
 };
 
+enum {
+       IFLA_VF_LINK_STATE_AUTO,        /* link state of the uplink */
+       IFLA_VF_LINK_STATE_ENABLE,      /* link always up */
+       IFLA_VF_LINK_STATE_DISABLE,     /* link always down */
+       __IFLA_VF_LINK_STATE_MAX,
+};
+
+struct ifla_vf_link_state {
+       __u32 vf;
+       __u32 link_state;
+};
+
 /* VF ports management section
  *
  *     Nested layout of set/get msg is:
index 49c14451d8ab81b9f9ebd75238e5374d4067c397..9007533867f0e99cc27cf3c19cc0539de558a8b6 100644 (file)
@@ -947,6 +947,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                        struct ifla_vf_vlan vf_vlan;
                        struct ifla_vf_tx_rate vf_tx_rate;
                        struct ifla_vf_spoofchk vf_spoofchk;
+                       struct ifla_vf_link_state vf_linkstate;
 
                        /*
                         * Not all SR-IOV capable drivers support the
@@ -956,18 +957,24 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                         */
                        ivi.spoofchk = -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
+                        */
+                       ivi.linkstate = 0;
                        if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi))
                                break;
                        vf_mac.vf =
                                vf_vlan.vf =
                                vf_tx_rate.vf =
-                               vf_spoofchk.vf = ivi.vf;
+                               vf_spoofchk.vf =
+                               vf_linkstate.vf = ivi.vf;
 
                        memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac));
                        vf_vlan.vlan = ivi.vlan;
                        vf_vlan.qos = ivi.qos;
                        vf_tx_rate.rate = ivi.tx_rate;
                        vf_spoofchk.setting = ivi.spoofchk;
+                       vf_linkstate.link_state = ivi.linkstate;
                        vf = nla_nest_start(skb, IFLA_VF_INFO);
                        if (!vf) {
                                nla_nest_cancel(skb, vfinfo);
@@ -978,7 +985,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                            nla_put(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate),
                                    &vf_tx_rate) ||
                            nla_put(skb, IFLA_VF_SPOOFCHK, sizeof(vf_spoofchk),
-                                   &vf_spoofchk))
+                                   &vf_spoofchk) ||
+                           nla_put(skb, IFLA_VF_LINK_STATE, sizeof(vf_linkstate),
+                                   &vf_linkstate))
                                goto nla_put_failure;
                        nla_nest_end(skb, vf);
                }
@@ -1238,6 +1247,15 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr *attr)
                                                               ivs->setting);
                        break;
                }
+               case IFLA_VF_LINK_STATE: {
+                       struct ifla_vf_link_state *ivl;
+                       ivl = nla_data(vf);
+                       err = -EOPNOTSUPP;
+                       if (ops->ndo_set_vf_link_state)
+                               err = ops->ndo_set_vf_link_state(dev, ivl->vf,
+                                                                ivl->link_state);
+                       break;
+               }
                default:
                        err = -EINVAL;
                        break;