~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/devlink/sb.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
  4  * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
  5  */
  6 
  7 #include "devl_internal.h"
  8 
  9 struct devlink_sb {
 10         struct list_head list;
 11         unsigned int index;
 12         u32 size;
 13         u16 ingress_pools_count;
 14         u16 egress_pools_count;
 15         u16 ingress_tc_count;
 16         u16 egress_tc_count;
 17 };
 18 
 19 static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb)
 20 {
 21         return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count;
 22 }
 23 
 24 static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink,
 25                                                   unsigned int sb_index)
 26 {
 27         struct devlink_sb *devlink_sb;
 28 
 29         list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
 30                 if (devlink_sb->index == sb_index)
 31                         return devlink_sb;
 32         }
 33         return NULL;
 34 }
 35 
 36 static bool devlink_sb_index_exists(struct devlink *devlink,
 37                                     unsigned int sb_index)
 38 {
 39         return devlink_sb_get_by_index(devlink, sb_index);
 40 }
 41 
 42 static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink,
 43                                                     struct nlattr **attrs)
 44 {
 45         if (attrs[DEVLINK_ATTR_SB_INDEX]) {
 46                 u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]);
 47                 struct devlink_sb *devlink_sb;
 48 
 49                 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
 50                 if (!devlink_sb)
 51                         return ERR_PTR(-ENODEV);
 52                 return devlink_sb;
 53         }
 54         return ERR_PTR(-EINVAL);
 55 }
 56 
 57 static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink,
 58                                                    struct genl_info *info)
 59 {
 60         return devlink_sb_get_from_attrs(devlink, info->attrs);
 61 }
 62 
 63 static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb,
 64                                                 struct nlattr **attrs,
 65                                                 u16 *p_pool_index)
 66 {
 67         u16 val;
 68 
 69         if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX])
 70                 return -EINVAL;
 71 
 72         val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]);
 73         if (val >= devlink_sb_pool_count(devlink_sb))
 74                 return -EINVAL;
 75         *p_pool_index = val;
 76         return 0;
 77 }
 78 
 79 static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb,
 80                                                struct genl_info *info,
 81                                                u16 *p_pool_index)
 82 {
 83         return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs,
 84                                                     p_pool_index);
 85 }
 86 
 87 static int
 88 devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs,
 89                                     enum devlink_sb_pool_type *p_pool_type)
 90 {
 91         u8 val;
 92 
 93         if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE])
 94                 return -EINVAL;
 95 
 96         val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]);
 97         if (val != DEVLINK_SB_POOL_TYPE_INGRESS &&
 98             val != DEVLINK_SB_POOL_TYPE_EGRESS)
 99                 return -EINVAL;
