diff options
author | Scott Feldman <scofeldm@cisco.com> | 2010-06-01 04:59:33 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-02 05:26:40 -0400 |
commit | 08f382ebb8a9efb898840aa74cf55148c7a98af6 (patch) | |
tree | 2486b90342f17a8f5a1bf8feb1a219143b83da48 /drivers | |
parent | f048fa9c8686119c3858a463cab6121dced7c0bf (diff) |
enic: bug fix: make the set/get netlink VF_PORT support symmetrical
To make get/set netlink VF_PORT truly symmetrical, we need to keep track
of what items are set and only return those items on get. Previously, the
driver wasn't differentiating between a set of attr with a NULL string,
for example, and not setting the attr at all. We only want to return
the NULL string if the attr was actually set with a NULL string. Otherwise,
don't return the attr.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/enic/enic.h | 7 | ||||
-rw-r--r-- | drivers/net/enic/enic_main.c | 200 |
2 files changed, 104 insertions, 103 deletions
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index 85f2a2e7030a..45e86d1e5b1b 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h | |||
@@ -74,7 +74,14 @@ struct enic_msix_entry { | |||
74 | void *devid; | 74 | void *devid; |
75 | }; | 75 | }; |
76 | 76 | ||
77 | #define ENIC_SET_APPLIED (1 << 0) | ||
78 | #define ENIC_SET_REQUEST (1 << 1) | ||
79 | #define ENIC_SET_NAME (1 << 2) | ||
80 | #define ENIC_SET_INSTANCE (1 << 3) | ||
81 | #define ENIC_SET_HOST (1 << 4) | ||
82 | |||
77 | struct enic_port_profile { | 83 | struct enic_port_profile { |
84 | u32 set; | ||
78 | u8 request; | 85 | u8 request; |
79 | char name[PORT_PROFILE_MAX]; | 86 | char name[PORT_PROFILE_MAX]; |
80 | u8 instance_uuid[PORT_UUID_MAX]; | 87 | u8 instance_uuid[PORT_UUID_MAX]; |
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 6586b5c7e4b6..bc7d6b96de3d 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c | |||
@@ -1029,8 +1029,7 @@ static int enic_dev_init_done(struct enic *enic, int *done, int *error) | |||
1029 | return err; | 1029 | return err; |
1030 | } | 1030 | } |
1031 | 1031 | ||
1032 | static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac, | 1032 | static int enic_set_port_profile(struct enic *enic, u8 *mac) |
1033 | char *name, u8 *instance_uuid, u8 *host_uuid) | ||
1034 | { | 1033 | { |
1035 | struct vic_provinfo *vp; | 1034 | struct vic_provinfo *vp; |
1036 | u8 oui[3] = VIC_PROVINFO_CISCO_OUI; | 1035 | u8 oui[3] = VIC_PROVINFO_CISCO_OUI; |
@@ -1040,97 +1039,112 @@ static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac, | |||
1040 | "%02X%02X-%02X%02X%02X%02X%0X%02X"; | 1039 | "%02X%02X-%02X%02X%02X%02X%0X%02X"; |
1041 | int err; | 1040 | int err; |
1042 | 1041 | ||
1043 | if (!name) | 1042 | err = enic_vnic_dev_deinit(enic); |
1044 | return -EINVAL; | 1043 | if (err) |
1044 | return err; | ||
1045 | 1045 | ||
1046 | if (!is_valid_ether_addr(mac)) | 1046 | switch (enic->pp.request) { |
1047 | return -EADDRNOTAVAIL; | ||
1048 | 1047 | ||
1049 | vp = vic_provinfo_alloc(GFP_KERNEL, oui, VIC_PROVINFO_LINUX_TYPE); | 1048 | case PORT_REQUEST_ASSOCIATE: |
1050 | if (!vp) | ||
1051 | return -ENOMEM; | ||
1052 | 1049 | ||
1053 | vic_provinfo_add_tlv(vp, | 1050 | if (!(enic->pp.set & ENIC_SET_NAME) || !strlen(enic->pp.name)) |
1054 | VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR, | 1051 | return -EINVAL; |
1055 | strlen(name) + 1, name); | ||
1056 | |||
1057 | vic_provinfo_add_tlv(vp, | ||
1058 | VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR, | ||
1059 | ETH_ALEN, mac); | ||
1060 | |||
1061 | if (instance_uuid) { | ||
1062 | uuid = instance_uuid; | ||
1063 | sprintf(uuid_str, uuid_fmt, | ||
1064 | uuid[0], uuid[1], uuid[2], uuid[3], | ||
1065 | uuid[4], uuid[5], uuid[6], uuid[7], | ||
1066 | uuid[8], uuid[9], uuid[10], uuid[11], | ||
1067 | uuid[12], uuid[13], uuid[14], uuid[15]); | ||
1068 | vic_provinfo_add_tlv(vp, | ||
1069 | VIC_LINUX_PROV_TLV_CLIENT_UUID_STR, | ||
1070 | sizeof(uuid_str), uuid_str); | ||
1071 | } | ||
1072 | 1052 | ||
1073 | if (host_uuid) { | 1053 | if (!is_valid_ether_addr(mac)) |
1074 | uuid = host_uuid; | 1054 | return -EADDRNOTAVAIL; |
1075 | sprintf(uuid_str, uuid_fmt, | ||
1076 | uuid[0], uuid[1], uuid[2], uuid[3], | ||
1077 | uuid[4], uuid[5], uuid[6], uuid[7], | ||
1078 | uuid[8], uuid[9], uuid[10], uuid[11], | ||
1079 | uuid[12], uuid[13], uuid[14], uuid[15]); | ||
1080 | vic_provinfo_add_tlv(vp, | ||
1081 | VIC_LINUX_PROV_TLV_HOST_UUID_STR, | ||
1082 | sizeof(uuid_str), uuid_str); | ||
1083 | } | ||
1084 | 1055 | ||
1085 | err = enic_vnic_dev_deinit(enic); | 1056 | vp = vic_provinfo_alloc(GFP_KERNEL, oui, |
1086 | if (err) | 1057 | VIC_PROVINFO_LINUX_TYPE); |
1087 | goto err_out; | 1058 | if (!vp) |
1059 | return -ENOMEM; | ||
1088 | 1060 | ||
1089 | memset(&enic->pp, 0, sizeof(enic->pp)); | 1061 | vic_provinfo_add_tlv(vp, |
1062 | VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR, | ||
1063 | strlen(enic->pp.name) + 1, enic->pp.name); | ||
1090 | 1064 | ||
1091 | err = enic_dev_init_prov(enic, vp); | 1065 | vic_provinfo_add_tlv(vp, |
1092 | if (err) | 1066 | VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR, |
1093 | goto err_out; | 1067 | ETH_ALEN, mac); |
1068 | |||
1069 | if (enic->pp.set & ENIC_SET_INSTANCE) { | ||
1070 | uuid = enic->pp.instance_uuid; | ||
1071 | sprintf(uuid_str, uuid_fmt, | ||
1072 | uuid[0], uuid[1], uuid[2], uuid[3], | ||
1073 | uuid[4], uuid[5], uuid[6], uuid[7], | ||
1074 | uuid[8], uuid[9], uuid[10], uuid[11], | ||
1075 | uuid[12], uuid[13], uuid[14], uuid[15]); | ||
1076 | vic_provinfo_add_tlv(vp, | ||
1077 | VIC_LINUX_PROV_TLV_CLIENT_UUID_STR, | ||
1078 | sizeof(uuid_str), uuid_str); | ||
1079 | } | ||
1094 | 1080 | ||
1095 | enic->pp.request = request; | 1081 | if (enic->pp.set & ENIC_SET_HOST) { |
1096 | memcpy(enic->pp.name, name, PORT_PROFILE_MAX); | 1082 | uuid = enic->pp.host_uuid; |
1097 | if (instance_uuid) | 1083 | sprintf(uuid_str, uuid_fmt, |
1098 | memcpy(enic->pp.instance_uuid, | 1084 | uuid[0], uuid[1], uuid[2], uuid[3], |
1099 | instance_uuid, PORT_UUID_MAX); | 1085 | uuid[4], uuid[5], uuid[6], uuid[7], |
1100 | if (host_uuid) | 1086 | uuid[8], uuid[9], uuid[10], uuid[11], |
1101 | memcpy(enic->pp.host_uuid, | 1087 | uuid[12], uuid[13], uuid[14], uuid[15]); |
1102 | host_uuid, PORT_UUID_MAX); | 1088 | vic_provinfo_add_tlv(vp, |
1089 | VIC_LINUX_PROV_TLV_HOST_UUID_STR, | ||
1090 | sizeof(uuid_str), uuid_str); | ||
1091 | } | ||
1103 | 1092 | ||
1104 | err_out: | 1093 | err = enic_dev_init_prov(enic, vp); |
1105 | vic_provinfo_free(vp); | 1094 | vic_provinfo_free(vp); |
1095 | if (err) | ||
1096 | return err; | ||
1097 | break; | ||
1106 | 1098 | ||
1107 | return err; | 1099 | case PORT_REQUEST_DISASSOCIATE: |
1108 | } | 1100 | break; |
1109 | 1101 | ||
1110 | static int enic_unset_port_profile(struct enic *enic) | 1102 | default: |
1111 | { | 1103 | return -EINVAL; |
1112 | memset(&enic->pp, 0, sizeof(enic->pp)); | 1104 | } |
1113 | return enic_vnic_dev_deinit(enic); | 1105 | |
1106 | enic->pp.set |= ENIC_SET_APPLIED; | ||
1107 | return 0; | ||
1114 | } | 1108 | } |
1115 | 1109 | ||
1116 | static int enic_set_vf_port(struct net_device *netdev, int vf, | 1110 | static int enic_set_vf_port(struct net_device *netdev, int vf, |
1117 | struct nlattr *port[]) | 1111 | struct nlattr *port[]) |
1118 | { | 1112 | { |
1119 | struct enic *enic = netdev_priv(netdev); | 1113 | struct enic *enic = netdev_priv(netdev); |
1120 | char *name = NULL; | 1114 | |
1121 | u8 *instance_uuid = NULL; | 1115 | memset(&enic->pp, 0, sizeof(enic->pp)); |
1122 | u8 *host_uuid = NULL; | 1116 | |
1123 | u8 request = PORT_REQUEST_DISASSOCIATE; | 1117 | if (port[IFLA_PORT_REQUEST]) { |
1118 | enic->pp.set |= ENIC_SET_REQUEST; | ||
1119 | enic->pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]); | ||
1120 | } | ||
1121 | |||
1122 | if (port[IFLA_PORT_PROFILE]) { | ||
1123 | enic->pp.set |= ENIC_SET_NAME; | ||
1124 | memcpy(enic->pp.name, nla_data(port[IFLA_PORT_PROFILE]), | ||
1125 | PORT_PROFILE_MAX); | ||
1126 | } | ||
1127 | |||
1128 | if (port[IFLA_PORT_INSTANCE_UUID]) { | ||
1129 | enic->pp.set |= ENIC_SET_INSTANCE; | ||
1130 | memcpy(enic->pp.instance_uuid, | ||
1131 | nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX); | ||
1132 | } | ||
1133 | |||
1134 | if (port[IFLA_PORT_HOST_UUID]) { | ||
1135 | enic->pp.set |= ENIC_SET_HOST; | ||
1136 | memcpy(enic->pp.host_uuid, | ||
1137 | nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX); | ||
1138 | } | ||
1124 | 1139 | ||
1125 | /* don't support VFs, yet */ | 1140 | /* don't support VFs, yet */ |
1126 | if (vf != PORT_SELF_VF) | 1141 | if (vf != PORT_SELF_VF) |
1127 | return -EOPNOTSUPP; | 1142 | return -EOPNOTSUPP; |
1128 | 1143 | ||
1129 | if (port[IFLA_PORT_REQUEST]) | 1144 | if (!(enic->pp.set & ENIC_SET_REQUEST)) |
1130 | request = nla_get_u8(port[IFLA_PORT_REQUEST]); | 1145 | return -EOPNOTSUPP; |
1131 | 1146 | ||
1132 | switch (request) { | 1147 | if (enic->pp.request == PORT_REQUEST_ASSOCIATE) { |
1133 | case PORT_REQUEST_ASSOCIATE: | ||
1134 | 1148 | ||
1135 | /* If the interface mac addr hasn't been assigned, | 1149 | /* If the interface mac addr hasn't been assigned, |
1136 | * assign a random mac addr before setting port- | 1150 | * assign a random mac addr before setting port- |
@@ -1139,30 +1153,9 @@ static int enic_set_vf_port(struct net_device *netdev, int vf, | |||
1139 | 1153 | ||
1140 | if (is_zero_ether_addr(netdev->dev_addr)) | 1154 | if (is_zero_ether_addr(netdev->dev_addr)) |
1141 | random_ether_addr(netdev->dev_addr); | 1155 | random_ether_addr(netdev->dev_addr); |
1142 | |||
1143 | if (port[IFLA_PORT_PROFILE]) | ||
1144 | name = nla_data(port[IFLA_PORT_PROFILE]); | ||
1145 | |||
1146 | if (port[IFLA_PORT_INSTANCE_UUID]) | ||
1147 | instance_uuid = | ||
1148 | nla_data(port[IFLA_PORT_INSTANCE_UUID]); | ||
1149 | |||
1150 | if (port[IFLA_PORT_HOST_UUID]) | ||
1151 | host_uuid = nla_data(port[IFLA_PORT_HOST_UUID]); | ||
1152 | |||
1153 | return enic_set_port_profile(enic, request, | ||
1154 | netdev->dev_addr, name, | ||
1155 | instance_uuid, host_uuid); | ||
1156 | |||
1157 | case PORT_REQUEST_DISASSOCIATE: | ||
1158 | |||
1159 | return enic_unset_port_profile(enic); | ||
1160 | |||
1161 | default: | ||
1162 | break; | ||
1163 | } | 1156 | } |
1164 | 1157 | ||
1165 | return -EOPNOTSUPP; | 1158 | return enic_set_port_profile(enic, netdev->dev_addr); |
1166 | } | 1159 | } |
1167 | 1160 | ||
1168 | static int enic_get_vf_port(struct net_device *netdev, int vf, | 1161 | static int enic_get_vf_port(struct net_device *netdev, int vf, |
@@ -1172,14 +1165,12 @@ static int enic_get_vf_port(struct net_device *netdev, int vf, | |||
1172 | int err, error, done; | 1165 | int err, error, done; |
1173 | u16 response = PORT_PROFILE_RESPONSE_SUCCESS; | 1166 | u16 response = PORT_PROFILE_RESPONSE_SUCCESS; |
1174 | 1167 | ||
1175 | /* don't support VFs, yet */ | 1168 | if (!(enic->pp.set & ENIC_SET_APPLIED)) |
1176 | if (vf != PORT_SELF_VF) | 1169 | return -ENODATA; |
1177 | return -EOPNOTSUPP; | ||
1178 | 1170 | ||
1179 | err = enic_dev_init_done(enic, &done, &error); | 1171 | err = enic_dev_init_done(enic, &done, &error); |
1180 | |||
1181 | if (err) | 1172 | if (err) |
1182 | return err; | 1173 | error = err; |
1183 | 1174 | ||
1184 | switch (error) { | 1175 | switch (error) { |
1185 | case ERR_SUCCESS: | 1176 | case ERR_SUCCESS: |
@@ -1202,12 +1193,15 @@ static int enic_get_vf_port(struct net_device *netdev, int vf, | |||
1202 | 1193 | ||
1203 | NLA_PUT_U16(skb, IFLA_PORT_REQUEST, enic->pp.request); | 1194 | NLA_PUT_U16(skb, IFLA_PORT_REQUEST, enic->pp.request); |
1204 | NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response); | 1195 | NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response); |
1205 | NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX, | 1196 | if (enic->pp.set & ENIC_SET_NAME) |
1206 | enic->pp.name); | 1197 | NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX, |
1207 | NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX, | 1198 | enic->pp.name); |
1208 | enic->pp.instance_uuid); | 1199 | if (enic->pp.set & ENIC_SET_INSTANCE) |
1209 | NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX, | 1200 | NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX, |
1210 | enic->pp.host_uuid); | 1201 | enic->pp.instance_uuid); |
1202 | if (enic->pp.set & ENIC_SET_HOST) | ||
1203 | NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX, | ||
1204 | enic->pp.host_uuid); | ||
1211 | 1205 | ||
1212 | return 0; | 1206 | return 0; |
1213 | 1207 | ||