Compare commits

..

12 Commits

Author SHA1 Message Date
Yu Watanabe 161bc1b627
Merge pull request #16057 from keszybz/resolvectl-sorted-no-nta
Drop NTA lists from resolvectl status and sort output by link number
2020-06-04 11:30:14 +09:00
Yu Watanabe bb9a9e33c9
Merge pull request #15171 from ssahani/tc-qfq
network: TC- Introduce Quick Fair Queueing (QFQ)
2020-06-04 11:17:42 +09:00
Zbigniew Jędrzejewski-Szmek 33bece166c basic/sort-util: adorn qsort_safe with a prefix underscore
It should not be used directly since we have typesafe_qsort(), so
let's mark it appropriately.
2020-06-03 15:31:28 +02:00
Zbigniew Jędrzejewski-Szmek bacafb0990 pstore: use typesafe_qsort
Also move "allocated" above "n", since, conceptually, it is modified
earlier (and that is the definition order we normally use).
2020-06-03 15:31:28 +02:00
Zbigniew Jędrzejewski-Szmek eb10767565 resolvect: sort status output by link number
This makes the output more predictable. Also, interesting interfaces
are often the low-numbered ones (actual hardware links, not virtual
devices stacked on top), and this makes them more visible.
2020-06-03 15:31:28 +02:00
Zbigniew Jędrzejewski-Szmek c9d243cdef resolvectl,systemctl: reduce scope of variables 2020-06-03 15:31:28 +02:00
Zbigniew Jędrzejewski-Szmek 6cf3011c6c Introduce strcasecmp_ptr() and use it in a few places 2020-06-03 15:31:28 +02:00
Zbigniew Jędrzejewski-Szmek 6773049a4c resolvectl: do not show NTA lists in status
Those lists are very long and use up a significant chunk of screen real estate.
But the contents are mostly static (usually they just reflect built-in
configuration). Let's just not show them in 'status' output. They can still
be viewed with 'nta' verb.
2020-06-03 15:31:28 +02:00
Yu Watanabe 891ff9633f test-network: add tests for QFQ 2020-06-03 17:25:48 +09:00
Yu Watanabe 4d7ddaf97b network: tc: introduce [QuickFairQueueingClass] section 2020-06-03 17:25:44 +09:00
Susant Sahani b12aaee5ab network: tc: introduce Quick Fair Queueing (QFQ) 2020-06-03 14:17:51 +09:00
Susant Sahani c33f1e5a3f sd-netlink: add netlink properties of Quick Fair Queueing (QFQ) 2020-06-03 13:41:44 +09:00
21 changed files with 380 additions and 85 deletions

View File

@ -3252,6 +3252,45 @@
</variablelist>
</refsect1>
<refsect1>
<title>[QuickFairQueueing] Section Options</title>
<para>The <literal>[QuickFairQueueing]</literal> section manages the queueing discipline
(qdisc) of Quick Fair Queueing (QFQ).</para>
<variablelist class='network-directives'>
<xi:include href="tc.xml" xpointer="qdisc-parent" />
<xi:include href="tc.xml" xpointer="qdisc-handle" />
</variablelist>
</refsect1>
<refsect1>
<title>[QuickFairQueueingClass] Section Options</title>
<para>The <literal>[QuickFairQueueingClass]</literal> section manages the traffic control class of
Quick Fair Queueing (qfq).</para>
<variablelist class='network-directives'>
<xi:include href="tc.xml" xpointer="tclass-parent" />
<xi:include href="tc.xml" xpointer="tclass-classid" />
<varlistentry>
<term><varname>Weight=</varname></term>
<listitem>
<para>Specifies the weight of the class. Takse an integer in the range 1..1023. Defaults to
unset in which case the kernel default is used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>MaxPacketSize=</varname></term>
<listitem>
<para>Specifies the maximum packet size in bytes for the class. When suffixed with K, M, or G, the specified
size is parsed as Kilobytes, Megabytes, or Gigabytes, respectively, to the base of 1000. When unset,
the kernel default is used.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>[BridgeVLAN] Section Options</title>
<para>The <literal>[BridgeVLAN]</literal> section manages the VLAN ID configuration of a bridge port and accepts

