Merge branch 'main' into next
Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
commit
8065d28218
|
|
@ -2744,7 +2744,7 @@ static int cmd_dev_param_set(struct dl *dl)
|
||||||
struct param_ctx ctx = {};
|
struct param_ctx ctx = {};
|
||||||
struct nlmsghdr *nlh;
|
struct nlmsghdr *nlh;
|
||||||
bool conv_exists;
|
bool conv_exists;
|
||||||
uint32_t val_u32;
|
uint32_t val_u32 = 0;
|
||||||
uint16_t val_u16;
|
uint16_t val_u16;
|
||||||
uint8_t val_u8;
|
uint8_t val_u8;
|
||||||
bool val_bool;
|
bool val_bool;
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ static void explain(void)
|
||||||
|
|
||||||
void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len)
|
void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
char eaddr[32];
|
char eaddr[18];
|
||||||
|
|
||||||
ether_ntoa_r((const struct ether_addr *)id->addr, eaddr);
|
ether_ntoa_r((const struct ether_addr *)id->addr, eaddr);
|
||||||
snprintf(buf, len, "%.2x%.2x.%s", id->prio[0], id->prio[1], eaddr);
|
snprintf(buf, len, "%.2x%.2x.%s", id->prio[0], id->prio[1], eaddr);
|
||||||
|
|
|
||||||
35
ip/ipnetns.c
35
ip/ipnetns.c
|
|
@ -1,5 +1,6 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#define _ATFILE_SOURCE
|
#define _ATFILE_SOURCE
|
||||||
|
#include <sys/file.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
@ -801,6 +802,7 @@ static int netns_add(int argc, char **argv, bool create)
|
||||||
const char *name;
|
const char *name;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int fd;
|
int fd;
|
||||||
|
int lock;
|
||||||
int made_netns_run_dir_mount = 0;
|
int made_netns_run_dir_mount = 0;
|
||||||
|
|
||||||
if (create) {
|
if (create) {
|
||||||
|
|
@ -831,12 +833,37 @@ static int netns_add(int argc, char **argv, bool create)
|
||||||
* namespace file in one namespace will unmount the network namespace
|
* namespace file in one namespace will unmount the network namespace
|
||||||
* file in all namespaces allowing the network namespace to be freed
|
* file in all namespaces allowing the network namespace to be freed
|
||||||
* sooner.
|
* sooner.
|
||||||
|
* These setup steps need to happen only once, as if multiple ip processes
|
||||||
|
* try to attempt the same operation at the same time, the mountpoints will
|
||||||
|
* be recursively created multiple times, eventually causing the system
|
||||||
|
* to lock up. For example, this has been observed when multiple netns
|
||||||
|
* namespaces are created in parallel at boot. See:
|
||||||
|
* https://bugs.debian.org/949235
|
||||||
|
* Try to take an exclusive file lock on the top level directory to ensure
|
||||||
|
* this cannot happen, but proceed nonetheless if it cannot happen for any
|
||||||
|
* reason.
|
||||||
*/
|
*/
|
||||||
|
lock = open(NETNS_RUN_DIR, O_RDONLY|O_DIRECTORY, 0);
|
||||||
|
if (lock < 0) {
|
||||||
|
fprintf(stderr, "Cannot open netns runtime directory \"%s\": %s\n",
|
||||||
|
NETNS_RUN_DIR, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (flock(lock, LOCK_EX) < 0) {
|
||||||
|
fprintf(stderr, "Warning: could not flock netns runtime directory \"%s\": %s\n",
|
||||||
|
NETNS_RUN_DIR, strerror(errno));
|
||||||
|
close(lock);
|
||||||
|
lock = -1;
|
||||||
|
}
|
||||||
while (mount("", NETNS_RUN_DIR, "none", MS_SHARED | MS_REC, NULL)) {
|
while (mount("", NETNS_RUN_DIR, "none", MS_SHARED | MS_REC, NULL)) {
|
||||||
/* Fail unless we need to make the mount point */
|
/* Fail unless we need to make the mount point */
|
||||||
if (errno != EINVAL || made_netns_run_dir_mount) {
|
if (errno != EINVAL || made_netns_run_dir_mount) {
|
||||||
fprintf(stderr, "mount --make-shared %s failed: %s\n",
|
fprintf(stderr, "mount --make-shared %s failed: %s\n",
|
||||||
NETNS_RUN_DIR, strerror(errno));
|
NETNS_RUN_DIR, strerror(errno));
|
||||||
|
if (lock != -1) {
|
||||||
|
flock(lock, LOCK_UN);
|
||||||
|
close(lock);
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -844,10 +871,18 @@ static int netns_add(int argc, char **argv, bool create)
|
||||||
if (mount(NETNS_RUN_DIR, NETNS_RUN_DIR, "none", MS_BIND | MS_REC, NULL)) {
|
if (mount(NETNS_RUN_DIR, NETNS_RUN_DIR, "none", MS_BIND | MS_REC, NULL)) {
|
||||||
fprintf(stderr, "mount --bind %s %s failed: %s\n",
|
fprintf(stderr, "mount --bind %s %s failed: %s\n",
|
||||||
NETNS_RUN_DIR, NETNS_RUN_DIR, strerror(errno));
|
NETNS_RUN_DIR, NETNS_RUN_DIR, strerror(errno));
|
||||||
|
if (lock != -1) {
|
||||||
|
flock(lock, LOCK_UN);
|
||||||
|
close(lock);
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
made_netns_run_dir_mount = 1;
|
made_netns_run_dir_mount = 1;
|
||||||
}
|
}
|
||||||
|
if (lock != -1) {
|
||||||
|
flock(lock, LOCK_UN);
|
||||||
|
close(lock);
|
||||||
|
}
|
||||||
|
|
||||||
/* Create the filesystem state */
|
/* Create the filesystem state */
|
||||||
fd = open(netns_path, O_RDONLY|O_CREAT|O_EXCL, 0);
|
fd = open(netns_path, O_RDONLY|O_CREAT|O_EXCL, 0);
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,7 @@ static void load_raw_table(FILE *fp)
|
||||||
buf[strlen(buf)-1] = 0;
|
buf[strlen(buf)-1] = 0;
|
||||||
if (info_source[0] && strcmp(info_source, buf+1))
|
if (info_source[0] && strcmp(info_source, buf+1))
|
||||||
source_mismatch = 1;
|
source_mismatch = 1;
|
||||||
strncpy(info_source, buf+1, sizeof(info_source)-1);
|
strlcpy(info_source, buf+1, sizeof(info_source));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((n = malloc(sizeof(*n))) == NULL)
|
if ((n = malloc(sizeof(*n))) == NULL)
|
||||||
|
|
|
||||||
|
|
@ -136,8 +136,7 @@ static void load_good_table(FILE *fp)
|
||||||
buf[strlen(buf)-1] = 0;
|
buf[strlen(buf)-1] = 0;
|
||||||
if (info_source[0] && strcmp(info_source, buf+1))
|
if (info_source[0] && strcmp(info_source, buf+1))
|
||||||
source_mismatch = 1;
|
source_mismatch = 1;
|
||||||
info_source[0] = 0;
|
strlcpy(info_source, buf + 1, sizeof(info_source));
|
||||||
strncat(info_source, buf+1, sizeof(info_source)-1);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* idbuf is as big as buf, so this is safe */
|
/* idbuf is as big as buf, so this is safe */
|
||||||
|
|
|
||||||
|
|
@ -1110,7 +1110,7 @@ static int u32_parse_opt(struct filter_util *qu, char *handle,
|
||||||
}
|
}
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
}
|
}
|
||||||
hash = sel2.sel.keys[0].val & sel2.sel.keys[0].mask;
|
hash = sel2.keys[0].val & sel2.keys[0].mask;
|
||||||
hash ^= hash >> 16;
|
hash ^= hash >> 16;
|
||||||
hash ^= hash >> 8;
|
hash ^= hash >> 8;
|
||||||
htid = ((hash % divisor) << 12) | (htid & 0xFFF00000);
|
htid = ((hash % divisor) << 12) | (htid & 0xFFF00000);
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ parse_ip6(int *argc_p, char ***argv_p,
|
||||||
/* Shift the field by 4 bits on success. */
|
/* Shift the field by 4 bits on success. */
|
||||||
if (!res) {
|
if (!res) {
|
||||||
int nkeys = sel->sel.nkeys;
|
int nkeys = sel->sel.nkeys;
|
||||||
struct tc_pedit_key *key = &sel->sel.keys[nkeys - 1];
|
struct tc_pedit_key *key = &sel->keys[nkeys - 1];
|
||||||
|
|
||||||
key->mask = htonl(ntohl(key->mask) << 4 | 0xf);
|
key->mask = htonl(ntohl(key->mask) << 4 | 0xf);
|
||||||
key->val = htonl(ntohl(key->val) << 4);
|
key->val = htonl(ntohl(key->val) << 4);
|
||||||
|
|
|
||||||
|
|
@ -243,13 +243,19 @@ static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
|
||||||
|
|
||||||
qopt = RTA_DATA(opt);
|
qopt = RTA_DATA(opt);
|
||||||
|
|
||||||
fprintf(f, " tc %u map ", qopt->num_tc);
|
print_uint(PRINT_ANY, "tc", "tc %u ", qopt->num_tc);
|
||||||
|
open_json_array(PRINT_ANY, is_json_context() ? "map" : "map ");
|
||||||
for (i = 0; i <= TC_PRIO_MAX; i++)
|
for (i = 0; i <= TC_PRIO_MAX; i++)
|
||||||
fprintf(f, "%u ", qopt->prio_tc_map[i]);
|
print_uint(PRINT_ANY, NULL, "%u ", qopt->prio_tc_map[i]);
|
||||||
fprintf(f, "\n queues:");
|
close_json_array(PRINT_ANY, "");
|
||||||
for (i = 0; i < qopt->num_tc; i++)
|
open_json_array(PRINT_ANY, is_json_context() ? "queues" : "\n queues:");
|
||||||
fprintf(f, "(%u:%u) ", qopt->offset[i],
|
for (i = 0; i < qopt->num_tc; i++) {
|
||||||
qopt->offset[i] + qopt->count[i] - 1);
|
open_json_array(PRINT_JSON, NULL);
|
||||||
|
print_uint(PRINT_ANY, NULL, "(%u:", qopt->offset[i]);
|
||||||
|
print_uint(PRINT_ANY, NULL, "%u) ", qopt->offset[i] + qopt->count[i] - 1);
|
||||||
|
close_json_array(PRINT_JSON, NULL);
|
||||||
|
}
|
||||||
|
close_json_array(PRINT_ANY, "");
|
||||||
|
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
struct rtattr *tb[TCA_MQPRIO_MAX + 1];
|
struct rtattr *tb[TCA_MQPRIO_MAX + 1];
|
||||||
|
|
@ -262,18 +268,18 @@ static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
|
||||||
__u16 *mode = RTA_DATA(tb[TCA_MQPRIO_MODE]);
|
__u16 *mode = RTA_DATA(tb[TCA_MQPRIO_MODE]);
|
||||||
|
|
||||||
if (*mode == TC_MQPRIO_MODE_CHANNEL)
|
if (*mode == TC_MQPRIO_MODE_CHANNEL)
|
||||||
fprintf(f, "\n mode:channel");
|
print_string(PRINT_ANY, "mode", "\n mode:%s", "channel");
|
||||||
} else {
|
} else {
|
||||||
fprintf(f, "\n mode:dcb");
|
print_string(PRINT_ANY, "mode", "\n mode:%s", "dcb");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tb[TCA_MQPRIO_SHAPER]) {
|
if (tb[TCA_MQPRIO_SHAPER]) {
|
||||||
__u16 *shaper = RTA_DATA(tb[TCA_MQPRIO_SHAPER]);
|
__u16 *shaper = RTA_DATA(tb[TCA_MQPRIO_SHAPER]);
|
||||||
|
|
||||||
if (*shaper == TC_MQPRIO_SHAPER_BW_RATE)
|
if (*shaper == TC_MQPRIO_SHAPER_BW_RATE)
|
||||||
fprintf(f, "\n shaper:bw_rlimit");
|
print_string(PRINT_ANY, "shaper", "\n shaper:%s", "bw_rlimit");
|
||||||
} else {
|
} else {
|
||||||
fprintf(f, "\n shaper:dcb");
|
print_string(PRINT_ANY, "shaper", "\n shaper:%s", "dcb");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tb[TCA_MQPRIO_MIN_RATE64]) {
|
if (tb[TCA_MQPRIO_MIN_RATE64]) {
|
||||||
|
|
@ -287,9 +293,10 @@ static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
|
||||||
return -1;
|
return -1;
|
||||||
*(min++) = rta_getattr_u64(r);
|
*(min++) = rta_getattr_u64(r);
|
||||||
}
|
}
|
||||||
fprintf(f, " min_rate:");
|
open_json_array(PRINT_ANY, is_json_context() ? "min_rate" : " min_rate:");
|
||||||
for (i = 0; i < qopt->num_tc; i++)
|
for (i = 0; i < qopt->num_tc; i++)
|
||||||
fprintf(f, "%s ", sprint_rate(min_rate64[i], b1));
|
print_string(PRINT_ANY, NULL, "%s ", sprint_rate(min_rate64[i], b1));
|
||||||
|
close_json_array(PRINT_ANY, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tb[TCA_MQPRIO_MAX_RATE64]) {
|
if (tb[TCA_MQPRIO_MAX_RATE64]) {
|
||||||
|
|
@ -303,9 +310,10 @@ static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
|
||||||
return -1;
|
return -1;
|
||||||
*(max++) = rta_getattr_u64(r);
|
*(max++) = rta_getattr_u64(r);
|
||||||
}
|
}
|
||||||
fprintf(f, " max_rate:");
|
open_json_array(PRINT_ANY, is_json_context() ? "max_rate" : " max_rate:");
|
||||||
for (i = 0; i < qopt->num_tc; i++)
|
for (i = 0; i < qopt->num_tc; i++)
|
||||||
fprintf(f, "%s ", sprint_rate(max_rate64[i], b1));
|
print_string(PRINT_ANY, NULL, "%s ", sprint_rate(max_rate64[i], b1));
|
||||||
|
close_json_array(PRINT_ANY, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue