-![systemd logo](http://brand.systemd.io/assets/page-logo.png)
+![Systemd](http://brand.systemd.io/assets/page-logo.png)
-# systemd - System and Service Manager
+System and Service Manager
<a href="https://in.waw.pl/systemd-github-state/systemd-systemd-issues.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-issues-small.svg" alt="Count of open issues over time"></a>
<a href="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests-small.svg" alt="Count of open pull requests over time"></a>
---
title: Automatic Boot Assessment
category: Booting
+layout: default
---
# Automatic Boot Assessment
---
title: Locking Block Device Access
category: Interfaces
+layout: default
---
# Locking Block Device Access
---
title: The Boot Loader Interface
category: Booting
+layout: default
---
# The Boot Loader Interface
---
title: The Boot Loader Specification
category: Booting
+layout: default
---
# The Boot Loader Specification
---
title: Control Group APIs and Delegation
category: Interfaces
+layout: default
---
# Control Group APIs and Delegation
---
title: The systemd Community Conduct Guidelines
category: Contributing
+layout: default
---
# The systemd Community Conduct Guidelines
---
title: Code Quality Tools
category: Contributing
+layout: default
---
# Code Quality Tools
---
title: Coding Style
category: Contributing
+layout: default
---
# Coding Style
---
title: Contributing
category: Contributing
+layout: default
---
# Contributing
---
title: Porting systemd To New Distributions
category: Concepts
+layout: default
---
# Porting systemd To New Distributions
---
title: Known Environment Variables
category: Interfaces
+layout: default
---
# Known Environment Variables
---
title: Hacking on systemd
category: Contributing
+layout: default
---
# Hacking on systemd
---
title: Portable Services Introduction
category: Concepts
+layout: default
---
# Portable Services Introduction
---
title: Predictable Network Interface Names
category: Concepts
+layout: default
---
# Predictable Network Interface Names
---
title: Random Seeds
category: Concepts
+layout: default
---
# Random Seeds
---
title: Steps to a Successful Release
category: Contributing
+layout: default
---
# Steps to a Successful Release
---
title: Reporting of security vulnerabilities
category: Contributing
+layout: default
---
# Reporting of security vulnerabilities
---
title: Using /tmp/ And /var/tmp/ Safely
category: Interfaces
+layout: default
---
# Using `/tmp/` And `/var/tmp/` Safely
---
title: Testing systemd using sanitizers
category: Contributing
+layout: default
---
# Testing systemd using sanitizers
---
title: What settings are currently available for transient units?
category: Interfaces
+layout: default
---
# What settings are currently available for transient units?
---
title: Notes for Translators
category: Contributing
+layout: default
---
# Notes for Translators
---
title: Users, Groups, UIDs and GIDs on `systemd` Systems
category: Concepts
+layout: default
---
# Users, Groups, UIDs and GIDs on `systemd` Systems
-theme: jekyll-theme-primer
+# Site settings
+title: systemd
+baseurl: "" # the subpath of your site, e.g. /blog/
+url: "http://systemd.io" # the base hostname & protocol for your site
+
+permalink: /:title/
+
+# Build settings
+markdown: kramdown
--- /dev/null
+<footer class="site-footer">
+ <p>© systemd, 2019</p>
+
+ <p><a href="https://github.com/systemd/systemd">Website source</a></p>
+</footer>
--- /dev/null
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="theme-color" content="#0021D8">
+
+ <title>{% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %}</title>
+
+ <link rel="canonical" href="{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url }}">
+ <link rel="alternate" type="application/rss+xml" title="{{ site.title }}" href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}" />
+
+ <link rel="stylesheet" href="{{ "/style.css" | prepend: site.baseurl }}">
+
+ <link rel="icon" type="image/png" href="/favicon.png" />
+ <link rel="icon" sizes="144x144" href="apple-touch-icon.png">
+</head>
--- /dev/null
+<header class="site-header">
+
+ <div class="wrapper">
+
+ <a class="page-logo" href="{{ site.baseurl }}/">
+ <img src="/assets/page-logo.svg" alt="systemd">
+ </a>
+
+ </div>
+
+</header>
--- /dev/null
+<!DOCTYPE html>
+<html>
+
+ {% include head.html %}
+
+ <body>
+
+ {% include header.html %}
+
+ <div class="container">
+ {{ content }}
+ </div>
+
+ {% include footer.html %}
+
+ </body>
+
+</html>
--- /dev/null
+<svg xmlns="http://www.w3.org/2000/svg" width="202" height="26">
+ <path overflow="visible" font-weight="400" d="M0 0v26h10v-4H4V4h6V0zm76 0v4h6v18h-6v4h10V0z" style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1" color="#000" font-family="sans-serif" fill="#201a26"/>
+ <path word-spacing="0" letter-spacing=".2" font-size="12" font-weight="700" style="line-height:1.25;-inkscape-font-specification:'Heebo Bold';text-align:start" d="M113.498 14.926q-4.5-.96-4.5-3.878 0-1.079.609-1.981.621-.902 1.781-1.441 1.16-.54 2.707-.54 1.63 0 2.848.528 1.219.516 1.875 1.453.656.926.656 2.121h-3.539q0-.762-.457-1.183-.457-.434-1.394-.434-.774 0-1.243.363-.457.364-.457.938 0 .55.516.89.527.34 1.781.575 1.5.28 2.543.738 1.043.445 1.653 1.242.62.797.62 2.027 0 1.114-.667 2.004-.657.88-1.887 1.383-1.219.504-2.836.504-1.711 0-2.965-.621-1.242-.633-1.898-1.617-.645-.985-.645-2.051h3.34q.036.914.656 1.36.621.433 1.594.433.902 0 1.383-.34.492-.351.492-.937 0-.364-.223-.61-.21-.258-.773-.48-.55-.223-1.57-.446zm19.384-7.606l-5.086 14.58q-.293.831-.726 1.523-.434.703-1.266 1.195-.832.504-2.098.504-.457 0-.75-.048-.281-.046-.785-.176v-2.672q.176.02.527.02.95 0 1.418-.293.47-.293.715-.961l.352-.926-4.43-12.738h3.797l2.262 7.687 2.285-7.687zm5.884 7.606q-4.5-.96-4.5-3.878 0-1.079.61-1.981.62-.902 1.781-1.441 1.16-.54 2.707-.54 1.629 0 2.848.528 1.218.516 1.875 1.453.656.926.656 2.121h-3.539q0-.762-.457-1.183-.457-.434-1.395-.434-.773 0-1.242.363-.457.364-.457.938 0 .55.516.89.527.34 1.781.575 1.5.28 2.543.738 1.043.445 1.652 1.242.621.797.621 2.027 0 1.114-.668 2.004-.656.88-1.886 1.383-1.219.504-2.836.504-1.711 0-2.965-.621-1.242-.633-1.899-1.617-.644-.985-.644-2.051h3.34q.036.914.656 1.36.621.433 1.594.433.902 0 1.383-.34.492-.351.492-.937 0-.364-.223-.61-.21-.258-.773-.48-.551-.223-1.57-.446zm13.983 2.403q.574 0 .984-.082v2.66q-.914.328-2.086.328-3.727 0-3.727-3.797V9.899h-1.793V7.321h1.793v-3.14h3.54v3.14h2.132v2.578h-2.133v6.129q0 .75.293 1.031.293.27.997.27zm14.228-2.519h-8.016q.2 1.183.985 1.886.785.691 2.015.691.914 0 1.688-.34.785-.351 1.336-1.042l1.699 1.957q-.668.96-1.957 1.617-1.278.656-3 .656-1.946 0-3.387-.82-1.43-.82-2.203-2.227-.762-1.406-.762-3.105v-.446q0-1.898.715-3.386.715-1.489 2.063-2.32 1.347-.844 3.187-.844 1.793 0 3.059.761 1.265.762 1.922 2.168.656 1.395.656 3.293zm-3.469-2.65q-.024-1.03-.574-1.628-.54-.598-1.617-.598-1.008 0-1.582.668-.563.668-.739 1.84h4.512zm19.923-5.073q1.934 0 2.989 1.148 1.054 1.148 1.054 3.727v8.039h-3.539V11.95q0-.797-.21-1.23-.212-.446-.61-.61-.387-.164-.984-.164-.715 0-1.219.352-.504.34-.797.972.02.082.02.27V20h-3.54v-8.015q0-.797-.21-1.242-.211-.445-.61-.621-.386-.176-.996-.176-.68 0-1.183.304-.492.293-.797.844V20h-3.539V7.32h3.316l.118 1.419q.633-.797 1.547-1.22.926-.433 2.086-.433 1.172 0 2.016.48.855.47 1.312 1.442.633-.926 1.582-1.418.961-.504 2.203-.504zM201.398 2v18h-3.187l-.176-1.359q-1.243 1.594-3.212 1.594-1.535 0-2.66-.82-1.113-.832-1.699-2.285-.574-1.454-.574-3.317v-.246q0-1.934.574-3.398.586-1.465 1.7-2.274 1.124-.808 2.683-.808 1.805 0 3.012 1.37V2.001zm-5.672 15.376q1.488 0 2.133-1.266v-4.898q-.61-1.266-2.11-1.266-1.207 0-1.77.984-.55.985-.55 2.637v.246q0 1.629.54 2.602.55.96 1.757.96z" font-family="Heebo" fill="#201a26"/>
+ <path d="M45 13L63 3v20z" fill="#30d475"/>
+ <circle cx="30.001" cy="13.001" r="9" fill="#30d475"/>
+</svg>
--- /dev/null
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16">
+ <g transform="translate(380 -506.52)">
+ <rect ry="16.875" rx="16.875" y="2409.281" x="4128.568" height="90" width="90" fill="#201a26" transform="matrix(.17778 0 0 .17778 -1113.968 78.203)" stroke-width="5.625"/>
+ <g fill="none" stroke="#fff" stroke-width="2">
+ <path d="M-377 513.02h-1.5v3h1.5M-367 513.02h1.5v3h-1.5" stroke-width="1"/>
+ </g>
+ <path d="M-368 516.77v-4.5l-3 1.25-1 1 1 1z" fill="#30d475"/>
+ <circle cx="-374.25" cy="514.52" r="1.75" fill="#30d475"/>
+ </g>
+</svg>
---
-title: systemd Documentation
+layout: default
---
-# systemd Documentation
+systemd is a suite of basic building blocks for a Linux system. It provides a system and service manager that runs as PID 1 and starts the rest of the system.
+
+systemd provides aggressive parallelization capabilities, uses socket and D-Bus activation for starting services, offers on-demand starting of daemons, keeps track of processes using Linux control groups, maintains mount and automount points, and implements an elaborate transactional dependency-based service control logic. systemd supports SysV and LSB init scripts and works as a replacement for sysvinit.
+
+Other parts include a logging daemon, utilities to control basic system configuration like the hostname, date, locale, maintain a list of logged-in users and running containers and virtual machines, system accounts, runtime directories and settings, and daemons to manage simple network configuration, network time synchronization, log forwarding, and name resolution.
+
+See the introductory blog story and three status updates for a longer introduction. Also see the [Wikipedia article](https://en.wikipedia.org/wiki/systemd).
+
+---
{% assign by_category = site.pages | group_by:"category" %}
{% assign extra_pages = site.data.extra_pages | group_by:"category" %}
* [{{ page.title }}]({{ page.url | relative_url }}){% endfor %}
{% endif %}
{% endfor %}
+
--- /dev/null
+@font-face {
+ font-family: 'Heebo';
+ src: url('fonts/heebo-regular.woff');
+ font-weight: 400;
+}
+
+@font-face {
+ font-family: 'Heebo';
+ src: url('fonts/heebo-bold.woff');
+ font-weight: 600;
+}
+
+/* Typography */
+* {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+html, body {
+ margin: 0;
+ padding: 0;
+ font-size: 16px;
+ font-family: "Heebo", sans-serif;
+ font-weight: 400;
+ line-height: 1.6;
+}
+body {
+ color: #241f31;
+ background-color: #f6f5f4;
+}
+h1, h2, h3, h4, h5, h6 {
+ margin: 1rem 0 10px;
+ font-weight: 600;
+ line-height: 1.25;
+}
+h1 {
+ text-align: center;
+ font-size: 30px;
+ font-weight: 100;
+ font-style: normal;
+ margin-bottom: 2rem;
+}
+@media screen and (min-width: 650px) {
+ h1 {
+ margin-left: 10%;
+ margin-right: 10%;
+ font-size: 38px;
+ }
+}
+h2 {
+ margin-top: 3rem;
+ font-size: 1.2rem;
+}
+a {
+ font-weight: 600;
+ text-decoration: none;
+ color: #26b763;
+ cursor: pointer;
+}
+a:hover {
+ text-decoration: underline;
+}
+b {
+ font-weight: 600;
+}
+small {
+ color: #777;
+}
+hr {
+ margin: 3rem auto 4rem;
+ width: 40%;
+ opacity: 40%;
+}
+
+/* Layout */
+.container {
+ width: 80%;
+ margin-left: auto;
+ margin-right: auto;
+ max-width: 720px;
+}
+
+/* Singletons */
+.page-logo {
+ display: block;
+ padding: 5rem 0 3rem;
+}
+.page-logo > img {
+ display: block;
+ margin: 0 auto;
+}
+
+.brand-white {
+ background-color: #fff;
+}
+
+.brand-green {
+ background-color: #30D475;
+}
+
+.brand-black {
+ background-color: #201A26;
+ color: white;
+}
+
+.page-link::after {
+ content: " ➜";
+}
+
+
+/* Footer */
+footer {
+ text-align: center;
+ padding: 3em 0 3em;
+ font-size: 1em;
+ margin-top: 4rem;
+}
+
+/* Github Code Highlighting */
+.highlight table td { padding: 5px; }
+.highlight table pre { margin: 0; }
+.highlight .cm {
+ color: #999988;
+ font-style: italic;
+}
+.highlight .cp {
+ color: #999999;
+ font-weight: bold;
+}
+.highlight .c1 {
+ color: #999988;
+ font-style: italic;
+}
+.highlight .cs {
+ color: #999999;
+ font-weight: bold;
+ font-style: italic;
+}
+.highlight .c, .highlight .ch, .highlight .cd, .highlight .cpf {
+ color: #999988;
+ font-style: italic;
+}
+.highlight .err {
+ color: #a61717;
+ background-color: #e3d2d2;
+}
+.highlight .gd {
+ color: #000000;
+ background-color: #ffdddd;
+}
+.highlight .ge {
+ color: #000000;
+ font-style: italic;
+}
+.highlight .gr {
+ color: #aa0000;
+}
+.highlight .gh {
+ color: #999999;
+}
+.highlight .gi {
+ color: #000000;
+ background-color: #ddffdd;
+}
+.highlight .go {
+ color: #888888;
+}
+.highlight .gp {
+ color: #555555;
+}
+.highlight .gs {
+ font-weight: bold;
+}
+.highlight .gu {
+ color: #aaaaaa;
+}
+.highlight .gt {
+ color: #aa0000;
+}
+.highlight .kc {
+ color: #000000;
+ font-weight: bold;
+}
+.highlight .kd {
+ color: #000000;
+ font-weight: bold;
+}
+.highlight .kn {
+ color: #000000;
+ font-weight: bold;
+}
+.highlight .kp {
+ color: #000000;
+ font-weight: bold;
+}
+.highlight .kr {
+ color: #000000;
+ font-weight: bold;
+}
+.highlight .kt {
+ color: #445588;
+ font-weight: bold;
+}
+.highlight .k, .highlight .kv {
+ color: #000000;
+ font-weight: bold;
+}
+.highlight .mf {
+ color: #009999;
+}
+.highlight .mh {
+ color: #009999;
+}
+.highlight .il {
+ color: #009999;
+}
+.highlight .mi {
+ color: #009999;
+}
+.highlight .mo {
+ color: #009999;
+}
+.highlight .m, .highlight .mb, .highlight .mx {
+ color: #009999;
+}
+.highlight .sb {
+ color: #d14;
+}
+.highlight .sc {
+ color: #d14;
+}
+.highlight .sd {
+ color: #d14;
+}
+.highlight .s2 {
+ color: #d14;
+}
+.highlight .se {
+ color: #d14;
+}
+.highlight .sh {
+ color: #d14;
+}
+.highlight .si {
+ color: #d14;
+}
+.highlight .sx {
+ color: #d14;
+}
+.highlight .sr {
+ color: #009926;
+}
+.highlight .s1 {
+ color: #d14;
+}
+.highlight .ss {
+ color: #990073;
+}
+.highlight .s, .highlight .sa, .highlight .dl {
+ color: #d14;
+}
+.highlight .na {
+ color: #008080;
+}
+.highlight .bp {
+ color: #999999;
+}
+.highlight .nb {
+ color: #0086B3;
+}
+.highlight .nc {
+ color: #445588;
+ font-weight: bold;
+}
+.highlight .no {
+ color: #008080;
+}
+.highlight .nd {
+ color: #3c5d5d;
+ font-weight: bold;
+}
+.highlight .ni {
+ color: #800080;
+}
+.highlight .ne {
+ color: #990000;
+ font-weight: bold;
+}
+.highlight .nf, .highlight .fm {
+ color: #990000;
+ font-weight: bold;
+}
+.highlight .nl {
+ color: #990000;
+ font-weight: bold;
+}
+.highlight .nn {
+ color: #555555;
+}
+.highlight .nt {
+ color: #000080;
+}
+.highlight .vc {
+ color: #008080;
+}
+.highlight .vg {
+ color: #008080;
+}
+.highlight .vi {
+ color: #008080;
+}
+.highlight .nv, .highlight .vm {
+ color: #008080;
+}
+.highlight .ow {
+ color: #000000;
+ font-weight: bold;
+}
+.highlight .o {
+ color: #000000;
+ font-weight: bold;
+}
+.highlight .w {
+ color: #bbbbbb;
+}
+.highlight {
+ background-color: #f8f8f8;
+}
+
+
+/* Code Blocks */
+.highlighter-rouge {
+ padding: 2px 1rem;
+ border-radius: 5px;
+ background-color: white;
+
+ overflow: auto;
+}
+.highlighter-rouge * {
+ background-color: white;
+}
+
+/* Inline Code */
+code.highlighter-rouge {
+ padding: 2px 6px;
+ background-color: rgba(0,0,0, 0.07);
+}
mouse:usb:v145fp01ac:name:HID-compliant Mouse Trust Gaming Mouse:
MOUSE_DPI=*800@528 1200@537 1600@536 2400@521
- ##########################################
- # Zelotes
- ##########################################
+##########################################
+# Zelotes
+##########################################
# Zelotes 5500 DPI 7 Button USB Wired Gaming Mouse
mouse:usb:v1d57pad17:*
[SPECIAL_GLYPH_SLIGHTLY_HAPPY_SMILEY] = "\360\237\231\202", /* 🙂 */
[SPECIAL_GLYPH_NEUTRAL_SMILEY] = "\360\237\230\220", /* 😐 */
[SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY] = "\360\237\231\201", /* 🙁 */
- [SPECIAL_GLYPH_UNHAPPY_SMILEY] = "\360\237\230\250", /* 😨️️ */
+ [SPECIAL_GLYPH_UNHAPPY_SMILEY] = "\360\237\230\250", /* 😨 */
[SPECIAL_GLYPH_DEPRESSED_SMILEY] = "\360\237\244\242", /* 🤢 */
},
};
#include "qdisc.h"
#include "string-util.h"
-int fair_queuing_controlled_delay_new(FairQueuingControlledDelay **ret) {
- FairQueuingControlledDelay *fqcd = NULL;
-
- fqcd = new0(FairQueuingControlledDelay, 1);
- if (!fqcd)
- return -ENOMEM;
-
- *ret = TAKE_PTR(fqcd);
-
- return 0;
-}
-
-int fair_queuing_controlled_delay_fill_message(Link *link, const FairQueuingControlledDelay *fqcd, sd_netlink_message *req) {
+static int fair_queuing_controlled_delay_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
+ FairQueuingControlledDelay *fqcd;
int r;
assert(link);
- assert(fqcd);
+ assert(qdisc);
assert(req);
+ fqcd = FQ_CODEL(qdisc);
+
r = sd_netlink_message_open_container_union(req, TCA_OPTIONS, "fq_codel");
if (r < 0)
return log_link_error_errno(link, r, "Could not open container TCA_OPTIONS: %m");
void *userdata) {
_cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+ FairQueuingControlledDelay *fqcd;
Network *network = data;
int r;
assert(rvalue);
assert(data);
- r = qdisc_new_static(network, filename, section_line, &qdisc);
+ r = qdisc_new_static(QDISC_KIND_FQ_CODEL, network, filename, section_line, &qdisc);
+ if (r == -ENOMEM)
+ return log_oom();
if (r < 0)
- return r;
+ return log_syntax(unit, LOG_ERR, filename, line, r,
+ "More than one kind of queueing discipline, ignoring assignment: %m");
+
+ fqcd = FQ_CODEL(qdisc);
if (isempty(rvalue)) {
- qdisc->fq_codel.limit = 0;
+ fqcd->limit = 0;
qdisc = NULL;
return 0;
}
- r = safe_atou32(rvalue, &qdisc->fq_codel.limit);
+ r = safe_atou32(rvalue, &fqcd->limit);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
return 0;
}
- qdisc->has_fair_queuing_controlled_delay = true;
qdisc = NULL;
return 0;
}
+
+const QDiscVTable fq_codel_vtable = {
+ .object_size = sizeof(FairQueuingControlledDelay),
+ .tca_kind = "fq_codel",
+ .fill_message = fair_queuing_controlled_delay_fill_message,
+};
* Copyright © 2019 VMware, Inc. */
#pragma once
-#include "sd-netlink.h"
-
#include "conf-parser.h"
-#include "networkd-link.h"
+#include "qdisc.h"
typedef struct FairQueuingControlledDelay {
+ QDisc meta;
uint32_t limit;
} FairQueuingControlledDelay;
-int fair_queuing_controlled_delay_new(FairQueuingControlledDelay **ret);
-int fair_queuing_controlled_delay_fill_message(Link *link, const FairQueuingControlledDelay *sfq, sd_netlink_message *req);
+DEFINE_QDISC_CAST(FQ_CODEL, FairQueuingControlledDelay);
+extern const QDiscVTable fq_codel_vtable;
CONFIG_PARSER_PROTOTYPE(config_parse_tc_fair_queuing_controlled_delay_limit);
#include "string-util.h"
#include "tc-util.h"
-int network_emulator_new(NetworkEmulator **ret) {
- NetworkEmulator *ne = NULL;
-
- ne = new(NetworkEmulator, 1);
- if (!ne)
- return -ENOMEM;
-
- *ne = (NetworkEmulator) {
- .delay = USEC_INFINITY,
- .jitter = USEC_INFINITY,
- };
-
- *ret = TAKE_PTR(ne);
-
- return 0;
-}
-
-int network_emulator_fill_message(Link *link, const NetworkEmulator *ne, sd_netlink_message *req) {
+static int network_emulator_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
struct tc_netem_qopt opt = {
.limit = 1000,
};
+ NetworkEmulator *ne;
int r;
assert(link);
- assert(ne);
+ assert(qdisc);
assert(req);
+ ne = NETEM(qdisc);
+
if (ne->limit > 0)
opt.limit = ne->limit;
_cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
Network *network = data;
+ NetworkEmulator *ne;
usec_t u;
int r;
assert(rvalue);
assert(data);
- r = qdisc_new_static(network, filename, section_line, &qdisc);
+ r = qdisc_new_static(QDISC_KIND_NETEM, network, filename, section_line, &qdisc);
+ if (r == -ENOMEM)
+ return log_oom();
if (r < 0)
- return r;
+ return log_syntax(unit, LOG_ERR, filename, line, r,
+ "More than one kind of queueing discipline, ignoring assignment: %m");
+
+ ne = NETEM(qdisc);
if (isempty(rvalue)) {
if (streq(lvalue, "NetworkEmulatorDelaySec"))
- qdisc->ne.delay = USEC_INFINITY;
+ ne->delay = USEC_INFINITY;
else if (streq(lvalue, "NetworkEmulatorDelayJitterSec"))
- qdisc->ne.jitter = USEC_INFINITY;
+ ne->jitter = USEC_INFINITY;
qdisc = NULL;
return 0;
}
if (streq(lvalue, "NetworkEmulatorDelaySec"))
- qdisc->ne.delay = u;
+ ne->delay = u;
else if (streq(lvalue, "NetworkEmulatorDelayJitterSec"))
- qdisc->ne.jitter = u;
+ ne->jitter = u;
- qdisc->has_network_emulator = true;
qdisc = NULL;
return 0;
_cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
Network *network = data;
+ NetworkEmulator *ne;
uint32_t rate;
int r;
assert(rvalue);
assert(data);
- r = qdisc_new_static(network, filename, section_line, &qdisc);
+ r = qdisc_new_static(QDISC_KIND_NETEM, network, filename, section_line, &qdisc);
+ if (r == -ENOMEM)
+ return log_oom();
if (r < 0)
- return r;
+ return log_syntax(unit, LOG_ERR, filename, line, r,
+ "More than one kind of queueing discipline, ignoring assignment: %m");
+
+ ne = NETEM(qdisc);
if (isempty(rvalue)) {
- qdisc->ne.loss = 0;
+ if (streq(lvalue, "NetworkEmulatorLossRate"))
+ ne->loss = 0;
+ else if (streq(lvalue, "NetworkEmulatorDuplicateRate"))
+ ne->duplicate = 0;
qdisc = NULL;
return 0;
}
if (streq(lvalue, "NetworkEmulatorLossRate"))
- qdisc->ne.loss = rate;
+ ne->loss = rate;
else if (streq(lvalue, "NetworkEmulatorDuplicateRate"))
- qdisc->ne.duplicate = rate;
+ ne->duplicate = rate;
qdisc = NULL;
return 0;
_cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
Network *network = data;
+ NetworkEmulator *ne;
int r;
assert(filename);
assert(rvalue);
assert(data);
- r = qdisc_new_static(network, filename, section_line, &qdisc);
+ r = qdisc_new_static(QDISC_KIND_NETEM, network, filename, section_line, &qdisc);
+ if (r == -ENOMEM)
+ return log_oom();
if (r < 0)
- return r;
+ return log_syntax(unit, LOG_ERR, filename, line, r,
+ "More than one kind of queueing discipline, ignoring assignment: %m");
+
+ ne = NETEM(qdisc);
if (isempty(rvalue)) {
- qdisc->ne.limit = 0;
+ ne->limit = 0;
qdisc = NULL;
return 0;
}
- r = safe_atou(rvalue, &qdisc->ne.limit);
+ r = safe_atou(rvalue, &ne->limit);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse 'NetworkEmulatorPacketLimit=', ignoring assignment: %s",
qdisc = NULL;
return 0;
}
+
+const QDiscVTable netem_vtable = {
+ .object_size = sizeof(NetworkEmulator),
+ .tca_kind = "netem",
+ .fill_message = network_emulator_fill_message,
+};
* Copyright © 2019 VMware, Inc. */
#pragma once
-#include "sd-netlink.h"
-
#include "conf-parser.h"
-#include "networkd-link.h"
+#include "qdisc.h"
#include "time-util.h"
typedef struct NetworkEmulator {
+ QDisc meta;
+
usec_t delay;
usec_t jitter;
uint32_t duplicate;
} NetworkEmulator;
-int network_emulator_new(NetworkEmulator **ret);
-int network_emulator_fill_message(Link *link, const NetworkEmulator *ne, sd_netlink_message *req);
+DEFINE_QDISC_CAST(NETEM, NetworkEmulator);
+extern const QDiscVTable netem_vtable;
CONFIG_PARSER_PROTOTYPE(config_parse_tc_network_emulator_delay);
CONFIG_PARSER_PROTOTYPE(config_parse_tc_network_emulator_rate);
#include "set.h"
#include "string-util.h"
-static int qdisc_new(QDisc **ret) {
+const QDiscVTable * const qdisc_vtable[_QDISC_KIND_MAX] = {
+ [QDISC_KIND_FQ_CODEL] = &fq_codel_vtable,
+ [QDISC_KIND_NETEM] = &netem_vtable,
+ [QDISC_KIND_SFQ] = &sfq_vtable,
+ [QDISC_KIND_TBF] = &tbf_vtable,
+};
+
+static int qdisc_new(QDiscKind kind, QDisc **ret) {
QDisc *qdisc;
- qdisc = new(QDisc, 1);
- if (!qdisc)
- return -ENOMEM;
+ if (kind == _QDISC_KIND_INVALID) {
+ qdisc = new(QDisc, 1);
+ if (!qdisc)
+ return -ENOMEM;
- *qdisc = (QDisc) {
- .family = AF_UNSPEC,
- .parent = TC_H_ROOT,
- };
+ *qdisc = (QDisc) {
+ .family = AF_UNSPEC,
+ .parent = TC_H_ROOT,
+ .kind = kind,
+ };
+ } else {
+ qdisc = malloc0(qdisc_vtable[kind]->object_size);
+ if (!qdisc)
+ return -ENOMEM;
+
+ qdisc->family = AF_UNSPEC;
+ qdisc->parent = TC_H_ROOT;
+ qdisc->kind = kind;
+ }
*ret = TAKE_PTR(qdisc);
return 0;
}
-int qdisc_new_static(Network *network, const char *filename, unsigned section_line, QDisc **ret) {
+int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(qdisc_freep) QDisc *qdisc = NULL;
+ QDisc *existing;
int r;
assert(network);
assert(ret);
- assert(!!filename == (section_line > 0));
+ assert(filename);
+ assert(section_line > 0);
- if (filename) {
- r = network_config_section_new(filename, section_line, &n);
- if (r < 0)
- return r;
+ r = network_config_section_new(filename, section_line, &n);
+ if (r < 0)
+ return r;
- qdisc = ordered_hashmap_get(network->qdiscs_by_section, n);
- if (qdisc) {
- *ret = TAKE_PTR(qdisc);
+ existing = ordered_hashmap_get(network->qdiscs_by_section, n);
+ if (existing) {
+ if (existing->kind != _QDISC_KIND_INVALID &&
+ kind != _QDISC_KIND_INVALID &&
+ existing->kind != kind)
+ return -EINVAL;
+ if (existing->kind == kind || kind == _QDISC_KIND_INVALID) {
+ *ret = existing;
return 0;
}
}
- r = qdisc_new(&qdisc);
+ r = qdisc_new(kind, &qdisc);
if (r < 0)
return r;
- qdisc->network = network;
+ if (existing) {
+ qdisc->family = existing->family;
+ qdisc->handle = existing->handle;
+ qdisc->parent = existing->parent;
+ qdisc->tca_kind = TAKE_PTR(existing->tca_kind);
- if (filename) {
- qdisc->section = TAKE_PTR(n);
+ qdisc_free(ordered_hashmap_remove(network->qdiscs_by_section, n));
+ }
- r = ordered_hashmap_ensure_allocated(&network->qdiscs_by_section, &network_config_hash_ops);
- if (r < 0)
- return r;
+ qdisc->network = network;
+ qdisc->section = TAKE_PTR(n);
- r = ordered_hashmap_put(network->qdiscs_by_section, qdisc->section, qdisc);
- if (r < 0)
- return r;
- }
+ r = ordered_hashmap_ensure_allocated(&network->qdiscs_by_section, &network_config_hash_ops);
+ if (r < 0)
+ return r;
- *ret = TAKE_PTR(qdisc);
+ r = ordered_hashmap_put(network->qdiscs_by_section, qdisc->section, qdisc);
+ if (r < 0)
+ return r;
+ *ret = TAKE_PTR(qdisc);
return 0;
}
int qdisc_configure(Link *link, QDisc *qdisc) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
- _cleanup_free_ char *tca_kind = NULL;
- char *p;
int r;
assert(link);
return log_link_error_errno(link, r, "Could not set tcm_handle message: %m");
}
- if (qdisc->has_network_emulator) {
- r = free_and_strdup(&tca_kind, "netem");
+ if (QDISC_VTABLE(qdisc)) {
+ r = sd_netlink_message_append_string(req, TCA_KIND, QDISC_VTABLE(qdisc)->tca_kind);
if (r < 0)
- return log_oom();
-
- r = network_emulator_fill_message(link, &qdisc->ne, req);
- if (r < 0)
- return r;
- }
-
- if (qdisc->has_token_buffer_filter) {
- r = free_and_strdup(&tca_kind, "tbf");
- if (r < 0)
- return log_oom();
-
- r = token_buffer_filter_fill_message(link, &qdisc->tbf, req);
- if (r < 0)
- return r;
- }
-
- if (qdisc->has_stochastic_fairness_queueing) {
- r = free_and_strdup(&tca_kind, "sfq");
- if (r < 0)
- return log_oom();
-
- r = stochastic_fairness_queueing_fill_message(link, &qdisc->sfq, req);
- if (r < 0)
- return r;
- }
-
- if (qdisc->has_fair_queuing_controlled_delay) {
- r = free_and_strdup(&tca_kind, "fq_codel");
- if (r < 0)
- return log_oom();
+ return log_link_error_errno(link, r, "Could not append TCA_KIND attribute: %m");
- r = fair_queuing_controlled_delay_fill_message(link, &qdisc->fq_codel, req);
+ r = QDISC_VTABLE(qdisc)->fill_message(link, qdisc, req);
if (r < 0)
return r;
- }
-
- p = tca_kind ?:qdisc->tca_kind;
- if (p) {
- r = sd_netlink_message_append_string(req, TCA_KIND, p);
+ } else {
+ r = sd_netlink_message_append_string(req, TCA_KIND, qdisc->tca_kind);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_KIND attribute: %m");
}
}
int qdisc_section_verify(QDisc *qdisc, bool *has_root, bool *has_clsact) {
- unsigned i;
int r;
assert(qdisc);
if (section_is_invalid(qdisc->section))
return -EINVAL;
- i = qdisc->has_network_emulator + qdisc->has_token_buffer_filter + qdisc->has_stochastic_fairness_queueing;
- if (i > 1)
- return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
- "%s: TrafficControlQueueingDiscipline section has more than one type of discipline. "
- "Ignoring [TrafficControlQueueingDiscipline] section from line %u.",
- qdisc->section->filename, qdisc->section->line);
-
- if (qdisc->has_token_buffer_filter) {
- r = token_buffer_filter_section_verify(&qdisc->tbf, qdisc->section);
+ if (QDISC_VTABLE(qdisc) && QDISC_VTABLE(qdisc)->verify) {
+ r = QDISC_VTABLE(qdisc)->verify(qdisc);
if (r < 0)
return r;
}
assert(rvalue);
assert(data);
- r = qdisc_new_static(network, filename, section_line, &qdisc);
+ r = qdisc_new_static(_QDISC_KIND_INVALID, network, filename, section_line, &qdisc);
if (r < 0)
return r;
#pragma once
#include "conf-parser.h"
-#include "fq-codel.h"
-#include "netem.h"
#include "networkd-link.h"
#include "networkd-network.h"
#include "networkd-util.h"
-#include "sfq.h"
-#include "tbf.h"
+
+typedef enum QDiscKind {
+ QDISC_KIND_FQ_CODEL,
+ QDISC_KIND_NETEM,
+ QDISC_KIND_SFQ,
+ QDISC_KIND_TBF,
+ _QDISC_KIND_MAX,
+ _QDISC_KIND_INVALID = -1,
+} QDiscKind;
typedef struct QDisc {
NetworkConfigSection *section;
Network *network;
- Link *link;
-
int family;
-
uint32_t handle;
uint32_t parent;
char *tca_kind;
- bool has_network_emulator:1;
- bool has_token_buffer_filter:1;
- bool has_stochastic_fairness_queueing:1;
- bool has_fair_queuing_controlled_delay:1;
-
- NetworkEmulator ne;
- TokenBufferFilter tbf;
- StochasticFairnessQueueing sfq;
- FairQueuingControlledDelay fq_codel;
+ QDiscKind kind;
} QDisc;
+typedef struct QDiscVTable {
+ size_t object_size;
+ const char *tca_kind;
+ int (*fill_message)(Link *link, QDisc *qdisc, sd_netlink_message *m);
+ int (*verify)(QDisc *qdisc);
+} QDiscVTable;
+
+extern const QDiscVTable * const qdisc_vtable[_QDISC_KIND_MAX];
+
+#define QDISC_VTABLE(q) ((q)->kind != _QDISC_KIND_INVALID ? qdisc_vtable[(q)->kind] : NULL)
+
+/* For casting a qdisc into the various qdisc kinds */
+#define DEFINE_QDISC_CAST(UPPERCASE, MixedCase) \
+ static inline MixedCase* UPPERCASE(QDisc *q) { \
+ if (_unlikely_(!q || q->kind != QDISC_KIND_##UPPERCASE)) \
+ return NULL; \
+ \
+ return (MixedCase*) q; \
+ }
+
+/* For casting the various qdisc kinds into a qdisc */
+#define QDISC(q) (&(q)->meta)
+
void qdisc_free(QDisc *qdisc);
-int qdisc_new_static(Network *network, const char *filename, unsigned section_line, QDisc **ret);
+int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret);
int qdisc_configure(Link *link, QDisc *qdisc);
-
int qdisc_section_verify(QDisc *qdisc, bool *has_root, bool *has_clsact);
DEFINE_NETWORK_SECTION_FUNCTIONS(QDisc, qdisc_free);
CONFIG_PARSER_PROTOTYPE(config_parse_tc_qdiscs_parent);
+
+#include "fq-codel.h"
+#include "netem.h"
+#include "sfq.h"
+#include "tbf.h"
#include "sfq.h"
#include "string-util.h"
-int stochastic_fairness_queueing_new(StochasticFairnessQueueing **ret) {
- StochasticFairnessQueueing *sfq = NULL;
-
- sfq = new0(StochasticFairnessQueueing, 1);
- if (!sfq)
- return -ENOMEM;
-
- *ret = TAKE_PTR(sfq);
-
- return 0;
-}
-
-int stochastic_fairness_queueing_fill_message(Link *link, const StochasticFairnessQueueing *sfq, sd_netlink_message *req) {
+static int stochastic_fairness_queueing_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
+ StochasticFairnessQueueing *sfq;
struct tc_sfq_qopt_v1 opt = {};
int r;
assert(link);
- assert(sfq);
+ assert(qdisc);
assert(req);
+ sfq = SFQ(qdisc);
+
opt.v0.perturb_period = sfq->perturb_period / USEC_PER_SEC;
r = sd_netlink_message_append_data(req, TCA_OPTIONS, &opt, sizeof(struct tc_sfq_qopt_v1));
void *userdata) {
_cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
+ StochasticFairnessQueueing *sfq;
Network *network = data;
int r;
assert(rvalue);
assert(data);
- r = qdisc_new_static(network, filename, section_line, &qdisc);
+ r = qdisc_new_static(QDISC_KIND_SFQ, network, filename, section_line, &qdisc);
+ if (r == -ENOMEM)
+ return log_oom();
if (r < 0)
- return r;
+ return log_syntax(unit, LOG_ERR, filename, line, r,
+ "More than one kind of queueing discipline, ignoring assignment: %m");
+
+ sfq = SFQ(qdisc);
if (isempty(rvalue)) {
- qdisc->sfq.perturb_period = 0;
+ sfq->perturb_period = 0;
qdisc = NULL;
return 0;
}
- r = parse_sec(rvalue, &qdisc->sfq.perturb_period);
+ r = parse_sec(rvalue, &sfq->perturb_period);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
return 0;
}
- qdisc->has_stochastic_fairness_queueing = true;
qdisc = NULL;
return 0;
}
+
+const QDiscVTable sfq_vtable = {
+ .object_size = sizeof(StochasticFairnessQueueing),
+ .tca_kind = "sfq",
+ .fill_message = stochastic_fairness_queueing_fill_message,
+};
* Copyright © 2019 VMware, Inc. */
#pragma once
-#include "sd-netlink.h"
-
#include "conf-parser.h"
-#include "networkd-link.h"
+#include "qdisc.h"
+#include "time-util.h"
typedef struct StochasticFairnessQueueing {
+ QDisc meta;
+
usec_t perturb_period;
} StochasticFairnessQueueing;
-int stochastic_fairness_queueing_new(StochasticFairnessQueueing **ret);
-int stochastic_fairness_queueing_fill_message(Link *link, const StochasticFairnessQueueing *sfq, sd_netlink_message *req);
+DEFINE_QDISC_CAST(SFQ, StochasticFairnessQueueing);
+extern const QDiscVTable sfq_vtable;
CONFIG_PARSER_PROTOTYPE(config_parse_tc_stochastic_fairness_queueing_perturb_period);
#include "tc-util.h"
#include "util.h"
-int token_buffer_filter_new(TokenBufferFilter **ret) {
- TokenBufferFilter *ne = NULL;
-
- ne = new0(TokenBufferFilter, 1);
- if (!ne)
- return -ENOMEM;
-
- *ret = TAKE_PTR(ne);
-
- return 0;
-}
-
-int token_buffer_filter_fill_message(Link *link, const TokenBufferFilter *tbf, sd_netlink_message *req) {
+static int token_buffer_filter_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
uint32_t rtab[256], ptab[256];
struct tc_tbf_qopt opt = {};
+ TokenBufferFilter *tbf;
int r;
assert(link);
- assert(tbf);
+ assert(qdisc);
assert(req);
+ tbf = TBF(qdisc);
+
opt.rate.rate = tbf->rate >= (1ULL << 32) ? ~0U : tbf->rate;
opt.peakrate.rate = tbf->peak_rate >= (1ULL << 32) ? ~0U : tbf->peak_rate;
_cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
Network *network = data;
+ TokenBufferFilter *tbf;
uint64_t k;
int r;
assert(rvalue);
assert(data);
- r = qdisc_new_static(network, filename, section_line, &qdisc);
+ r = qdisc_new_static(QDISC_KIND_TBF, network, filename, section_line, &qdisc);
+ if (r == -ENOMEM)
+ return log_oom();
if (r < 0)
- return r;
+ return log_syntax(unit, LOG_ERR, filename, line, r,
+ "More than one kind of queueing discipline, ignoring assignment: %m");
+
+ tbf = TBF(qdisc);
if (isempty(rvalue)) {
if (streq(lvalue, "TokenBufferFilterRate"))
- qdisc->tbf.rate = 0;
+ tbf->rate = 0;
else if (streq(lvalue, "TokenBufferFilterBurst"))
- qdisc->tbf.burst = 0;
+ tbf->burst = 0;
else if (streq(lvalue, "TokenBufferFilterLimitSize"))
- qdisc->tbf.limit = 0;
+ tbf->limit = 0;
else if (streq(lvalue, "TokenBufferFilterMTUBytes"))
- qdisc->tbf.mtu = 0;
+ tbf->mtu = 0;
else if (streq(lvalue, "TokenBufferFilterMPUBytes"))
- qdisc->tbf.mpu = 0;
+ tbf->mpu = 0;
else if (streq(lvalue, "TokenBufferFilterPeakRate"))
- qdisc->tbf.peak_rate = 0;
+ tbf->peak_rate = 0;
qdisc = NULL;
return 0;
}
if (streq(lvalue, "TokenBufferFilterRate"))
- qdisc->tbf.rate = k / 8;
+ tbf->rate = k / 8;
else if (streq(lvalue, "TokenBufferFilterBurst"))
- qdisc->tbf.burst = k;
+ tbf->burst = k;
else if (streq(lvalue, "TokenBufferFilterLimitSize"))
- qdisc->tbf.limit = k;
+ tbf->limit = k;
else if (streq(lvalue, "TokenBufferFilterMPUBytes"))
- qdisc->tbf.mpu = k;
+ tbf->mpu = k;
else if (streq(lvalue, "TokenBufferFilterMTUBytes"))
- qdisc->tbf.mtu = k;
+ tbf->mtu = k;
else if (streq(lvalue, "TokenBufferFilterPeakRate"))
- qdisc->tbf.peak_rate = k / 8;
+ tbf->peak_rate = k / 8;
- qdisc->has_token_buffer_filter = true;
qdisc = NULL;
return 0;
_cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
Network *network = data;
+ TokenBufferFilter *tbf;
usec_t u;
int r;
assert(rvalue);
assert(data);
- r = qdisc_new_static(network, filename, section_line, &qdisc);
+ r = qdisc_new_static(QDISC_KIND_TBF, network, filename, section_line, &qdisc);
+ if (r == -ENOMEM)
+ return log_oom();
if (r < 0)
- return r;
+ return log_syntax(unit, LOG_ERR, filename, line, r,
+ "More than one kind of queueing discipline, ignoring assignment: %m");
+
+ tbf = TBF(qdisc);
if (isempty(rvalue)) {
- qdisc->tbf.latency = 0;
+ tbf->latency = 0;
qdisc = NULL;
return 0;
return 0;
}
- qdisc->tbf.latency = u;
+ tbf->latency = u;
- qdisc->has_token_buffer_filter = true;
qdisc = NULL;
return 0;
}
-int token_buffer_filter_section_verify(const TokenBufferFilter *tbf, const NetworkConfigSection *section) {
+static int token_buffer_filter_verify(QDisc *qdisc) {
+ TokenBufferFilter *tbf = TBF(qdisc);
+
if (tbf->limit > 0 && tbf->latency > 0)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Specifying both TokenBufferFilterLimitSize= and TokenBufferFilterLatencySec= is not allowed. "
"Ignoring [TrafficControlQueueingDiscipline] section from line %u.",
- section->filename, section->line);
+ qdisc->section->filename, qdisc->section->line);
if (tbf->limit == 0 && tbf->latency == 0)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Either TokenBufferFilterLimitSize= or TokenBufferFilterLatencySec= is required. "
"Ignoring [TrafficControlQueueingDiscipline] section from line %u.",
- section->filename, section->line);
+ qdisc->section->filename, qdisc->section->line);
if (tbf->rate == 0)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: TokenBufferFilterRate= is mandatory. "
"Ignoring [TrafficControlQueueingDiscipline] section from line %u.",
- section->filename, section->line);
+ qdisc->section->filename, qdisc->section->line);
if (tbf->burst == 0)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: TokenBufferFilterBurst= is mandatory. "
"Ignoring [TrafficControlQueueingDiscipline] section from line %u.",
- section->filename, section->line);
+ qdisc->section->filename, qdisc->section->line);
if (tbf->peak_rate > 0 && tbf->mtu == 0)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: TokenBufferFilterMTUBytes= is mandatory when TokenBufferFilterPeakRate= is specified. "
"Ignoring [TrafficControlQueueingDiscipline] section from line %u.",
- section->filename, section->line);
+ qdisc->section->filename, qdisc->section->line);
return 0;
}
+
+const QDiscVTable tbf_vtable = {
+ .object_size = sizeof(TokenBufferFilter),
+ .tca_kind = "tbf",
+ .fill_message = token_buffer_filter_fill_message,
+ .verify = token_buffer_filter_verify
+};
* Copyright © 2019 VMware, Inc. */
#pragma once
-#include "sd-netlink.h"
-
#include "conf-parser.h"
-#include "networkd-link.h"
-#include "networkd-util.h"
-#include "tc-util.h"
+#include "qdisc.h"
+#include "time-util.h"
typedef struct TokenBufferFilter {
+ QDisc meta;
+
uint64_t rate;
uint64_t peak_rate;
uint32_t burst;
size_t mpu;
} TokenBufferFilter;
-int token_buffer_filter_new(TokenBufferFilter **ret);
-int token_buffer_filter_fill_message(Link *link, const TokenBufferFilter *tbf, sd_netlink_message *req);
-int token_buffer_filter_section_verify(const TokenBufferFilter *tbf, const NetworkConfigSection *section);
+DEFINE_QDISC_CAST(TBF, TokenBufferFilter);
+extern const QDiscVTable tbf_vtable;
CONFIG_PARSER_PROTOTYPE(config_parse_tc_token_buffer_filter_latency);
CONFIG_PARSER_PROTOTYPE(config_parse_tc_token_buffer_filter_size);