aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorScott Feldman <scofeldm@cisco.com>2010-05-18 01:49:55 -0400
committerDavid S. Miller <davem@davemloft.net>2010-05-18 01:49:55 -0400
commit57b610805ce92dbd79fc97509f80fa5391b99623 (patch)
tree0d022d63c81d73b51e6001758d4353d0518a01e1
parentee289b6440c3b0ccb9459495783e8c299bec6604 (diff)
net: Add netlink support for virtual port management (was iovnl)
Add new netdev ops ndo_{set|get}_vf_port to allow setting of port-profile on a netdev interface. Extends netlink socket RTM_SETLINK/ RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF (added to end of IFLA_cmd list). These are both nested atrtibutes using this layout: [IFLA_NUM_VF] [IFLA_VF_PORTS] [IFLA_VF_PORT] [IFLA_PORT_*], ... [IFLA_VF_PORT] [IFLA_PORT_*], ... ... [IFLA_PORT_SELF] [IFLA_PORT_*], ... These attributes are design to be set and get symmetrically. VF_PORTS is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV device. PORT_SELF is for the PF of the SR-IOV device, in case it wants to also have a port-profile, or for the case where the VF==PF, like in enic patch 2/2 of this patch set. A port-profile is used to configure/enable the external switch virtual port backing the netdev interface, not to configure the host-facing side of the netdev. A port-profile is an identifier known to the switch. How port- profiles are installed on the switch or how available port-profiles are made know to the host is outside the scope of this patch. There are two types of port-profiles specs in the netlink msg. The first spec is for 802.1Qbg (pre-)standard, VDP protocol. The second spec is for devices that run a similar protocol as VDP but in firmware, thus hiding the protocol details. In either case, the specs have much in common and makes sense to define the netlink msg as the union of the two specs. For example, both specs have a notition of associating/deassociating a port-profile. And both specs require some information from the hypervisor manager, such as client port instance ID. The general flow is the port-profile is applied to a host netdev interface using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the switch, and the switch virtual port backing the host netdev interface is configured/enabled based on the settings defined by the port-profile. What those settings comprise, and how those settings are managed is again outside the scope of this patch, since this patch only deals with the first step in the flow. Signed-off-by: Scott Feldman <scofeldm@cisco.com> Signed-off-by: Roopa Prabhu <roprabhu@cisco.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/if_link.h75
-rw-r--r--include/linux/netdevice.h8
-rw-r--r--net/core/rtnetlink.c169
3 files changed, 251 insertions, 1 deletions
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index c3af67fce3f2..85c812db5a3f 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -113,6 +113,8 @@ enum {
113 IFLA_NUM_VF, /* Number of VFs if device is SR-IOV PF */ 113 IFLA_NUM_VF, /* Number of VFs if device is SR-IOV PF */
114 IFLA_VFINFO_LIST, 114 IFLA_VFINFO_LIST,
115 IFLA_STATS64, 115 IFLA_STATS64,
116 IFLA_VF_PORTS,
117 IFLA_PORT_SELF,
116 __IFLA_MAX 118 __IFLA_MAX
117}; 119};
118 120
@@ -274,4 +276,77 @@ struct ifla_vf_info {
274 __u32 qos; 276 __u32 qos;
275 __u32 tx_rate; 277 __u32 tx_rate;
276}; 278};
279
280/* VF ports management section
281 *
282 * Nested layout of set/get msg is:
283 *
284 * [IFLA_NUM_VF]
285 * [IFLA_VF_PORTS]
286 * [IFLA_VF_PORT]
287 * [IFLA_PORT_*], ...
288 * [IFLA_VF_PORT]
289 * [IFLA_PORT_*], ...
290 * ...
291 * [IFLA_PORT_SELF]
292 * [IFLA_PORT_*], ...
293 */
294
295enum {
296 IFLA_VF_PORT_UNSPEC,
297 IFLA_VF_PORT, /* nest */
298 __IFLA_VF_PORT_MAX,
299};
300
301#define IFLA_VF_PORT_MAX (__IFLA_VF_PORT_MAX - 1)
302
303enum {
304 IFLA_PORT_UNSPEC,
305 IFLA_PORT_VF, /* __u32 */
306 IFLA_PORT_PROFILE, /* string */
307 IFLA_PORT_VSI_TYPE, /* 802.1Qbg (pre-)standard VDP */
308 IFLA_PORT_INSTANCE_UUID, /* binary UUID */
309 IFLA_PORT_HOST_UUID, /* binary UUID */
310 IFLA_PORT_REQUEST, /* __u8 */
311 IFLA_PORT_RESPONSE, /* __u16, output only */
312 __IFLA_PORT_MAX,
313};
314
315#define IFLA_PORT_MAX (__IFLA_PORT_MAX - 1)
316
317#define PORT_PROFILE_MAX 40
318#define PORT_UUID_MAX 16
319#define PORT_SELF_VF -1
320
321enum {
322 PORT_REQUEST_PREASSOCIATE = 0,
323 PORT_REQUEST_PREASSOCIATE_RR,
324 PORT_REQUEST_ASSOCIATE,
325 PORT_REQUEST_DISASSOCIATE,
326};
327
328enum {
329 PORT_VDP_RESPONSE_SUCCESS = 0,
330 PORT_VDP_RESPONSE_INVALID_FORMAT,
331 PORT_VDP_RESPONSE_INSUFFICIENT_RESOURCES,
332 PORT_VDP_RESPONSE_UNUSED_VTID,
333 PORT_VDP_RESPONSE_VTID_VIOLATION,
334 PORT_VDP_RESPONSE_VTID_VERSION_VIOALTION,
335 PORT_VDP_RESPONSE_OUT_OF_SYNC,
336 /* 0x08-0xFF reserved for future VDP use */
337 PORT_PROFILE_RESPONSE_SUCCESS = 0x100,
338 PORT_PROFILE_RESPONSE_INPROGRESS,
339 PORT_PROFILE_RESPONSE_INVALID,
340 PORT_PROFILE_RESPONSE_BADSTATE,
341 PORT_PROFILE_RESPONSE_INSUFFICIENT_RESOURCES,
342 PORT_PROFILE_RESPONSE_ERROR,
343};
344
345struct ifla_port_vsi {
346 __u8 vsi_mgr_id;
347 __u8 vsi_type_id[3];
348 __u8 vsi_type_version;
349 __u8 pad[3];
350};
351
277#endif /* _LINUX_IF_LINK_H */ 352#endif /* _LINUX_IF_LINK_H */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c1b2341897c2..c3487a6bdf99 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -686,6 +686,9 @@ struct netdev_rx_queue {
686 * int (*ndo_set_vf_tx_rate)(struct net_device *dev, int vf, int rate); 686 * int (*ndo_set_vf_tx_rate)(struct net_device *dev, int vf, int rate);
687 * int (*ndo_get_vf_config)(struct net_device *dev, 687 * int (*ndo_get_vf_config)(struct net_device *dev,
688 * int vf, struct ifla_vf_info *ivf); 688 * int vf, struct ifla_vf_info *ivf);
689 * int (*ndo_set_vf_port)(struct net_device *dev, int vf,
690 * struct nlattr *port[]);
691 * int (*ndo_get_vf_port)(struct net_device *dev, int vf, struct sk_buff *skb);
689 */ 692 */
690#define HAVE_NET_DEVICE_OPS 693#define HAVE_NET_DEVICE_OPS
691struct net_device_ops { 694struct net_device_ops {
@@ -735,6 +738,11 @@ struct net_device_ops {
735 int (*ndo_get_vf_config)(struct net_device *dev, 738 int (*ndo_get_vf_config)(struct net_device *dev,
736 int vf, 739 int vf,
737 struct ifla_vf_info *ivf); 740 struct ifla_vf_info *ivf);
741 int (*ndo_set_vf_port)(struct net_device *dev,
742 int vf,
743 struct nlattr *port[]);
744 int (*ndo_get_vf_port)(struct net_device *dev,
745 int vf, struct sk_buff *skb);
738#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) 746#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
739 int (*ndo_fcoe_enable)(struct net_device *dev); 747 int (*ndo_fcoe_enable)(struct net_device *dev);
740 int (*ndo_fcoe_disable)(struct net_device *dev); 748 int (*ndo_fcoe_disable)(struct net_device *dev);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 66db1201da9b..e4b9870e4706 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -660,6 +660,31 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev)
660 return 0; 660 return 0;
661} 661}
662 662
663static size_t rtnl_port_size(const struct net_device *dev)
664{
665 size_t port_size = nla_total_size(4) /* PORT_VF */
666 + nla_total_size(PORT_PROFILE_MAX) /* PORT_PROFILE */
667 + nla_total_size(sizeof(struct ifla_port_vsi))
668 /* PORT_VSI_TYPE */
669 + nla_total_size(PORT_UUID_MAX) /* PORT_INSTANCE_UUID */
670 + nla_total_size(PORT_UUID_MAX) /* PORT_HOST_UUID */
671 + nla_total_size(1) /* PROT_VDP_REQUEST */
672 + nla_total_size(2); /* PORT_VDP_RESPONSE */
673 size_t vf_ports_size = nla_total_size(sizeof(struct nlattr));
674 size_t vf_port_size = nla_total_size(sizeof(struct nlattr))
675 + port_size;
676 size_t port_self_size = nla_total_size(sizeof(struct nlattr))
677 + port_size;
678
679 if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent)
680 return 0;
681 if (dev_num_vf(dev->dev.parent))
682 return port_self_size + vf_ports_size +
683 vf_port_size * dev_num_vf(dev->dev.parent);
684 else
685 return port_self_size;
686}
687
663static inline size_t if_nlmsg_size(const struct net_device *dev) 688static inline size_t if_nlmsg_size(const struct net_device *dev)
664{ 689{
665 return NLMSG_ALIGN(sizeof(struct ifinfomsg)) 690 return NLMSG_ALIGN(sizeof(struct ifinfomsg))
@@ -680,9 +705,82 @@ static inline size_t if_nlmsg_size(const struct net_device *dev)
680 + nla_total_size(1) /* IFLA_LINKMODE */ 705 + nla_total_size(1) /* IFLA_LINKMODE */
681 + nla_total_size(4) /* IFLA_NUM_VF */ 706 + nla_total_size(4) /* IFLA_NUM_VF */
682 + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */ 707 + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */
708 + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
683 + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ 709 + rtnl_link_get_size(dev); /* IFLA_LINKINFO */
684} 710}
685 711
712static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev)
713{
714 struct nlattr *vf_ports;
715 struct nlattr *vf_port;
716 int vf;
717 int err;
718
719 vf_ports = nla_nest_start(skb, IFLA_VF_PORTS);
720 if (!vf_ports)
721 return -EMSGSIZE;
722
723 for (vf = 0; vf < dev_num_vf(dev->dev.parent); vf++) {
724 vf_port = nla_nest_start(skb, IFLA_VF_PORT);
725 if (!vf_port) {
726 nla_nest_cancel(skb, vf_ports);
727 return -EMSGSIZE;
728 }
729 NLA_PUT_U32(skb, IFLA_PORT_VF, vf);
730 err = dev->netdev_ops->ndo_get_vf_port(dev, vf, skb);
731 if (err) {
732nla_put_failure:
733 nla_nest_cancel(skb, vf_port);
734 continue;
735 }
736 nla_nest_end(skb, vf_port);
737 }
738
739 nla_nest_end(skb, vf_ports);
740
741 return 0;
742}
743
744static int rtnl_port_self_fill(struct sk_buff *skb, struct net_device *dev)
745{
746 struct nlattr *port_self;
747 int err;
748
749 port_self = nla_nest_start(skb, IFLA_PORT_SELF);
750 if (!port_self)
751 return -EMSGSIZE;
752
753 err = dev->netdev_ops->ndo_get_vf_port(dev, PORT_SELF_VF, skb);
754 if (err) {
755 nla_nest_cancel(skb, port_self);
756 return err;
757 }
758
759 nla_nest_end(skb, port_self);
760
761 return 0;
762}
763
764static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev)
765{
766 int err;
767
768 if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent)
769 return 0;
770
771 err = rtnl_port_self_fill(skb, dev);
772 if (err)
773 return err;
774
775 if (dev_num_vf(dev->dev.parent)) {
776 err = rtnl_vf_ports_fill(skb, dev);
777 if (err)
778 return err;
779 }
780
781 return 0;
782}
783
686static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, 784static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
687 int type, u32 pid, u32 seq, u32 change, 785 int type, u32 pid, u32 seq, u32 change,
688 unsigned int flags) 786 unsigned int flags)
@@ -754,13 +852,15 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
754 goto nla_put_failure; 852 goto nla_put_failure;
755 copy_rtnl_link_stats64(nla_data(attr), stats); 853 copy_rtnl_link_stats64(nla_data(attr), stats);
756 854
855 if (dev->dev.parent)
856 NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent));
857
757 if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { 858 if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) {
758 int i; 859 int i;
759 860
760 struct nlattr *vfinfo, *vf; 861 struct nlattr *vfinfo, *vf;
761 int num_vfs = dev_num_vf(dev->dev.parent); 862 int num_vfs = dev_num_vf(dev->dev.parent);
762 863
763 NLA_PUT_U32(skb, IFLA_NUM_VF, num_vfs);
764 vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST); 864 vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST);
765 if (!vfinfo) 865 if (!vfinfo)
766 goto nla_put_failure; 866 goto nla_put_failure;
@@ -788,6 +888,10 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
788 } 888 }
789 nla_nest_end(skb, vfinfo); 889 nla_nest_end(skb, vfinfo);
790 } 890 }
891
892 if (rtnl_port_fill(skb, dev))
893 goto nla_put_failure;
894
791 if (dev->rtnl_link_ops) { 895 if (dev->rtnl_link_ops) {
792 if (rtnl_link_fill(skb, dev) < 0) 896 if (rtnl_link_fill(skb, dev) < 0)
793 goto nla_put_failure; 897 goto nla_put_failure;
@@ -849,6 +953,8 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
849 [IFLA_NET_NS_PID] = { .type = NLA_U32 }, 953 [IFLA_NET_NS_PID] = { .type = NLA_U32 },
850 [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, 954 [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 },
851 [IFLA_VFINFO_LIST] = {. type = NLA_NESTED }, 955 [IFLA_VFINFO_LIST] = {. type = NLA_NESTED },
956 [IFLA_VF_PORTS] = { .type = NLA_NESTED },
957 [IFLA_PORT_SELF] = { .type = NLA_NESTED },
852}; 958};
853EXPORT_SYMBOL(ifla_policy); 959EXPORT_SYMBOL(ifla_policy);
854 960
@@ -870,6 +976,20 @@ static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
870 .len = sizeof(struct ifla_vf_tx_rate) }, 976 .len = sizeof(struct ifla_vf_tx_rate) },
871}; 977};
872 978
979static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = {
980 [IFLA_PORT_VF] = { .type = NLA_U32 },
981 [IFLA_PORT_PROFILE] = { .type = NLA_STRING,
982 .len = PORT_PROFILE_MAX },
983 [IFLA_PORT_VSI_TYPE] = { .type = NLA_BINARY,
984 .len = sizeof(struct ifla_port_vsi)},
985 [IFLA_PORT_INSTANCE_UUID] = { .type = NLA_BINARY,
986 .len = PORT_UUID_MAX },
987 [IFLA_PORT_HOST_UUID] = { .type = NLA_STRING,
988 .len = PORT_UUID_MAX },
989 [IFLA_PORT_REQUEST] = { .type = NLA_U8, },
990 [IFLA_PORT_RESPONSE] = { .type = NLA_U16, },
991};
992
873struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) 993struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
874{ 994{
875 struct net *net; 995 struct net *net;
@@ -1089,6 +1209,53 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
1089 } 1209 }
1090 err = 0; 1210 err = 0;
1091 1211
1212 if (tb[IFLA_VF_PORTS]) {
1213 struct nlattr *port[IFLA_PORT_MAX+1];
1214 struct nlattr *attr;
1215 int vf;
1216 int rem;
1217
1218 err = -EOPNOTSUPP;
1219 if (!ops->ndo_set_vf_port)
1220 goto errout;
1221
1222 nla_for_each_nested(attr, tb[IFLA_VF_PORTS], rem) {
1223 if (nla_type(attr) != IFLA_VF_PORT)
1224 continue;
1225 err = nla_parse_nested(port, IFLA_PORT_MAX,
1226 attr, ifla_port_policy);
1227 if (err < 0)
1228 goto errout;
1229 if (!port[IFLA_PORT_VF]) {
1230 err = -EOPNOTSUPP;
1231 goto errout;
1232 }
1233 vf = nla_get_u32(port[IFLA_PORT_VF]);
1234 err = ops->ndo_set_vf_port(dev, vf, port);
1235 if (err < 0)
1236 goto errout;
1237 modified = 1;
1238 }
1239 }
1240 err = 0;
1241
1242 if (tb[IFLA_PORT_SELF]) {
1243 struct nlattr *port[IFLA_PORT_MAX+1];
1244
1245 err = nla_parse_nested(port, IFLA_PORT_MAX,
1246 tb[IFLA_PORT_SELF], ifla_port_policy);
1247 if (err < 0)
1248 goto errout;
1249
1250 err = -EOPNOTSUPP;
1251 if (ops->ndo_set_vf_port)
1252 err = ops->ndo_set_vf_port(dev, PORT_SELF_VF, port);
1253 if (err < 0)
1254 goto errout;
1255 modified = 1;
1256 }
1257 err = 0;
1258
1092errout: 1259errout:
1093 if (err < 0 && modified && net_ratelimit()) 1260 if (err < 0 && modified && net_ratelimit())
1094 printk(KERN_WARNING "A link change request failed with " 1261 printk(KERN_WARNING "A link change request failed with "