aboutsummaryrefslogtreecommitdiffstats
path: root/net/dcb/dcbnl.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dcb/dcbnl.c')
-rw-r--r--net/dcb/dcbnl.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 19ac2b985485..2ff908498924 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -66,6 +66,7 @@ static const struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = {
66 [DCB_ATTR_PFC_STATE] = {.type = NLA_U8}, 66 [DCB_ATTR_PFC_STATE] = {.type = NLA_U8},
67 [DCB_ATTR_BCN] = {.type = NLA_NESTED}, 67 [DCB_ATTR_BCN] = {.type = NLA_NESTED},
68 [DCB_ATTR_APP] = {.type = NLA_NESTED}, 68 [DCB_ATTR_APP] = {.type = NLA_NESTED},
69 [DCB_ATTR_IEEE] = {.type = NLA_NESTED},
69}; 70};
70 71
71/* DCB priority flow control to User Priority nested attributes */ 72/* DCB priority flow control to User Priority nested attributes */
@@ -167,6 +168,17 @@ static const struct nla_policy dcbnl_app_nest[DCB_APP_ATTR_MAX + 1] = {
167 [DCB_APP_ATTR_PRIORITY] = {.type = NLA_U8}, 168 [DCB_APP_ATTR_PRIORITY] = {.type = NLA_U8},
168}; 169};
169 170
171/* IEEE 802.1Qaz nested attributes. */
172static const struct nla_policy dcbnl_ieee_policy[DCB_ATTR_IEEE_MAX + 1] = {
173 [DCB_ATTR_IEEE_ETS] = {.len = sizeof(struct ieee_ets)},
174 [DCB_ATTR_IEEE_PFC] = {.len = sizeof(struct ieee_pfc)},
175 [DCB_ATTR_IEEE_APP_TABLE] = {.type = NLA_NESTED},
176};
177
178static const struct nla_policy dcbnl_ieee_app[DCB_ATTR_IEEE_APP_MAX + 1] = {
179 [DCB_ATTR_IEEE_APP] = {.len = sizeof(struct dcb_app)},
180};
181
170/* standard netlink reply call */ 182/* standard netlink reply call */
171static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, 183static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
172 u32 seq, u16 flags) 184 u32 seq, u16 flags)
@@ -1118,6 +1130,117 @@ err:
1118 return ret; 1130 return ret;
1119} 1131}
1120 1132
1133/* Handle IEEE 802.1Qaz SET commands. If any requested operation can not
1134 * be completed the entire msg is aborted and error value is returned.
1135 * No attempt is made to reconcile the case where only part of the
1136 * cmd can be completed.
1137 */
1138static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb,
1139 u32 pid, u32 seq, u16 flags)
1140{
1141 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1142 struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
1143 int err = -EOPNOTSUPP;
1144
1145 if (!ops)
1146 goto err;
1147
1148 err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
1149 tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
1150 if (err)
1151 goto err;
1152
1153 if (ieee[DCB_ATTR_IEEE_ETS] && ops->ieee_setets) {
1154 struct ieee_ets *ets = nla_data(ieee[DCB_ATTR_IEEE_ETS]);
1155 err = ops->ieee_setets(netdev, ets);
1156 if (err)
1157 goto err;
1158 }
1159
1160 if (ieee[DCB_ATTR_IEEE_PFC] && ops->ieee_setets) {
1161 struct ieee_pfc *pfc = nla_data(ieee[DCB_ATTR_IEEE_PFC]);
1162 err = ops->ieee_setpfc(netdev, pfc);
1163 if (err)
1164 goto err;
1165 }
1166
1167 if (ieee[DCB_ATTR_IEEE_APP_TABLE] && ops->ieee_setapp) {
1168 struct nlattr *attr;
1169 int rem;
1170
1171 nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
1172 struct dcb_app *app_data;
1173 if (nla_type(attr) != DCB_ATTR_IEEE_APP)
1174 continue;
1175 app_data = nla_data(attr);
1176 err = ops->ieee_setapp(netdev, app_data);
1177 if (err)
1178 goto err;
1179 }
1180 }
1181
1182err:
1183 dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE,
1184 pid, seq, flags);
1185 return err;
1186}
1187
1188
1189/* Handle IEEE 802.1Qaz GET commands. */
1190static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
1191 u32 pid, u32 seq, u16 flags)
1192{
1193 struct sk_buff *skb;
1194 struct nlmsghdr *nlh;
1195 struct dcbmsg *dcb;
1196 struct nlattr *ieee;
1197 const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
1198 int err;
1199
1200 if (!ops)
1201 return -EOPNOTSUPP;
1202
1203 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1204 if (!skb)
1205 return -ENOBUFS;
1206
1207 nlh = NLMSG_NEW(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
1208
1209 dcb = NLMSG_DATA(nlh);
1210 dcb->dcb_family = AF_UNSPEC;
1211 dcb->cmd = DCB_CMD_IEEE_GET;
1212
1213 NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name);
1214
1215 ieee = nla_nest_start(skb, DCB_ATTR_IEEE);
1216 if (!ieee)
1217 goto nla_put_failure;
1218
1219 if (ops->ieee_getets) {
1220 struct ieee_ets ets;
1221 err = ops->ieee_getets(netdev, &ets);
1222 if (!err)
1223 NLA_PUT(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets);
1224 }
1225
1226 if (ops->ieee_getpfc) {
1227 struct ieee_pfc pfc;
1228 err = ops->ieee_getpfc(netdev, &pfc);
1229 if (!err)
1230 NLA_PUT(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc);
1231 }
1232
1233 nla_nest_end(skb, ieee);
1234 nlmsg_end(skb, nlh);
1235
1236 return rtnl_unicast(skb, &init_net, pid);
1237nla_put_failure:
1238 nlmsg_cancel(skb, nlh);
1239nlmsg_failure:
1240 kfree_skb(skb);
1241 return -1;
1242}
1243
1121static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 1244static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1122{ 1245{
1123 struct net *net = sock_net(skb->sk); 1246 struct net *net = sock_net(skb->sk);
@@ -1223,6 +1346,14 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1223 ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq, 1346 ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq,
1224 nlh->nlmsg_flags); 1347 nlh->nlmsg_flags);
1225 goto out; 1348 goto out;
1349 case DCB_CMD_IEEE_SET:
1350 ret = dcbnl_ieee_set(netdev, tb, pid, nlh->nlmsg_seq,
1351 nlh->nlmsg_flags);
1352 goto out;
1353 case DCB_CMD_IEEE_GET:
1354 ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq,
1355 nlh->nlmsg_flags);
1356 goto out;
1226 default: 1357 default:
1227 goto errout; 1358 goto errout;
1228 } 1359 }