100         *p_pool_type = val;
101         return 0;
102 }
103 
104 static int
105 devlink_sb_pool_type_get_from_info(struct genl_info *info,
106                                    enum devlink_sb_pool_type *p_pool_type)
107 {
108         return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type);
109 }
110 
111 static int
112 devlink_sb_th_type_get_from_attrs(struct nlattr **attrs,
113                                   enum devlink_sb_threshold_type *p_th_type)
114 {
115         u8 val;
116 
117         if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE])
118                 return -EINVAL;
119 
120         val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]);
121         if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC &&
122             val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC)
123                 return -EINVAL;
124         *p_th_type = val;
125         return 0;
126 }
127 
128 static int
129 devlink_sb_th_type_get_from_info(struct genl_info *info,
130                                  enum devlink_sb_threshold_type *p_th_type)
131 {
132         return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type);
133 }
134 
135 static int
136 devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb,
137                                    struct nlattr **attrs,
138                                    enum devlink_sb_pool_type pool_type,
139                                    u16 *p_tc_index)
140 {
141         u16 val;
142 
143         if (!attrs[DEVLINK_ATTR_SB_TC_INDEX])
144                 return -EINVAL;
145 
146         val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]);
147         if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS &&
148             val >= devlink_sb->ingress_tc_count)
149                 return -EINVAL;
150         if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS &&
151             val >= devlink_sb->egress_tc_count)
152                 return -EINVAL;
153         *p_tc_index = val;
154         return 0;
155 }
156 
157 static int
158 devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb,
159                                   struct genl_info *info,
160                                   enum devlink_sb_pool_type pool_type,
161                                   u16 *p_tc_index)
162 {
163         return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs,
164                                                   pool_type, p_tc_index);
165 }
166 
167 static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink,
168                               struct devlink_sb *devlink_sb,
169                               enum devlink_command cmd, u32 portid,
170                               u32 seq, int flags)
171 {
172         void *hdr;
173 
174         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
175         if (!hdr)
176                 return -EMSGSIZE;
177 
178         if (devlink_nl_put_handle(msg, devlink))
179                 goto nla_put_failure;
180         if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
181                 goto nla_put_failure;
182         if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size))
183                 goto nla_put_failure;
184         if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT,
185                         devlink_sb->ingress_pools_count))
186                 goto nla_put_failure;
187         if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT,
188                         devlink_sb->egress_pools_count))
189                 goto nla_put_failure;
190         if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT,
191                         devlink_sb->ingress_tc_count))
192                 goto nla_put_failure;
193         if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT,
194                         devlink_sb->egress_tc_count))
195                 goto nla_put_failure;
196 
197         genlmsg_end(msg, hdr);
198         return 0;
199 
200 nla_put_failure:
201         genlmsg_cancel(msg, hdr);
202         return -EMSGSIZE;
203 }
204 
205 int devlink_nl_sb_get_doit(struct sk_buff *skb, struct genl_info *info)
206 {
207         struct devlink *devlink = info->user_ptr[0];
208         struct devlink_sb *devlink_sb;
209         struct sk_buff *msg;
210         int err;
211 
212         devlink_sb = devlink_sb_get_from_info(devlink, info);
213         if (IS_ERR(devlink_sb))
214                 return PTR_ERR(devlink_sb);
215 
216         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
217         if (!msg)
218                 return -ENOMEM;
219 
220         err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
221                                  DEVLINK_CMD_SB_NEW,
222                                  info->snd_portid, info->snd_seq, 0);
223         if (err) {
224                 nlmsg_free(msg);
225                 return err;
226         }
227 
228         return genlmsg_reply(msg, info);
229 }
230 
231 static int
232 devlink_nl_sb_get_dump_one(struct sk_buff *msg, struct devlink *devlink,
233                            struct netlink_callback *cb, int flags)
234 {
235         struct devlink_nl_dump_state *state = devlink_dump_state(cb);
236         struct devlink_sb *devlink_sb;
237         int idx = 0;
238         int err = 0;
239 
240         list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
241                 if (idx < state->idx) {
242                         idx++;
243                         continue;
244                 }
245                 err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
246                                          DEVLINK_CMD_SB_NEW,
247                                          NETLINK_CB(cb->skb).portid,
248                                          cb->nlh->nlmsg_seq, flags);
249                 if (err) {
250                         state->idx = idx;
251                         break;
252                 }
253                 idx++;
254         }
255 
256         return err;
257 }
258 
259 int devlink_nl_sb_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
260 {
261         return devlink_nl_dumpit(skb, cb, devlink_nl_sb_get_dump_one);
262 }
263 
264 static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink,
265                                    struct devlink_sb *devlink_sb,
266                                    u16 pool_index, enum devlink_command cmd,
267                                    u32 portid, u32 seq, int flags)
268 {
269         struct devlink_sb_pool_info pool_info;
270         void *hdr;
271         int err;
272 
273         err = devlink->ops->sb_pool_get(devlink, devlink_sb->index,
274                                         pool_index, &pool_info);
275         if (err)
276                 return err;
277 
278         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
279         if (!hdr)
280                 return -EMSGSIZE;
281 
282         if (devlink_nl_put_handle(msg, devlink))
283                 goto nla_put_failure;
284         if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
285                 goto nla_put_failure;
286         if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
287                 goto nla_put_failure;
288         if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type))
289                 goto nla_put_failure;
290         if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size))
291                 goto nla_put_failure;
292         if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE,
293                        pool_info.threshold_type))
294                 goto nla_put_failure;
295         if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_CELL_SIZE,
296                         pool_info.cell_size))
297                 goto nla_put_failure;
298 
299         genlmsg_end(msg, hdr);
300         return 0;
301 
302 nla_put_failure:
303         genlmsg_cancel(msg, hdr);
304         return -EMSGSIZE;
305 }
306 
307 int devlink_nl_sb_pool_get_doit(struct sk_buff *skb, struct genl_info *info)
308 {
309         struct devlink *devlink = info->user_ptr[0];
310         struct devlink_sb *devlink_sb;
311         struct sk_buff *msg;
312         u16 pool_index;
313         int err;
314 
315         devlink_sb = devlink_sb_get_from_info(devlink, info);
316         if (IS_ERR(devlink_sb))
317                 return PTR_ERR(devlink_sb);
318 
319         err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
320                                                   &pool_index);
321         if (err)
322                 return err;
323 
324         if (!devlink->ops->sb_pool_get)
325                 return -EOPNOTSUPP;
326 
327         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
328         if (!msg)
329                 return -ENOMEM;
330 
331         err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index,
332                                       DEVLINK_CMD_SB_POOL_NEW,
333                                       info->snd_portid, info->snd_seq, 0);
334         if (err) {
335                 nlmsg_free(msg);
336                 return err;
337         }
338 
339         return genlmsg_reply(msg, info);
340 }
341 
342 static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
343                                 struct devlink *devlink,
344                                 struct devlink_sb *devlink_sb,
345                                 u32 portid, u32 seq, int flags)
346 {
347         u16 pool_count = devlink_sb_pool_count(devlink_sb);
348         u16 pool_index;
349         int err;
350 
351         for (pool_index = 0; pool_index < pool_count; pool_index++) {
352                 if (*p_idx < start) {
353                         (*p_idx)++;
354                         continue;
355                 }
356                 err = devlink_nl_sb_pool_fill(msg, devlink,
357                                               devlink_sb,
358                                               pool_index,
359                                               DEVLINK_CMD_SB_POOL_NEW,
360                                               portid, seq, flags);
361                 if (err)
362                         return err;
363                 (*p_idx)++;
364         }
365         return 0;
366 }
367 
368 static int
369 devlink_nl_sb_pool_get_dump_one(struct sk_buff *msg, struct devlink *devlink,
370                                 struct netlink_callback *cb, int flags)
371 {
372         struct devlink_nl_dump_state *state = devlink_dump_state(cb);
373         struct devlink_sb *devlink_sb;
374         int err = 0;
375         int idx = 0;
376 
377         if (!devlink->ops->sb_pool_get)
378                 return 0;
379 
380         list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
381                 err = __sb_pool_get_dumpit(msg, state->idx, &idx,
382                                            devlink, devlink_sb,
383                                            NETLINK_CB(cb->skb).portid,
384                                            cb->nlh->nlmsg_seq, flags);
385                 if (err == -EOPNOTSUPP) {
386                         err = 0;
387                 } else if (err) {
388                         state->idx = idx;
389                         break;
390                 }
391         }
392 
393         return err;
394 }
395 
396 int devlink_nl_sb_pool_get_dumpit(struct sk_buff *skb,
397                                   struct netlink_callback *cb)
398 {
399         return devlink_nl_dumpit(skb, cb, devlink_nl_sb_pool_get_dump_one);
400 }
401 
402 static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index,
403                                u16 pool_index, u32 size,
404                                enum devlink_sb_threshold_type threshold_type,
405                                struct netlink_ext_ack *extack)
406 
407 {
408         const struct devlink_ops *ops = devlink->ops;
409 
410         if (ops->sb_pool_set)
411                 return ops->sb_pool_set(devlink, sb_index, pool_index,
412                                         size, threshold_type, extack);
413         return -EOPNOTSUPP;
414 }
415 
416 int devlink_nl_sb_pool_set_doit(struct sk_buff *skb, struct genl_info *info)
417 {
418         struct devlink *devlink = info->user_ptr[0];
419         enum devlink_sb_threshold_type threshold_type;
420         struct devlink_sb *devlink_sb;
421         u16 pool_index;
422         u32 size;
423         int err;
424 
425         devlink_sb = devlink_sb_get_from_info(devlink, info);
426         if (IS_ERR(devlink_sb))
427                 return PTR_ERR(devlink_sb);
428 
429         err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
430                                                   &pool_index);
431         if (err)
432                 return err;
433 
434         err = devlink_sb_th_type_get_from_info(info, &threshold_type);
435         if (err)
436                 return err;
437 
438         if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_POOL_SIZE))
439                 return -EINVAL;
440 
441         size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]);
442         return devlink_sb_pool_set(devlink, devlink_sb->index,
443                                    pool_index, size, threshold_type,
444                                    info->extack);
445 }
446 
447 static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
448                                         struct devlink *devlink,
449                                         struct devlink_port *devlink_port,
450                                         struct devlink_sb *devlink_sb,
451                                         u16 pool_index,
452                                         enum devlink_command cmd,
453                                         u32 portid, u32 seq, int flags)
454 {
455         const struct devlink_ops *ops = devlink->ops;
456         u32 threshold;
457         void *hdr;
458         int err;
459 
460         err = ops->sb_port_pool_get(devlink_port, devlink_sb->index,
461                                     pool_index, &threshold);
462         if (err)
463                 return err;
464 
465         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
466         if (!hdr)
467                 return -EMSGSIZE;
468 
469         if (devlink_nl_put_handle(msg, devlink))
470                 goto nla_put_failure;
471         if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
472                 goto nla_put_failure;
473         if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
474                 goto nla_put_failure;
475         if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
476                 goto nla_put_failure;
477         if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
478                 goto nla_put_failure;
479 
480         if (ops->sb_occ_port_pool_get) {
481                 u32 cur;
482                 u32 max;
483 
484                 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index,
485                                                 pool_index, &cur, &max);
486                 if (err && err != -EOPNOTSUPP)
487                         goto sb_occ_get_failure;
488                 if (!err) {
489                         if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
490                                 goto nla_put_failure;
491                         if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
492                                 goto nla_put_failure;
493                 }
494         }
495 
496         genlmsg_end(msg, hdr);
497         return 0;
498 
499 nla_put_failure:
500         err = -EMSGSIZE;
501 sb_occ_get_failure:
502         genlmsg_cancel(msg, hdr);
503         return err;
504 }
505 
506 int devlink_nl_sb_port_pool_get_doit(struct sk_buff *skb,
507                                      struct genl_info *info)
508 {
509         struct devlink_port *devlink_port = info->user_ptr[1];
510         struct devlink *devlink = devlink_port->devlink;
511         struct devlink_sb *devlink_sb;
512         struct sk_buff *msg;
513         u16 pool_index;
514         int err;
515 
516         devlink_sb = devlink_sb_get_from_info(devlink, info);
517         if (IS_ERR(devlink_sb))
518                 return PTR_ERR(devlink_sb);
519 
520         err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
521                                                   &pool_index);
522         if (err)
523                 return err;
524 
525         if (!devlink->ops->sb_port_pool_get)
526                 return -EOPNOTSUPP;
527 
528         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
529         if (!msg)
530                 return -ENOMEM;
531 
532         err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port,
533                                            devlink_sb, pool_index,
534                                            DEVLINK_CMD_SB_PORT_POOL_NEW,
535                                            info->snd_portid, info->snd_seq, 0);
536         if (err) {
537                 nlmsg_free(msg);
538                 return err;
539         }
540 
541         return genlmsg_reply(msg, info);
542 }
543 
544 static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
545                                      struct devlink *devlink,
546                                      struct devlink_sb *devlink_sb,
547                                      u32 portid, u32 seq, int flags)
548 {
549         struct devlink_port *devlink_port;
550         u16 pool_count = devlink_sb_pool_count(devlink_sb);
551         unsigned long port_index;
552         u16 pool_index;
553         int err;
554 
555         xa_for_each(&devlink->ports, port_index, devlink_port) {
556                 for (pool_index = 0; pool_index < pool_count; pool_index++) {
557                         if (*p_idx < start) {
558                                 (*p_idx)++;
559                                 continue;
560                         }
561                         err = devlink_nl_sb_port_pool_fill(msg, devlink,
562                                                            devlink_port,
563                                                            devlink_sb,
564                                                            pool_index,
565                                                            DEVLINK_CMD_SB_PORT_POOL_NEW,
566                                                            portid, seq, flags);
567                         if (err)
568                                 return err;
569                         (*p_idx)++;
570                 }
571         }
572         return 0;
573 }
574 
575 static int
576 devlink_nl_sb_port_pool_get_dump_one(struct sk_buff *msg,
577                                      struct devlink *devlink,
578                                      struct netlink_callback *cb, int flags)
579 {
580         struct devlink_nl_dump_state *state = devlink_dump_state(cb);
581         struct devlink_sb *devlink_sb;
582         int idx = 0;
583         int err = 0;
584 
585         if (!devlink->ops->sb_port_pool_get)
586                 return 0;
587 
588         list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
589                 err = __sb_port_pool_get_dumpit(msg, state->idx, &idx,
590                                                 devlink, devlink_sb,
591                                                 NETLINK_CB(cb->skb).portid,
592                                                 cb->nlh->nlmsg_seq, flags);
593                 if (err == -EOPNOTSUPP) {
594                         err = 0;
595                 } else if (err) {
596                         state->idx = idx;
597                         break;
598                 }
599         }
600 
601         return err;
602 }
603 
604 int devlink_nl_sb_port_pool_get_dumpit(struct sk_buff *skb,
605                                        struct netlink_callback *cb)
606 {
607         return devlink_nl_dumpit(skb, cb, devlink_nl_sb_port_pool_get_dump_one);
608 }
609 
610 static int devlink_sb_port_pool_set(struct devlink_port *devlink_port,
611                                     unsigned int sb_index, u16 pool_index,
612                                     u32 threshold,
613                                     struct netlink_ext_ack *extack)
614 
615 {
616         const struct devlink_ops *ops = devlink_port->devlink->ops;
617 
618         if (ops->sb_port_pool_set)
619                 return ops->sb_port_pool_set(devlink_port, sb_index,
620                                              pool_index, threshold, extack);
621         return -EOPNOTSUPP;
622 }
623 
624 int devlink_nl_sb_port_pool_set_doit(struct sk_buff *skb,
625                                      struct genl_info *info)
626 {
627         struct devlink_port *devlink_port = info->user_ptr[1];
628         struct devlink *devlink = info->user_ptr[0];
629         struct devlink_sb *devlink_sb;
630         u16 pool_index;
631         u32 threshold;
632         int err;
633 
634         devlink_sb = devlink_sb_get_from_info(devlink, info);
635         if (IS_ERR(devlink_sb))
636                 return PTR_ERR(devlink_sb);
637 
638         err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
639                                                   &pool_index);
640         if (err)
641                 return err;
642 
643         if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_THRESHOLD))
644                 return -EINVAL;
645 
646         threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
647         return devlink_sb_port_pool_set(devlink_port, devlink_sb->index,
648                                         pool_index, threshold, info->extack);
649 }
650 
651 static int
652 devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink,
653                                 struct devlink_port *devlink_port,
654                                 struct devlink_sb *devlink_sb, u16 tc_index,
655                                 enum devlink_sb_pool_type pool_type,
656                                 enum devlink_command cmd,
657                                 u32 portid, u32 seq, int flags)
658 {
659         const struct devlink_ops *ops = devlink->ops;
660         u16 pool_index;
661         u32 threshold;
662         void *hdr;
663         int err;
664 
665         err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index,
666                                        tc_index, pool_type,
667                                        &pool_index, &threshold);
668         if (err)
669                 return err;
670 
671         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
672         if (!hdr)
673                 return -EMSGSIZE;
674 
675         if (devlink_nl_put_handle(msg, devlink))
676                 goto nla_put_failure;
677         if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
678                 goto nla_put_failure;
679         if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
680                 goto nla_put_failure;
681         if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index))
682                 goto nla_put_failure;
683         if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type))
684                 goto nla_put_failure;
685         if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
686                 goto nla_put_failure;
687         if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
688                 goto nla_put_failure;
689 
690         if (ops->sb_occ_tc_port_bind_get) {
691                 u32 cur;
692                 u32 max;
693 
694                 err = ops->sb_occ_tc_port_bind_get(devlink_port,
695                                                    devlink_sb->index,
696                                                    tc_index, pool_type,
697                                                    &cur, &max);
698                 if (err && err != -EOPNOTSUPP)
699                         return err;
700                 if (!err) {
701                         if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
702                                 goto nla_put_failure;
703                         if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
704                                 goto nla_put_failure;
705                 }
706         }
707 
708         genlmsg_end(msg, hdr);
709         return 0;
710 
711 nla_put_failure:
712         genlmsg_cancel(msg, hdr);
713         return -EMSGSIZE;
714 }
715 
716 int devlink_nl_sb_tc_pool_bind_get_doit(struct sk_buff *skb,
717                                         struct genl_info *info)
718 {
719         struct devlink_port *devlink_port = info->user_ptr[1];
720         struct devlink *devlink = devlink_port->devlink;
721         struct devlink_sb *devlink_sb;
722         struct sk_buff *msg;
723         enum devlink_sb_pool_type pool_type;
724         u16 tc_index;
725         int err;
726 
727         devlink_sb = devlink_sb_get_from_info(devlink, info);
728         if (IS_ERR(devlink_sb))
729                 return PTR_ERR(devlink_sb);
730 
731         err = devlink_sb_pool_type_get_from_info(info, &pool_type);
732         if (err)
733                 return err;
734 
735         err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
736                                                 pool_type, &tc_index);
737         if (err)
738                 return err;
739 
740         if (!devlink->ops->sb_tc_pool_bind_get)
741                 return -EOPNOTSUPP;
742 
743         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
744         if (!msg)
745                 return -ENOMEM;
746 
747         err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port,
748                                               devlink_sb, tc_index, pool_type,
749                                               DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
750                                               info->snd_portid,
751                                               info->snd_seq, 0);
752         if (err) {
753                 nlmsg_free(msg);
754                 return err;
755         }
756 
757         return genlmsg_reply(msg, info);
758 }
759 
760 static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
761                                         int start, int *p_idx,
762                                         struct devlink *devlink,
763                                         struct devlink_sb *devlink_sb,
764                                         u32 portid, u32 seq, int flags)
765 {
766         struct devlink_port *devlink_port;
767         unsigned long port_index;
768         u16 tc_index;
769         int err;
770 
771         xa_for_each(&devlink->ports, port_index, devlink_port) {
772                 for (tc_index = 0;
773                      tc_index < devlink_sb->ingress_tc_count; tc_index++) {
774                         if (*p_idx < start) {
775                                 (*p_idx)++;
776                                 continue;
777                         }
778                         err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
779                                                               devlink_port,
780                                                               devlink_sb,
781                                                               tc_index,
782                                                               DEVLINK_SB_POOL_TYPE_INGRESS,
783                                                               DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
784                                                               portid, seq,
785                                                               flags);
786                         if (err)
787                                 return err;
788                         (*p_idx)++;
789                 }
790                 for (tc_index = 0;
791                      tc_index < devlink_sb->egress_tc_count; tc_index++) {
792                         if (*p_idx < start) {
793                                 (*p_idx)++;
794                                 continue;
795                         }
796                         err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
797                                                               devlink_port,
798                                                               devlink_sb,
799                                                               tc_index,
800                                                               DEVLINK_SB_POOL_TYPE_EGRESS,
801                                                               DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
802                                                               portid, seq,
803                                                               flags);
804                         if (err)
805                                 return err;
806                         (*p_idx)++;
807                 }
808         }
809         return 0;
810 }
811 
812 static int devlink_nl_sb_tc_pool_bind_get_dump_one(struct sk_buff *msg,
813                                                    struct devlink *devlink,
814                                                    struct netlink_callback *cb,
815                                                    int flags)
816 {
817         struct devlink_nl_dump_state *state = devlink_dump_state(cb);
818         struct devlink_sb *devlink_sb;
819         int idx = 0;
820         int err = 0;
821 
822         if (!devlink->ops->sb_tc_pool_bind_get)
823                 return 0;
824 
825         list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
826                 err = __sb_tc_pool_bind_get_dumpit(msg, state->idx, &idx,
827                                                    devlink, devlink_sb,
828                                                    NETLINK_CB(cb->skb).portid,
829                                                    cb->nlh->nlmsg_seq, flags);
830                 if (err == -EOPNOTSUPP) {
831                         err = 0;
832                 } else if (err) {
833                         state->idx = idx;
834                         break;
835                 }
836         }
837 
838         return err;
839 }
840 
841 int devlink_nl_sb_tc_pool_bind_get_dumpit(struct sk_buff *skb,
842                                           struct netlink_callback *cb)
843 {
844         return devlink_nl_dumpit(skb, cb,
845                                  devlink_nl_sb_tc_pool_bind_get_dump_one);
846 }
847 
848 static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
849                                        unsigned int sb_index, u16 tc_index,
850                                        enum devlink_sb_pool_type pool_type,
851                                        u16 pool_index, u32 threshold,
852                                        struct netlink_ext_ack *extack)
853 
854 {
855         const struct devlink_ops *ops = devlink_port->devlink->ops;
856 
857         if (ops->sb_tc_pool_bind_set)
858                 return ops->sb_tc_pool_bind_set(devlink_port, sb_index,
859                                                 tc_index, pool_type,
860                                                 pool_index, threshold, extack);
861         return -EOPNOTSUPP;
862 }
863 
864 int devlink_nl_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
865                                         struct genl_info *info)
866 {
867         struct devlink_port *devlink_port = info->user_ptr[1];
868         struct devlink *devlink = info->user_ptr[0];
869         enum devlink_sb_pool_type pool_type;
870         struct devlink_sb *devlink_sb;
871         u16 tc_index;
872         u16 pool_index;
873         u32 threshold;
874         int err;
875 
876         devlink_sb = devlink_sb_get_from_info(devlink, info);
877         if (IS_ERR(devlink_sb))
878                 return PTR_ERR(devlink_sb);
879 
880         err = devlink_sb_pool_type_get_from_info(info, &pool_type);
881         if (err)
882                 return err;
883 
884         err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
885                                                 pool_type, &tc_index);
886         if (err)
887                 return err;
888 
889         err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
890                                                   &pool_index);
891         if (err)
892                 return err;
893 
894         if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_THRESHOLD))
895                 return -EINVAL;
896 
897         threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
898         return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index,
899                                            tc_index, pool_type,
900                                            pool_index, threshold, info->extack);
901 }
902 
903 int devlink_nl_sb_occ_snapshot_doit(struct sk_buff *skb, struct genl_info *info)
904 {
905         struct devlink *devlink = info->user_ptr[0];
906         const struct devlink_ops *ops = devlink->ops;
907         struct devlink_sb *devlink_sb;
908 
909         devlink_sb = devlink_sb_get_from_info(devlink, info);
910         if (IS_ERR(devlink_sb))
911                 return PTR_ERR(devlink_sb);
912 
913         if (ops->sb_occ_snapshot)
914                 return ops->sb_occ_snapshot(devlink, devlink_sb->index);
915         return -EOPNOTSUPP;
916 }
917 
918 int devlink_nl_sb_occ_max_clear_doit(struct sk_buff *skb,
919                                      struct genl_info *info)
920 {
921         struct devlink *devlink = info->user_ptr[0];
922         const struct devlink_ops *ops = devlink->ops;
923         struct devlink_sb *devlink_sb;
924 
925         devlink_sb = devlink_sb_get_from_info(devlink, info);
926         if (IS_ERR(devlink_sb))
927                 return PTR_ERR(devlink_sb);
928 
929         if (ops->sb_occ_max_clear)
930                 return ops->sb_occ_max_clear(devlink, devlink_sb->index);
931         return -EOPNOTSUPP;
932 }
933 
934 int devl_sb_register(struct devlink *devlink, unsigned int sb_index,
935                      u32 size, u16 ingress_pools_count,
936                      u16 egress_pools_count, u16 ingress_tc_count,
937                      u16 egress_tc_count)
938 {
939         struct devlink_sb *devlink_sb;
940 
941         lockdep_assert_held(&devlink->lock);
942 
943         if (devlink_sb_index_exists(devlink, sb_index))
944                 return -EEXIST;
945 
946         devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL);
947         if (!devlink_sb)
948                 return -ENOMEM;
949         devlink_sb->index = sb_index;
950         devlink_sb->size = size;
951         devlink_sb->ingress_pools_count = ingress_pools_count;
952         devlink_sb->egress_pools_count = egress_pools_count;
953         devlink_sb->ingress_tc_count = ingress_tc_count;
954         devlink_sb->egress_tc_count = egress_tc_count;
955         list_add_tail(&devlink_sb->list, &devlink->sb_list);
956         return 0;
957 }
958 EXPORT_SYMBOL_GPL(devl_sb_register);
959 
960 int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
961                         u32 size, u16 ingress_pools_count,
962                         u16 egress_pools_count, u16 ingress_tc_count,
963                         u16 egress_tc_count)
964 {
965         int err;
966 
967         devl_lock(devlink);
968         err = devl_sb_register(devlink, sb_index, size, ingress_pools_count,
969                                egress_pools_count, ingress_tc_count,
970                                egress_tc_count);
971         devl_unlock(devlink);
972         return err;
973 }
974 EXPORT_SYMBOL_GPL(devlink_sb_register);
975 
976 void devl_sb_unregister(struct devlink *devlink, unsigned int sb_index)
977 {
978         struct devlink_sb *devlink_sb;
979 
980         lockdep_assert_held(&devlink->lock);
981 
982         devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
983         WARN_ON(!devlink_sb);
984         list_del(&devlink_sb->list);
985         kfree(devlink_sb);
986 }
987 EXPORT_SYMBOL_GPL(devl_sb_unregister);
988 
989 void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index)
990 {
991         devl_lock(devlink);
992         devl_sb_unregister(devlink, sb_index);
993         devl_unlock(devlink);
994 }
995 EXPORT_SYMBOL_GPL(devlink_sb_unregister);
996 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php