1 /* SPDX-License-Identifier: LGPL-2.1-or-later
2  * Copyright © 2020 VMware, Inc. */
3 
4 #include <linux/pkt_sched.h>
5 
6 #include "alloc-util.h"
7 #include "conf-parser.h"
8 #include "netlink-util.h"
9 #include "parse-util.h"
10 #include "qdisc.h"
11 #include "sfb.h"
12 #include "string-util.h"
13 
stochastic_fair_blue_fill_message(Link * link,QDisc * qdisc,sd_netlink_message * req)14 static int stochastic_fair_blue_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
15         StochasticFairBlue *sfb;
16         int r;
17 
18         assert(link);
19         assert(qdisc);
20         assert(req);
21 
22         assert_se(sfb = SFB(qdisc));
23 
24         const struct tc_sfb_qopt opt = {
25             .rehash_interval = 600*1000,
26             .warmup_time = 60*1000,
27             .penalty_rate = 10,
28             .penalty_burst = 20,
29             .increment = (SFB_MAX_PROB + 1000) / 2000,
30             .decrement = (SFB_MAX_PROB + 10000) / 20000,
31             .max = 25,
32             .bin_size = 20,
33             .limit = sfb->packet_limit,
34         };
35 
36         r = sd_netlink_message_open_container_union(req, TCA_OPTIONS, "sfb");
37         if (r < 0)
38                 return r;
39 
40         r = sd_netlink_message_append_data(req, TCA_SFB_PARMS, &opt, sizeof(opt));
41         if (r < 0)
42                 return r;
43 
44         r = sd_netlink_message_close_container(req);
45         if (r < 0)
46                 return r;
47 
48         return 0;
49 }
50 
config_parse_stochastic_fair_blue_u32(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)51 int config_parse_stochastic_fair_blue_u32(
52                 const char *unit,
53                 const char *filename,
54                 unsigned line,
55                 const char *section,
56                 unsigned section_line,
57                 const char *lvalue,
58                 int ltype,
59                 const char *rvalue,
60                 void *data,
61                 void *userdata) {
62 
63         _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
64         StochasticFairBlue *sfb;
65         Network *network = data;
66         int r;
67 
68         assert(filename);
69         assert(lvalue);
70         assert(rvalue);
71         assert(data);
72 
73         r = qdisc_new_static(QDISC_KIND_SFB, network, filename, section_line, &qdisc);
74         if (r == -ENOMEM)
75                 return log_oom();
76         if (r < 0) {
77                 log_syntax(unit, LOG_WARNING, filename, line, r,
78                            "More than one kind of queueing discipline, ignoring assignment: %m");
79                 return 0;
80         }
81 
82         sfb = SFB(qdisc);
83 
84         if (isempty(rvalue)) {
85                 sfb->packet_limit = 0;
86 
87                 TAKE_PTR(qdisc);
88                 return 0;
89         }
90 
91         r = safe_atou32(rvalue, &sfb->packet_limit);
92         if (r < 0) {
93                 log_syntax(unit, LOG_WARNING, filename, line, r,
94                            "Failed to parse '%s=', ignoring assignment: %s",
95                            lvalue, rvalue);
96                 return 0;
97         }
98 
99         TAKE_PTR(qdisc);
100 
101         return 0;
102 }
103 
104 const QDiscVTable sfb_vtable = {
105         .object_size = sizeof(StochasticFairBlue),
106         .tca_kind = "sfb",
107         .fill_message = stochastic_fair_blue_fill_message,
108 };
109