View File

@ -39,7 +39,7 @@ static inline void* bsearch_safe(const void *key, const void *base,
* Normal qsort requires base to be nonnull. Here were require
* that only if nmemb > 0.
*/
static inline void qsort_safe(void *base, size_t nmemb, size_t size, __compar_fn_t compar) {
static inline void _qsort_safe(void *base, size_t nmemb, size_t size, __compar_fn_t compar) {
if (nmemb <= 1)
return;
@ -52,7 +52,7 @@ static inline void qsort_safe(void *base, size_t nmemb, size_t size, __compar_fn
#define typesafe_qsort(p, n, func) \
({ \
int (*_func_)(const typeof(p[0])*, const typeof(p[0])*) = func; \
qsort_safe((p), (n), sizeof((p)[0]), (__compar_fn_t) _func_); \
_qsort_safe((p), (n), sizeof((p)[0]), (__compar_fn_t) _func_); \
})
static inline void qsort_r_safe(void *base, size_t nmemb, size_t size, __compar_d_fn_t compar, void *userdata) {

View File

@ -19,18 +19,19 @@
#include "util.h"
int strcmp_ptr(const char *a, const char *b) {
/* Like strcmp(), but tries to make sense of NULL pointers */
if (a && b)
return strcmp(a, b);
return CMP(a, b); /* Direct comparison of pointers, one of which is NULL */
}
if (!a && b)
return -1;
int strcasecmp_ptr(const char *a, const char *b) {
/* Like strcasecmp(), but tries to make sense of NULL pointers */
if (a && !b)
return 1;
return 0;
if (a && b)
return strcasecmp(a, b);
return CMP(a, b); /* Direct comparison of pointers, one of which is NULL */
}
char* endswith(const char *s, const char *postfix) {

View File

@ -27,6 +27,7 @@
#define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0)
int strcmp_ptr(const char *a, const char *b) _pure_;
int strcasecmp_ptr(const char *a, const char *b) _pure_;
static inline bool streq_ptr(const char *a, const char *b) {
return strcmp_ptr(a, b) == 0;

View File

@ -810,6 +810,11 @@ static const NLType rtnl_tca_option_data_pie_types[] = {
[TCA_PIE_LIMIT] = { .type = NETLINK_TYPE_U32 },
};
static const NLType rtnl_tca_option_data_qfq_types[] = {
[TCA_QFQ_WEIGHT] = { .type = NETLINK_TYPE_U32 },
[TCA_QFQ_LMAX] = { .type = NETLINK_TYPE_U32 },
};
static const NLType rtnl_tca_option_data_sfb_types[] = {
[TCA_SFB_PARMS] = { .size = sizeof(struct tc_sfb_qopt) },
};
@ -834,6 +839,7 @@ static const char* const nl_union_tca_option_data_table[] = {
[NL_UNION_TCA_OPTION_DATA_HHF] = "hhf",
[NL_UNION_TCA_OPTION_DATA_HTB] = "htb",
[NL_UNION_TCA_OPTION_DATA_PIE] = "pie",
[NL_UNION_TCA_OPTION_DATA_QFQ] = "qfq",
[NL_UNION_TCA_OPTION_DATA_SFB] = "sfb",
[NL_UNION_TCA_OPTION_DATA_TBF] = "tbf",
};
@ -859,6 +865,8 @@ static const NLTypeSystem rtnl_tca_option_data_type_systems[] = {
.types = rtnl_tca_option_data_htb_types },
[NL_UNION_TCA_OPTION_DATA_PIE] = { .count = ELEMENTSOF(rtnl_tca_option_data_pie_types),
.types = rtnl_tca_option_data_pie_types },
[NL_UNION_TCA_OPTION_DATA_QFQ] = { .count = ELEMENTSOF(rtnl_tca_option_data_qfq_types),
.types = rtnl_tca_option_data_qfq_types },
[NL_UNION_TCA_OPTION_DATA_SFB] = { .count = ELEMENTSOF(rtnl_tca_option_data_sfb_types),
.types = rtnl_tca_option_data_sfb_types },
[NL_UNION_TCA_OPTION_DATA_TBF] = { .count = ELEMENTSOF(rtnl_tca_option_data_tbf_types),

View File

@ -105,6 +105,7 @@ typedef enum NLUnionTCAOptionData {
NL_UNION_TCA_OPTION_DATA_HHF,
NL_UNION_TCA_OPTION_DATA_HTB,
NL_UNION_TCA_OPTION_DATA_PIE,
NL_UNION_TCA_OPTION_DATA_QFQ,
NL_UNION_TCA_OPTION_DATA_SFB,
NL_UNION_TCA_OPTION_DATA_TBF,
_NL_UNION_TCA_OPTION_DATA_MAX,

View File

@ -131,6 +131,8 @@ sources = files('''
tc/pie.h
tc/qdisc.c
tc/qdisc.h
tc/qfq.c
tc/qfq.h
tc/sfb.c
tc/sfb.h
tc/sfq.c

View File

@ -312,6 +312,12 @@ PFIFOFast.Handle, config_parse_qdisc_handle,
PFIFOHeadDrop.Parent, config_parse_qdisc_parent, QDISC_KIND_PFIFO_HEAD_DROP, 0
PFIFOHeadDrop.Handle, config_parse_qdisc_handle, QDISC_KIND_PFIFO_HEAD_DROP, 0
PFIFOHeadDrop.PacketLimit, config_parse_pfifo_size, QDISC_KIND_PFIFO_HEAD_DROP, 0
QuickFairQueueing.Parent, config_parse_qdisc_parent, QDISC_KIND_QFQ, 0
QuickFairQueueing.Handle, config_parse_qdisc_handle, QDISC_KIND_QFQ, 0
QuickFairQueueingClass.Parent, config_parse_tclass_parent, TCLASS_KIND_QFQ, 0
QuickFairQueueingClass.ClassId, config_parse_tclass_classid, TCLASS_KIND_QFQ, 0
QuickFairQueueingClass.Weight, config_parse_quick_fair_queueing_weight, TCLASS_KIND_QFQ, 0
QuickFairQueueingClass.MaxPacketSize, config_parse_quick_fair_queueing_max_packet, TCLASS_KIND_QFQ, 0
FairQueueing.Parent, config_parse_qdisc_parent, QDISC_KIND_FQ, 0
FairQueueing.Handle, config_parse_qdisc_handle, QDISC_KIND_FQ, 0
FairQueueing.PacketLimit, config_parse_fair_queueing_u32, QDISC_KIND_FQ, 0

View File

@ -508,9 +508,6 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
"ControlledDelay\0"
"DeficitRoundRobinScheduler\0"
"DeficitRoundRobinSchedulerClass\0"
"PFIFO\0"
"PFIFOFast\0"
"PFIFOHeadDrop\0"
"FairQueueing\0"
"FairQueueingControlledDelay\0"
"GenericRandomEarlyDetection\0"
@ -518,7 +515,12 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
"HierarchyTokenBucket\0"
"HierarchyTokenBucketClass\0"
"NetworkEmulator\0"
"PFIFO\0"
"PFIFOFast\0"
"PFIFOHeadDrop\0"
"PIE\0"
"QuickFairQueueing\0"
"QuickFairQueueingClass\0"
"StochasticFairBlue\0"
"StochasticFairnessQueueing\0"
"TokenBucketFilter\0"

View File

@ -27,6 +27,7 @@ const QDiscVTable * const qdisc_vtable[_QDISC_KIND_MAX] = {
[QDISC_KIND_HTB] = &htb_vtable,
[QDISC_KIND_NETEM] = &netem_vtable,
[QDISC_KIND_PIE] = &pie_vtable,
[QDISC_KIND_QFQ] = &qfq_vtable,
[QDISC_KIND_PFIFO] = &pfifo_vtable,
[QDISC_KIND_PFIFO_FAST] = &pfifo_fast_vtable,
[QDISC_KIND_PFIFO_HEAD_DROP] = &pfifo_head_drop_vtable,

View File

@ -23,6 +23,7 @@ typedef enum QDiscKind {
QDISC_KIND_PFIFO_FAST,
QDISC_KIND_PFIFO_HEAD_DROP,
QDISC_KIND_PIE,
QDISC_KIND_QFQ,
QDISC_KIND_SFB,
QDISC_KIND_SFQ,
QDISC_KIND_TBF,
@ -93,6 +94,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_qdisc_handle);
#include "hhf.h"
#include "htb.h"
#include "pie.h"
#include "qfq.h"
#include "netem.h"
#include "drr.h"
#include "sfb.h"

170
src/network/tc/qfq.c Normal file
View File

@ -0,0 +1,170 @@
/* SPDX-License-Identifier: LGPL-2.1+
* Copyright © 2020 VMware, Inc. */
#include <linux/pkt_sched.h>
#include "parse-util.h"
#include "qdisc.h"
#include "qfq.h"
#include "string-util.h"
#define QFQ_MAX_WEIGHT (1 << 10)
#define QFQ_MIN_MAX_PACKET 512
#define QFQ_MAX_MAX_PACKET (1 << 16)
const QDiscVTable qfq_vtable = {
.object_size = sizeof(QuickFairQueueing),
.tca_kind = "qfq",
};
static int quick_fair_queueing_class_fill_message(Link *link, TClass *tclass, sd_netlink_message *req) {
QuickFairQueueingClass *qfq;
int r;
assert(link);
assert(tclass);
assert(req);
qfq = TCLASS_TO_QFQ(tclass);
r = sd_netlink_message_open_container_union(req, TCA_OPTIONS, "qfq");
if (r < 0)
return log_link_error_errno(link, r, "Could not open container TCA_OPTIONS: %m");
if (qfq->weight > 0) {
r = sd_netlink_message_append_u32(req, TCA_QFQ_WEIGHT, qfq->weight);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_QFQ_WEIGHT attribute: %m");
}
if (qfq->max_packet > 0) {
r = sd_netlink_message_append_u32(req, TCA_QFQ_LMAX, qfq->max_packet);
if (r < 0)
return log_link_error_errno(link, r, "Could not append TCA_QFQ_LMAX attribute: %m");
}
r = sd_netlink_message_close_container(req);
if (r < 0)
return log_link_error_errno(link, r, "Could not close container TCA_OPTIONS: %m");
return 0;
}
int config_parse_quick_fair_queueing_weight(
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) {
_cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL;
QuickFairQueueingClass *qfq;
Network *network = data;
uint32_t v;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = tclass_new_static(TCLASS_KIND_QFQ, network, filename, section_line, &tclass);
if (r < 0)
return log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to create traffic control class, ignoring assignment: %m");
qfq = TCLASS_TO_QFQ(tclass);
if (isempty(rvalue)) {
qfq->weight = 0;
tclass = NULL;
return 0;
}
r = safe_atou32(rvalue, &v);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
if (v == 0 || v > QFQ_MAX_WEIGHT) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Invalid '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
qfq->weight = v;
tclass = NULL;
return 0;
}
int config_parse_quick_fair_queueing_max_packet(
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) {
_cleanup_(tclass_free_or_set_invalidp) TClass *tclass = NULL;
QuickFairQueueingClass *qfq;
Network *network = data;
uint64_t v;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = tclass_new_static(TCLASS_KIND_QFQ, network, filename, section_line, &tclass);
if (r < 0)
return log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to create traffic control class, ignoring assignment: %m");
qfq = TCLASS_TO_QFQ(tclass);
if (isempty(rvalue)) {
qfq->max_packet = 0;
tclass = NULL;
return 0;
}
r = parse_size(rvalue, 1000, &v);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
if (v < QFQ_MIN_MAX_PACKET || v > QFQ_MAX_MAX_PACKET) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Invalid '%s=', ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
qfq->max_packet = (uint32_t) v;
tclass = NULL;
return 0;
}
const TClassVTable qfq_tclass_vtable = {
.object_size = sizeof(QuickFairQueueingClass),
.tca_kind = "qfq",
.fill_message = quick_fair_queueing_class_fill_message,
};

26
src/network/tc/qfq.h Normal file
View File

@ -0,0 +1,26 @@
/* SPDX-License-Identifier: LGPL-2.1+
* Copyright © 2020 VMware, Inc. */
#pragma once
#include "conf-parser.h"
#include "qdisc.h"
typedef struct QuickFairQueueing {
QDisc meta;
} QuickFairQueueing;
DEFINE_QDISC_CAST(QFQ, QuickFairQueueing);
extern const QDiscVTable qfq_vtable;
typedef struct QuickFairQueueingClass {
TClass meta;
uint32_t weight;
uint32_t max_packet;
} QuickFairQueueingClass;
DEFINE_TCLASS_CAST(QFQ, QuickFairQueueingClass);
extern const TClassVTable qfq_tclass_vtable;
CONFIG_PARSER_PROTOTYPE(config_parse_quick_fair_queueing_weight);
CONFIG_PARSER_PROTOTYPE(config_parse_quick_fair_queueing_max_packet);

View File

@ -18,6 +18,7 @@
const TClassVTable * const tclass_vtable[_TCLASS_KIND_MAX] = {
[TCLASS_KIND_DRR] = &drr_tclass_vtable,
[TCLASS_KIND_HTB] = &htb_tclass_vtable,
[TCLASS_KIND_QFQ] = &qfq_tclass_vtable,
};
static int tclass_new(TClassKind kind, TClass **ret) {

View File

@ -11,6 +11,7 @@
typedef enum TClassKind {
TCLASS_KIND_DRR,
TCLASS_KIND_HTB,
TCLASS_KIND_QFQ,
_TCLASS_KIND_MAX,
_TCLASS_KIND_INVALID = -1,
} TClassKind;
@ -67,3 +68,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_tclass_classid);
#include "drr.h"
#include "htb.h"
#include "qfq.h"

View File

@ -101,8 +101,8 @@ typedef struct PStoreEntry {
typedef struct PStoreList {
PStoreEntry *entries;
size_t n_allocated;
size_t n_entries;
size_t n_entries_allocated;
} PStoreList;
static void pstore_entries_reset(PStoreList *list) {
@ -112,8 +112,7 @@ static void pstore_entries_reset(PStoreList *list) {
list->n_entries = 0;
}
static int compare_pstore_entries(const void *_a, const void *_b) {
PStoreEntry *a = (PStoreEntry *)_a, *b = (PStoreEntry *)_b;
static int compare_pstore_entries(const PStoreEntry *a, const PStoreEntry *b) {
return strcmp(a->dirent.d_name, b->dirent.d_name);
}
@ -349,7 +348,7 @@ static int list_files(PStoreList *list, const char *sourcepath) {
continue;
}
if (!GREEDY_REALLOC(list->entries, list->n_entries_allocated, list->n_entries + 1))
if (!GREEDY_REALLOC(list->entries, list->n_allocated, list->n_entries + 1))
return log_oom();
list->entries[list->n_entries++] = (PStoreEntry) {
@ -394,7 +393,7 @@ static int run(int argc, char *argv[]) {
/* Handle each pstore file */
/* Sort files lexigraphically ascending, generally needed by all */
qsort_safe(list.entries, list.n_entries, sizeof(PStoreEntry), compare_pstore_entries);
typesafe_qsort(list.entries, list.n_entries, compare_pstore_entries);
/* Process known file types */
process_dmesg_files(&list);

View File

@ -28,6 +28,7 @@
#include "resolved-def.h"
#include "resolved-dns-packet.h"
#include "socket-netlink.h"
#include "sort-util.h"
#include "stdio-util.h"
#include "string-table.h"
#include "strv.h"
@ -79,6 +80,21 @@ typedef enum StatusMode {
STATUS_NTA,
} StatusMode;
typedef struct InterfaceInfo {
int index;
const char *name;
} InterfaceInfo;
static int interface_info_compare(const InterfaceInfo *a, const InterfaceInfo *b) {
int r;
r = CMP(a->index, b->index);
if (r != 0)
return r;
return strcmp_ptr(a->name, b->name);
}
int ifname_mangle(const char *s) {
_cleanup_free_ char *iface = NULL;
const char *dot;
@ -1500,10 +1516,6 @@ static int status_ifindex(sd_bus *bus, int ifindex, const char *name, StatusMode
if (r < 0)
return r;
r = dump_list(table, "DNSSEC NTA:", link_info.ntas);
if (r < 0)
return r;
r = table_print(table, NULL);
if (r < 0)
return log_error_errno(r, "Failed to print table: %m");
@ -1745,11 +1757,6 @@ static int status_global(sd_bus *bus, StatusMode mode, bool *empty_line) {
if (r < 0)
return r;
strv_sort(global_info.ntas);
r = dump_list(table, "DNSSEC NTA:", global_info.ntas);
if (r < 0)
return r;
r = table_print(table, NULL);
if (r < 0)
return log_error_errno(r, "Failed to print table: %m");
@ -1762,7 +1769,6 @@ static int status_global(sd_bus *bus, StatusMode mode, bool *empty_line) {
static int status_all(sd_bus *bus, StatusMode mode) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
sd_netlink_message *i;
bool empty_line = false;
int r;
@ -1788,31 +1794,43 @@ static int status_all(sd_bus *bus, StatusMode mode) {
if (r < 0)
return log_error_errno(r, "Failed to enumerate links: %m");
r = 0;
for (i = reply; i; i = sd_netlink_message_next(i)) {
_cleanup_free_ InterfaceInfo *infos = NULL;
size_t n_allocated = 0, n_infos = 0;
for (sd_netlink_message *i = reply; i; i = sd_netlink_message_next(i)) {
const char *name;
int ifindex, q;
int ifindex;
uint16_t type;
q = sd_netlink_message_get_type(i, &type);
if (q < 0)
return rtnl_log_parse_error(q);
r = sd_netlink_message_get_type(i, &type);
if (r < 0)
return rtnl_log_parse_error(r);
if (type != RTM_NEWLINK)
continue;
q = sd_rtnl_message_link_get_ifindex(i, &ifindex);
if (q < 0)
return rtnl_log_parse_error(q);
r = sd_rtnl_message_link_get_ifindex(i, &ifindex);
if (r < 0)
return rtnl_log_parse_error(r);
if (ifindex == LOOPBACK_IFINDEX)
continue;
q = sd_netlink_message_read_string(i, IFLA_IFNAME, &name);
if (q < 0)
return rtnl_log_parse_error(q);
r = sd_netlink_message_read_string(i, IFLA_IFNAME, &name);
if (r < 0)
return rtnl_log_parse_error(r);
q = status_ifindex(bus, ifindex, name, mode, &empty_line);
if (!GREEDY_REALLOC(infos, n_allocated, n_infos + 1))
return log_oom();
infos[n_infos++] = (InterfaceInfo) { ifindex, name };
}
typesafe_qsort(infos, n_infos, interface_info_compare);
r = 0;
for (size_t i = 0; i < n_infos; i++) {
int q = status_ifindex(bus, infos[i].index, infos[i].name, mode, &empty_line);
if (q < 0 && r >= 0)
r = q;
}
@ -3042,7 +3060,7 @@ static int native_main(int argc, char *argv[], sd_bus *bus) {
static int translate(const char *verb, const char *single_arg, size_t num_args, char **args, sd_bus *bus) {
char **fake, **p;
size_t num, i;
size_t num;
assert(verb);
assert(num_args == 0 || args);
@ -3053,7 +3071,7 @@ static int translate(const char *verb, const char *single_arg, size_t num_args,
*p++ = (char *) verb;
if (single_arg)
*p++ = (char *) single_arg;
for (i = 0; i < num_args; i++)
for (size_t i = 0; i < num_args; i++)
*p++ = args[i];
optind = 0;

View File

@ -322,28 +322,17 @@ static bool install_client_side(void) {
}
static int compare_unit_info(const UnitInfo *a, const UnitInfo *b) {
const char *d1, *d2;
int r;
/* First, order by machine */
if (!a->machine && b->machine)
return -1;
if (a->machine && !b->machine)
return 1;
if (a->machine && b->machine) {
r = strcasecmp(a->machine, b->machine);
r = strcasecmp_ptr(a->machine, b->machine);
if (r != 0)
return r;
}
/* Second, order by unit type */
d1 = strrchr(a->id, '.');
d2 = strrchr(b->id, '.');
if (d1 && d2) {
r = strcasecmp(d1, d2);
r = strcasecmp_ptr(strrchr(a->id, '.'), strrchr(b->id, '.'));
if (r != 0)
return r;
}
/* Third, order by name */
return strcasecmp(a->id, b->id);
@ -408,8 +397,6 @@ static int output_table(Table *table) {
static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
_cleanup_(table_unrefp) Table *table = NULL;
const UnitInfo *u;
int job_count = 0;
int r;
table = table_new("", "unit", "load", "active", "sub", "job", "description");
@ -428,7 +415,8 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
(void) table_set_empty_string(table, "-");
for (u = unit_infos; unit_infos && u < unit_infos + c; u++) {
int job_count = 0;
for (const UnitInfo *u = unit_infos; unit_infos && u < unit_infos + c; u++) {
_cleanup_free_ char *j = NULL;
const char *on_underline = "", *on_loaded = "", *on_active = "";
const char *on_circle = "", *id;
@ -975,21 +963,15 @@ static int socket_info_compare(const struct socket_info *a, const struct socket_
assert(a);
assert(b);
if (!a->machine && b->machine)
return -1;
if (a->machine && !b->machine)
return 1;
if (a->machine && b->machine) {
r = strcasecmp(a->machine, b->machine);
r = strcasecmp_ptr(a->machine, b->machine);
if (r != 0)
return r;
}
r = strcmp(a->path, b->path);
if (r == 0)
r = strcmp(a->type, b->type);
if (r != 0)
return r;
return strcmp(a->type, b->type);
}
static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
@ -1234,15 +1216,9 @@ static int timer_info_compare(const struct timer_info *a, const struct timer_inf
assert(a);
assert(b);
if (!a->machine && b->machine)
return -1;
if (a->machine && !b->machine)
return 1;
if (a->machine && b->machine) {
r = strcasecmp(a->machine, b->machine);
r = strcasecmp_ptr(a->machine, b->machine);
if (r != 0)
return r;
}
r = CMP(a->next_elapse, b->next_elapse);
if (r != 0)

View File

@ -411,6 +411,14 @@ PacketLimit=
Parent=
Handle=
PacketLimit=
[QuickFairQueueing]
Parent=
Handle=
[QuickFairQueueingClass]
Parent=
ClassId=
Weight=
MaxPacketSize=
[DeficitRoundRobinScheduler]
Parent=
Handle=

View File

@ -0,0 +1,22 @@
[Match]
Name=test1
[Network]
IPv6AcceptRA=no
Address=10.1.2.4/16
[QuickFairQueueing]
Parent=root
Handle=0002
[QuickFairQueueingClass]
Parent=root
ClassId=0002:0030
Weight=2
MaxPacketSize=16000
[QuickFairQueueingClass]
Parent=root
ClassId=0002:0031
Weight=10
MaxPacketSize=8000

View File

@ -1676,6 +1676,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
'25-qdisc-hhf.network',
'25-qdisc-ingress-netem-compat.network',
'25-qdisc-pie.network',
'25-qdisc-qfq.network',
'25-route-ipv6-src.network',
'25-route-static.network',
'25-route-vrf.network',
@ -2423,10 +2424,11 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
self.assertRegex(output, 'prio 1 rate 1Mbit ceil 500Kbit')
def test_qdisc2(self):
copy_unit_to_networkd_unit_path('25-qdisc-drr.network', '12-dummy.netdev')
copy_unit_to_networkd_unit_path('25-qdisc-drr.network', '12-dummy.netdev',
'25-qdisc-qfq.network', '11-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable'])
self.wait_online(['dummy98:routable', 'test1:routable'])
output = check_output('tc qdisc show dev dummy98')
print(output)
@ -2435,6 +2437,14 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, 'class drr 2:30 root quantum 2000b')
output = check_output('tc qdisc show dev test1')
print(output)
self.assertRegex(output, 'qdisc qfq 2: root')
output = check_output('tc class show dev test1')
print(output)
self.assertRegex(output, 'class qfq 2:30 root weight 2 maxpkt 16000')
self.assertRegex(output, 'class qfq 2:31 root weight 10 maxpkt 8000')
@expectedFailureIfCAKEIsNotAvailable()
def test_qdisc_cake(self):
copy_unit_to_networkd_unit_path('25-qdisc-cake.network', '12-dummy.netdev')