Merge branch 'iproute2-master' into iproute2-next

Conflicts:
	include/uapi/linux/bpf.h

Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
David Ahern 2018-07-25 10:08:04 -07:00
commit a0bc57e1ef
13 changed files with 180 additions and 109 deletions

View File

@ -199,7 +199,7 @@ int mnlg_socket_group_add(struct mnlg_socket *nlg, const char *group_name)
nlh = __mnlg_msg_prepare(nlg, CTRL_CMD_GETFAMILY,
NLM_F_REQUEST | NLM_F_ACK, GENL_ID_CTRL, 1);
mnl_attr_put_u32(nlh, CTRL_ATTR_FAMILY_ID, nlg->id);
mnl_attr_put_u16(nlh, CTRL_ATTR_FAMILY_ID, nlg->id);
err = mnlg_socket_send(nlg, nlh);
if (err < 0)

View File

@ -853,10 +853,8 @@ int print_linkinfo(const struct sockaddr_nl *who,
if (!name)
return -1;
if (filter.label &&
(!filter.family || filter.family == AF_PACKET) &&
fnmatch(filter.label, name, 0))
return -1;
if (filter.label)
return 0;
if (tb[IFLA_GROUP]) {
int group = rta_getattr_u32(tb[IFLA_GROUP]);

View File

@ -177,6 +177,7 @@ static const char *seg6_action_names[SEG6_LOCAL_ACTION_MAX + 1] = {
[SEG6_LOCAL_ACTION_END_S] = "End.S",
[SEG6_LOCAL_ACTION_END_AS] = "End.AS",
[SEG6_LOCAL_ACTION_END_AM] = "End.AM",
[SEG6_LOCAL_ACTION_END_BPF] = "End.BPF",
};
static const char *format_action_type(int action)
@ -202,6 +203,27 @@ static int read_action_type(const char *name)
return SEG6_LOCAL_ACTION_UNSPEC;
}
static void print_encap_bpf_prog(FILE *fp, struct rtattr *encap,
const char *str)
{
struct rtattr *tb[LWT_BPF_PROG_MAX+1];
const char *progname = NULL;
parse_rtattr_nested(tb, LWT_BPF_PROG_MAX, encap);
if (tb[LWT_BPF_PROG_NAME])
progname = rta_getattr_str(tb[LWT_BPF_PROG_NAME]);
if (is_json_context())
print_string(PRINT_JSON, str, NULL,
progname ? : "<unknown>");
else {
fprintf(fp, "%s ", str);
if (progname)
fprintf(fp, "%s ", progname);
}
}
static void print_encap_seg6local(FILE *fp, struct rtattr *encap)
{
struct rtattr *tb[SEG6_LOCAL_MAX + 1];
@ -250,6 +272,9 @@ static void print_encap_seg6local(FILE *fp, struct rtattr *encap)
print_string(PRINT_ANY, "oif",
"oif %s ", ll_index_to_name(oif));
}
if (tb[SEG6_LOCAL_BPF])
print_encap_bpf_prog(fp, tb[SEG6_LOCAL_BPF], "endpoint");
}
static void print_encap_mpls(FILE *fp, struct rtattr *encap)
@ -356,27 +381,6 @@ static void print_encap_ip6(FILE *fp, struct rtattr *encap)
"tc %u ", rta_getattr_u8(tb[LWTUNNEL_IP6_TC]));
}
static void print_encap_bpf_prog(FILE *fp, struct rtattr *encap,
const char *str)
{
struct rtattr *tb[LWT_BPF_PROG_MAX+1];
const char *progname = NULL;
parse_rtattr_nested(tb, LWT_BPF_PROG_MAX, encap);
if (tb[LWT_BPF_PROG_NAME])
progname = rta_getattr_str(tb[LWT_BPF_PROG_NAME]);
if (is_json_context())
print_string(PRINT_JSON, str, NULL,
progname ? : "<unknown>");
else {
fprintf(fp, "%s ", str);
if (progname)
fprintf(fp, "%s ", progname);
}
}
static void print_encap_bpf(FILE *fp, struct rtattr *encap)
{
struct rtattr *tb[LWT_BPF_MAX+1];
@ -546,11 +550,60 @@ static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp,
return 0;
}
struct lwt_x {
struct rtattr *rta;
size_t len;
};
static void bpf_lwt_cb(void *lwt_ptr, int fd, const char *annotation)
{
struct lwt_x *x = lwt_ptr;
rta_addattr32(x->rta, x->len, LWT_BPF_PROG_FD, fd);
rta_addattr_l(x->rta, x->len, LWT_BPF_PROG_NAME, annotation,
strlen(annotation) + 1);
}
static const struct bpf_cfg_ops bpf_cb_ops = {
.ebpf_cb = bpf_lwt_cb,
};
static int lwt_parse_bpf(struct rtattr *rta, size_t len,
int *argcp, char ***argvp,
int attr, const enum bpf_prog_type bpf_type)
{
struct bpf_cfg_in cfg = {
.type = bpf_type,
.argc = *argcp,
.argv = *argvp,
};
struct lwt_x x = {
.rta = rta,
.len = len,
};
struct rtattr *nest;
int err;
nest = rta_nest(rta, len, attr);
err = bpf_parse_and_load_common(&cfg, &bpf_cb_ops, &x);
if (err < 0) {
fprintf(stderr, "Failed to parse eBPF program: %s\n",
strerror(-err));
return -1;
}
rta_nest_end(rta, nest);
*argcp = cfg.argc;
*argvp = cfg.argv;
return 0;
}
static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp,
char ***argvp)
{
int segs_ok = 0, hmac_ok = 0, table_ok = 0, nh4_ok = 0, nh6_ok = 0;
int iif_ok = 0, oif_ok = 0, action_ok = 0, srh_ok = 0;
int iif_ok = 0, oif_ok = 0, action_ok = 0, srh_ok = 0, bpf_ok = 0;
__u32 action = 0, table, iif, oif;
struct ipv6_sr_hdr *srh;
char **argv = *argvp;
@ -627,6 +680,14 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp,
} else {
continue;
}
} else if (strcmp(*argv, "endpoint") == 0) {
NEXT_ARG();
if (bpf_ok++)
duparg2("endpoint", *argv);
if (lwt_parse_bpf(rta, len, &argc, &argv, SEG6_LOCAL_BPF,
BPF_PROG_TYPE_LWT_SEG6LOCAL) < 0)
exit(-1);
} else {
break;
}
@ -896,55 +957,6 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
return 0;
}
struct lwt_x {
struct rtattr *rta;
size_t len;
};
static void bpf_lwt_cb(void *lwt_ptr, int fd, const char *annotation)
{
struct lwt_x *x = lwt_ptr;
rta_addattr32(x->rta, x->len, LWT_BPF_PROG_FD, fd);
rta_addattr_l(x->rta, x->len, LWT_BPF_PROG_NAME, annotation,
strlen(annotation) + 1);
}
static const struct bpf_cfg_ops bpf_cb_ops = {
.ebpf_cb = bpf_lwt_cb,
};
static int lwt_parse_bpf(struct rtattr *rta, size_t len,
int *argcp, char ***argvp,
int attr, const enum bpf_prog_type bpf_type)
{
struct bpf_cfg_in cfg = {
.type = bpf_type,
.argc = *argcp,
.argv = *argvp,
};
struct lwt_x x = {
.rta = rta,
.len = len,
};
struct rtattr *nest;
int err;
nest = rta_nest(rta, len, attr);
err = bpf_parse_and_load_common(&cfg, &bpf_cb_ops, &x);
if (err < 0) {
fprintf(stderr, "Failed to parse eBPF program: %s\n",
strerror(-err));
return -1;
}
rta_nest_end(rta, nest);
*argcp = cfg.argc;
*argvp = cfg.argv;
return 0;
}
static void lwt_bpf_usage(void)
{
fprintf(stderr, "Usage: ip route ... encap bpf [ in BPF ] [ out BPF ] [ xmit BPF ] [...]\n");

View File

@ -95,6 +95,11 @@ static const struct bpf_prog_meta __bpf_prog_meta[] = {
.subdir = "ip",
.section = ELF_SECTION_PROG,
},
[BPF_PROG_TYPE_LWT_SEG6LOCAL] = {
.type = "lwt_seg6local",
.subdir = "ip",
.section = ELF_SECTION_PROG,
},
};
static bool bpf_map_offload_neutral(enum bpf_map_type type)

View File

@ -7,7 +7,7 @@ devlink \- Devlink tool
.in +8
.ti -8
.B devlink
.RI "[ " OPTIONS " ] " OBJECT " { " COMMAND " | "
.RI "[ " OPTIONS " ] { " dev | port | monitor | sb | resource " } { " COMMAND " | "
.BR help " }"
.sp
@ -17,18 +17,6 @@ devlink \- Devlink tool
.BI "-batch " filename
.sp
.ti -8
.IR OBJECT " := { "
.BR dev " | " port " | " monitor " | " sb " | " resource " }"
.sp
.ti -8
.IR OPTIONS " := { "
\fB\-V\fR[\fIersion\fR] |
\fB\-n\fR[\fIno-nice-names\fR] }
\fB\-j\fR[\fIjson\fR] }
\fB\-p\fR[\fIpretty\fR] }
.SH OPTIONS
.TP

View File

@ -28,7 +28,7 @@ defined rate limiting method to the traffic.
This queueing discipline is intended to be used by TSN (Time Sensitive
Networking) applications, the CBS parameters are derived directly by
what is described by the Annex L of the IEEE 802.1Q-2014
Sepcification. The algorithm and how it affects the latency are
Specification. The algorithm and how it affects the latency are
detailed there.
CBS is meant to be installed under another qdisc that maps packet
@ -60,7 +60,7 @@ packet size, which is then used for calculating the idleslope.
sendslope
Sendslope is the rate of credits that is depleted (it should be a
negative number of kilobits per second) when a transmission is
ocurring. It can be calculated as follows, (IEEE 802.1Q-2014 Section
occurring. It can be calculated as follows, (IEEE 802.1Q-2014 Section
8.6.8.2 item g):
sendslope = idleslope - port_transmit_rate

View File

@ -998,6 +998,19 @@ struct ib_uverbs_flow_spec_action_handle {
__u32 reserved1;
};
struct ib_uverbs_flow_spec_action_count {
union {
struct ib_uverbs_flow_spec_hdr hdr;
struct {
__u32 type;
__u16 size;
__u16 reserved;
};
};
__u32 handle;
__u32 reserved1;
};
struct ib_uverbs_flow_tunnel_filter {
__be32 tunnel_id;
};
@ -1033,6 +1046,56 @@ struct ib_uverbs_flow_spec_esp {
struct ib_uverbs_flow_spec_esp_filter mask;
};
struct ib_uverbs_flow_gre_filter {
/* c_ks_res0_ver field is bits 0-15 in offset 0 of a standard GRE header:
* bit 0 - C - checksum bit.
* bit 1 - reserved. set to 0.
* bit 2 - key bit.
* bit 3 - sequence number bit.
* bits 4:12 - reserved. set to 0.
* bits 13:15 - GRE version.
*/
__be16 c_ks_res0_ver;
__be16 protocol;
__be32 key;
};
struct ib_uverbs_flow_spec_gre {
union {
struct ib_uverbs_flow_spec_hdr hdr;
struct {
__u32 type;
__u16 size;
__u16 reserved;
};
};
struct ib_uverbs_flow_gre_filter val;
struct ib_uverbs_flow_gre_filter mask;
};
struct ib_uverbs_flow_mpls_filter {
/* The field includes the entire MPLS label:
* bits 0:19 - label field.
* bits 20:22 - traffic class field.
* bits 23 - bottom of stack bit.
* bits 24:31 - ttl field.
*/
__be32 label;
};
struct ib_uverbs_flow_spec_mpls {
union {
struct ib_uverbs_flow_spec_hdr hdr;
struct {
__u32 type;
__u16 size;
__u16 reserved;
};
};
struct ib_uverbs_flow_mpls_filter val;
struct ib_uverbs_flow_mpls_filter mask;
};
struct ib_uverbs_flow_attr {
__u32 type;
__u16 size;

View File

@ -1203,7 +1203,7 @@ static void flower_print_ip_attr(char *name, struct rtattr *key_attr,
if (mask_attr)
sprintf(out + done, "/%x", rta_getattr_u8(mask_attr));
sprintf(namefrm, "\n %s %%x", name);
sprintf(namefrm, "\n %s %%s", name);
print_string(PRINT_ANY, name, namefrm, out);
}

View File

@ -291,9 +291,9 @@ static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
if (RTA_PAYLOAD(tb[TCA_HTB_PARMS]) < sizeof(*hopt)) return -1;
if (!hopt->level) {
print_int(PRINT_ANY, "prio", "prio ", (int)hopt->prio);
print_int(PRINT_ANY, "prio", "prio %d ", (int)hopt->prio);
if (show_details)
print_int(PRINT_ANY, "quantum", "quantum ",
print_int(PRINT_ANY, "quantum", "quantum %d ",
(int)hopt->quantum);
}

View File

@ -173,7 +173,8 @@ static int mqprio_parse_opt(struct qdisc_util *qu, int argc,
argc--; argv++;
}
tail = addattr_nest_compat(n, 1024, TCA_OPTIONS, &opt, sizeof(opt));
tail = NLMSG_TAIL(n);
addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt));
if (flags & TC_MQPRIO_F_MODE)
addattr_l(n, 1024, TCA_MQPRIO_MODE,
@ -208,7 +209,7 @@ static int mqprio_parse_opt(struct qdisc_util *qu, int argc,
addattr_nest_end(n, start);
}
addattr_nest_compat_end(n, tail);
tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail;
return 0;
}

View File

@ -422,6 +422,8 @@ static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv,
}
}
tail = NLMSG_TAIL(n);
if (reorder.probability) {
if (opt.latency == 0) {
fprintf(stderr, "reordering not possible without specifying some delay\n");
@ -450,7 +452,8 @@ static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv,
return -1;
}
tail = addattr_nest_compat(n, 1024, TCA_OPTIONS, &opt, sizeof(opt));
if (addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt)) < 0)
return -1;
if (present[TCA_NETEM_CORR] &&
addattr_l(n, 1024, TCA_NETEM_CORR, &cor, sizeof(cor)) < 0)
@ -509,7 +512,7 @@ static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv,
return -1;
free(dist_data);
}
addattr_nest_compat_end(n, tail);
tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
return 0;
}

21
tc/tc.c
View File

@ -334,6 +334,7 @@ static int batch(const char *name)
int batchsize = 0;
size_t len = 0;
int ret = 0;
int err;
bool send;
batch_mode = 1;
@ -402,9 +403,9 @@ static int batch(const char *name)
continue; /* blank line */
}
ret = do_cmd(largc, largv, tail == NULL ? NULL : tail->buf,
err = do_cmd(largc, largv, tail == NULL ? NULL : tail->buf,
tail == NULL ? 0 : sizeof(tail->buf));
if (ret != 0) {
if (err != 0) {
fprintf(stderr, "Command failed %s:%d\n", name,
cmdlineno - 1);
ret = 1;
@ -426,15 +427,17 @@ static int batch(const char *name)
iov->iov_len = n->nlmsg_len;
}
ret = rtnl_talk_iov(&rth, iovs, batchsize, NULL);
if (ret < 0) {
fprintf(stderr, "Command failed %s:%d\n", name,
cmdlineno - (batchsize + ret) - 1);
return 2;
}
err = rtnl_talk_iov(&rth, iovs, batchsize, NULL);
put_batch_bufs(&buf_pool, &head, &tail);
batchsize = 0;
free(iovs);
if (err < 0) {
fprintf(stderr, "Command failed %s:%d\n", name,
cmdlineno - (batchsize + err) - 1);
ret = 1;
if (!force)
break;
}
batchsize = 0;
}
} while (!lastline);

View File

@ -842,8 +842,6 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtat
memcpy(&re, RTA_DATA(tbs[TCA_STATS_RATE_EST]),
MIN(RTA_PAYLOAD(tbs[TCA_STATS_RATE_EST]), sizeof(re)));
fprintf(fp, "\n%srate %s %upps ",
prefix, sprint_rate(re.bps, b1), re.pps);
print_string(PRINT_FP, NULL, "\n%s", prefix);
print_uint(PRINT_JSON, "rate", NULL, re.bps);
print_string(PRINT_FP, NULL, "rate %s",