diff options
-rw-r--r-- | include/linux/dcbnl.h | 106 | ||||
-rw-r--r-- | include/net/dcbnl.h | 11 | ||||
-rw-r--r-- | net/dcb/dcbnl.c | 131 |
3 files changed, 248 insertions, 0 deletions
diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h index 8723491f7dfd..287b5618e296 100644 --- a/include/linux/dcbnl.h +++ b/include/linux/dcbnl.h | |||
@@ -22,6 +22,87 @@ | |||
22 | 22 | ||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | 24 | ||
25 | /* IEEE 802.1Qaz std supported values */ | ||
26 | #define IEEE_8021QAZ_MAX_TCS 8 | ||
27 | |||
28 | /* This structure contains the IEEE 802.1Qaz ETS managed object | ||
29 | * | ||
30 | * @willing: willing bit in ETS configuratin TLV | ||
31 | * @ets_cap: indicates supported capacity of ets feature | ||
32 | * @cbs: credit based shaper ets algorithm supported | ||
33 | * @tc_tx_bw: tc tx bandwidth indexed by traffic class | ||
34 | * @tc_rx_bw: tc rx bandwidth indexed by traffic class | ||
35 | * @tc_tsa: TSA Assignment table, indexed by traffic class | ||
36 | * @prio_tc: priority assignment table mapping 8021Qp to traffic class | ||
37 | * @tc_reco_bw: recommended tc bandwidth indexed by traffic class for TLV | ||
38 | * @tc_reco_tsa: recommended tc bandwidth indexed by traffic class for TLV | ||
39 | * @reco_prio_tc: recommended tc tx bandwidth indexed by traffic class for TLV | ||
40 | * | ||
41 | * Recommended values are used to set fields in the ETS recommendation TLV | ||
42 | * with hardware offloaded LLDP. | ||
43 | * | ||
44 | * ---- | ||
45 | * TSA Assignment 8 bit identifiers | ||
46 | * 0 strict priority | ||
47 | * 1 credit-based shaper | ||
48 | * 2 enhanced transmission selection | ||
49 | * 3-254 reserved | ||
50 | * 255 vendor specific | ||
51 | */ | ||
52 | struct ieee_ets { | ||
53 | __u8 willing; | ||
54 | __u8 ets_cap; | ||
55 | __u8 cbs; | ||
56 | __u8 tc_tx_bw[IEEE_8021QAZ_MAX_TCS]; | ||
57 | __u8 tc_rx_bw[IEEE_8021QAZ_MAX_TCS]; | ||
58 | __u8 tc_tsa[IEEE_8021QAZ_MAX_TCS]; | ||
59 | __u8 prio_tc[IEEE_8021QAZ_MAX_TCS]; | ||
60 | __u8 tc_reco_bw[IEEE_8021QAZ_MAX_TCS]; | ||
61 | __u8 tc_reco_tsa[IEEE_8021QAZ_MAX_TCS]; | ||
62 | __u8 reco_prio_tc[IEEE_8021QAZ_MAX_TCS]; | ||
63 | }; | ||
64 | |||
65 | /* This structure contains the IEEE 802.1Qaz PFC managed object | ||
66 | * | ||
67 | * @pfc_cap: Indicates the number of traffic classes on the local device | ||
68 | * that may simultaneously have PFC enabled. | ||
69 | * @pfc_en: bitmap indicating pfc enabled traffic classes | ||
70 | * @mbc: enable macsec bypass capability | ||
71 | * @delay: the allowance made for a round-trip propagation delay of the | ||
72 | * link in bits. | ||
73 | * @requests: count of the sent pfc frames | ||
74 | * @indications: count of the received pfc frames | ||
75 | */ | ||
76 | struct ieee_pfc { | ||
77 | __u8 pfc_cap; | ||
78 | __u8 pfc_en; | ||
79 | __u8 mbc; | ||
80 | __u16 delay; | ||
81 | __u64 requests[IEEE_8021QAZ_MAX_TCS]; | ||
82 | __u64 indications[IEEE_8021QAZ_MAX_TCS]; | ||
83 | }; | ||
84 | |||
85 | /* This structure contains the IEEE 802.1Qaz APP managed object | ||
86 | * | ||
87 | * @selector: protocol identifier type | ||
88 | * @protocol: protocol of type indicated | ||
89 | * @priority: 3-bit unsigned integer indicating priority | ||
90 | * | ||
91 | * ---- | ||
92 | * Selector field values | ||
93 | * 0 Reserved | ||
94 | * 1 Ethertype | ||
95 | * 2 Well known port number over TCP or SCTP | ||
96 | * 3 Well known port number over UDP or DCCP | ||
97 | * 4 Well known port number over TCP, SCTP, UDP, or DCCP | ||
98 | * 5-7 Reserved | ||
99 | */ | ||
100 | struct dcb_app { | ||
101 | __u8 selector; | ||
102 | __u32 protocol; | ||
103 | __u8 priority; | ||
104 | }; | ||
105 | |||
25 | struct dcbmsg { | 106 | struct dcbmsg { |
26 | __u8 dcb_family; | 107 | __u8 dcb_family; |
27 | __u8 cmd; | 108 | __u8 cmd; |
@@ -50,6 +131,8 @@ struct dcbmsg { | |||
50 | * @DCB_CMD_SBCN: get backward congestion notification configration. | 131 | * @DCB_CMD_SBCN: get backward congestion notification configration. |
51 | * @DCB_CMD_GAPP: get application protocol configuration | 132 | * @DCB_CMD_GAPP: get application protocol configuration |
52 | * @DCB_CMD_SAPP: set application protocol configuration | 133 | * @DCB_CMD_SAPP: set application protocol configuration |
134 | * @DCB_CMD_IEEE_SET: set IEEE 802.1Qaz configuration | ||
135 | * @DCB_CMD_IEEE_GET: get IEEE 802.1Qaz configuration | ||
53 | */ | 136 | */ |
54 | enum dcbnl_commands { | 137 | enum dcbnl_commands { |
55 | DCB_CMD_UNDEFINED, | 138 | DCB_CMD_UNDEFINED, |
@@ -83,6 +166,9 @@ enum dcbnl_commands { | |||
83 | DCB_CMD_GAPP, | 166 | DCB_CMD_GAPP, |
84 | DCB_CMD_SAPP, | 167 | DCB_CMD_SAPP, |
85 | 168 | ||
169 | DCB_CMD_IEEE_SET, | ||
170 | DCB_CMD_IEEE_GET, | ||
171 | |||
86 | __DCB_CMD_ENUM_MAX, | 172 | __DCB_CMD_ENUM_MAX, |
87 | DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, | 173 | DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, |
88 | }; | 174 | }; |
@@ -102,6 +188,7 @@ enum dcbnl_commands { | |||
102 | * @DCB_ATTR_CAP: DCB capabilities of the device (NLA_NESTED) | 188 | * @DCB_ATTR_CAP: DCB capabilities of the device (NLA_NESTED) |
103 | * @DCB_ATTR_NUMTCS: number of traffic classes supported (NLA_NESTED) | 189 | * @DCB_ATTR_NUMTCS: number of traffic classes supported (NLA_NESTED) |
104 | * @DCB_ATTR_BCN: backward congestion notification configuration (NLA_NESTED) | 190 | * @DCB_ATTR_BCN: backward congestion notification configuration (NLA_NESTED) |
191 | * @DCB_ATTR_IEEE: IEEE 802.1Qaz supported attributes (NLA_NESTED) | ||
105 | */ | 192 | */ |
106 | enum dcbnl_attrs { | 193 | enum dcbnl_attrs { |
107 | DCB_ATTR_UNDEFINED, | 194 | DCB_ATTR_UNDEFINED, |
@@ -119,10 +206,29 @@ enum dcbnl_attrs { | |||
119 | DCB_ATTR_BCN, | 206 | DCB_ATTR_BCN, |
120 | DCB_ATTR_APP, | 207 | DCB_ATTR_APP, |
121 | 208 | ||
209 | /* IEEE std attributes */ | ||
210 | DCB_ATTR_IEEE, | ||
211 | |||
122 | __DCB_ATTR_ENUM_MAX, | 212 | __DCB_ATTR_ENUM_MAX, |
123 | DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, | 213 | DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, |
124 | }; | 214 | }; |
125 | 215 | ||
216 | enum ieee_attrs { | ||
217 | DCB_ATTR_IEEE_UNSPEC, | ||
218 | DCB_ATTR_IEEE_ETS, | ||
219 | DCB_ATTR_IEEE_PFC, | ||
220 | DCB_ATTR_IEEE_APP_TABLE, | ||
221 | __DCB_ATTR_IEEE_MAX | ||
222 | }; | ||
223 | #define DCB_ATTR_IEEE_MAX (__DCB_ATTR_IEEE_MAX - 1) | ||
224 | |||
225 | enum ieee_attrs_app { | ||
226 | DCB_ATTR_IEEE_APP_UNSPEC, | ||
227 | DCB_ATTR_IEEE_APP, | ||
228 | __DCB_ATTR_IEEE_APP_MAX | ||
229 | }; | ||
230 | #define DCB_ATTR_IEEE_APP_MAX (__DCB_ATTR_IEEE_APP_MAX - 1) | ||
231 | |||
126 | /** | 232 | /** |
127 | * enum dcbnl_pfc_attrs - DCB Priority Flow Control user priority nested attrs | 233 | * enum dcbnl_pfc_attrs - DCB Priority Flow Control user priority nested attrs |
128 | * | 234 | * |
diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h index b36ac7e0914d..e2d841e963b3 100644 --- a/include/net/dcbnl.h +++ b/include/net/dcbnl.h | |||
@@ -20,11 +20,22 @@ | |||
20 | #ifndef __NET_DCBNL_H__ | 20 | #ifndef __NET_DCBNL_H__ |
21 | #define __NET_DCBNL_H__ | 21 | #define __NET_DCBNL_H__ |
22 | 22 | ||
23 | #include <linux/dcbnl.h> | ||
24 | |||
23 | /* | 25 | /* |
24 | * Ops struct for the netlink callbacks. Used by DCB-enabled drivers through | 26 | * Ops struct for the netlink callbacks. Used by DCB-enabled drivers through |
25 | * the netdevice struct. | 27 | * the netdevice struct. |
26 | */ | 28 | */ |
27 | struct dcbnl_rtnl_ops { | 29 | struct dcbnl_rtnl_ops { |
30 | /* IEEE 802.1Qaz std */ | ||
31 | int (*ieee_getets) (struct net_device *, struct ieee_ets *); | ||
32 | int (*ieee_setets) (struct net_device *, struct ieee_ets *); | ||
33 | int (*ieee_getpfc) (struct net_device *, struct ieee_pfc *); | ||
34 | int (*ieee_setpfc) (struct net_device *, struct ieee_pfc *); | ||
35 | int (*ieee_getapp) (struct net_device *, struct dcb_app *); | ||
36 | int (*ieee_setapp) (struct net_device *, struct dcb_app *); | ||
37 | |||
38 | /* CEE std */ | ||
28 | u8 (*getstate)(struct net_device *); | 39 | u8 (*getstate)(struct net_device *); |
29 | u8 (*setstate)(struct net_device *, u8); | 40 | u8 (*setstate)(struct net_device *, u8); |
30 | void (*getpermhwaddr)(struct net_device *, u8 *); | 41 | void (*getpermhwaddr)(struct net_device *, u8 *); |
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. */ | ||
172 | static 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 | |||
178 | static 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 */ |
171 | static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, | 183 | static 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 | */ | ||
1138 | static 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 | |||
1182 | err: | ||
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. */ | ||
1190 | static 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); | ||
1237 | nla_put_failure: | ||
1238 | nlmsg_cancel(skb, nlh); | ||
1239 | nlmsg_failure: | ||
1240 | kfree_skb(skb); | ||
1241 | return -1; | ||
1242 | } | ||
1243 | |||
1121 | static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 1244 | static 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 | } |