Merge branch 'net-next-3.11'
This commit is contained in:
commit
a067644497
|
|
@ -5,6 +5,14 @@
|
|||
*
|
||||
* Copyright (c) 2009 Wolfgang Grandegger <wg@grandegger.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef CAN_NETLINK_H
|
||||
|
|
|
|||
|
|
@ -323,6 +323,17 @@ struct ifla_vxlan_port_range {
|
|||
__be16 high;
|
||||
};
|
||||
|
||||
/* Bonding section */
|
||||
|
||||
enum {
|
||||
IFLA_BOND_UNSPEC,
|
||||
IFLA_BOND_MODE,
|
||||
IFLA_BOND_ACTIVE_SLAVE,
|
||||
__IFLA_BOND_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1)
|
||||
|
||||
/* SR-IOV virtual function management section */
|
||||
|
||||
enum {
|
||||
|
|
|
|||
|
|
@ -388,6 +388,20 @@ enum {
|
|||
|
||||
#define TCA_CGROUP_MAX (__TCA_CGROUP_MAX - 1)
|
||||
|
||||
/* BPF classifier */
|
||||
|
||||
enum {
|
||||
TCA_BPF_UNSPEC,
|
||||
TCA_BPF_ACT,
|
||||
TCA_BPF_POLICE,
|
||||
TCA_BPF_CLASSID,
|
||||
TCA_BPF_OPS_LEN,
|
||||
TCA_BPF_OPS,
|
||||
__TCA_BPF_MAX,
|
||||
};
|
||||
|
||||
#define TCA_BPF_MAX (__TCA_BPF_MAX - 1)
|
||||
|
||||
/* Extended Matches */
|
||||
|
||||
struct tcf_ematch_tree_hdr {
|
||||
|
|
|
|||
|
|
@ -357,6 +357,8 @@ enum {
|
|||
TCA_HTB_CTAB,
|
||||
TCA_HTB_RTAB,
|
||||
TCA_HTB_DIRECT_QLEN,
|
||||
TCA_HTB_RATE64,
|
||||
TCA_HTB_CEIL64,
|
||||
__TCA_HTB_MAX,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
|
|||
iplink_vlan.o link_veth.o link_gre.o iplink_can.o \
|
||||
iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o \
|
||||
iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \
|
||||
link_iptnl.o link_gre6.o
|
||||
link_iptnl.o link_gre6.o iplink_bond.o
|
||||
|
||||
RTMONOBJ=rtmon.o
|
||||
|
||||
|
|
|
|||
|
|
@ -85,8 +85,8 @@ void iplink_usage(void)
|
|||
if (iplink_have_newlink()) {
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n");
|
||||
fprintf(stderr, " can | bridge | ipoib | ip6tnl | ipip | sit | vxlan |\n");
|
||||
fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti }\n");
|
||||
fprintf(stderr, " can | bridge | bond | ipoib | ip6tnl | ipip | sit |\n");
|
||||
fprintf(stderr, " vxlan | gre | gretap | ip6gre | ip6gretap | vti }\n");
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* iplink_bond.c Bonding device support
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Authors: Jiri Pirko <jiri@resnulli.us>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include "rt_names.h"
|
||||
#include "utils.h"
|
||||
#include "ip_common.h"
|
||||
|
||||
static void explain(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: ... bond [ mode BONDMODE ] [ active_slave SLAVE_DEV ]\n"
|
||||
" [ clear_active_slave ]\n"
|
||||
"\n"
|
||||
"BONDMODE := 0-6\n"
|
||||
);
|
||||
}
|
||||
|
||||
static int bond_parse_opt(struct link_util *lu, int argc, char **argv,
|
||||
struct nlmsghdr *n)
|
||||
{
|
||||
__u8 mode;
|
||||
unsigned ifindex;
|
||||
|
||||
while (argc > 0) {
|
||||
if (matches(*argv, "mode") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u8(&mode, *argv, 0)) {
|
||||
invarg("mode %s is invalid", *argv);
|
||||
return -1;
|
||||
}
|
||||
addattr8(n, 1024, IFLA_BOND_MODE, mode);
|
||||
} else if (matches(*argv, "active_slave") == 0) {
|
||||
NEXT_ARG();
|
||||
ifindex = if_nametoindex(*argv);
|
||||
if (!ifindex)
|
||||
return -1;
|
||||
addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, ifindex);
|
||||
} else if (matches(*argv, "clear_active_slave") == 0) {
|
||||
addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, 0);
|
||||
} else {
|
||||
fprintf(stderr, "bond: unknown command \"%s\"?\n", *argv);
|
||||
explain();
|
||||
return -1;
|
||||
}
|
||||
argc--, argv++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
||||
{
|
||||
unsigned ifindex;
|
||||
|
||||
if (!tb)
|
||||
return;
|
||||
|
||||
if (tb[IFLA_BOND_MODE])
|
||||
fprintf(f, "mode %u ", rta_getattr_u8(tb[IFLA_BOND_MODE]));
|
||||
|
||||
if (tb[IFLA_BOND_ACTIVE_SLAVE] &&
|
||||
(ifindex = rta_getattr_u32(tb[IFLA_BOND_ACTIVE_SLAVE]))) {
|
||||
char buf[IFNAMSIZ];
|
||||
const char *n = if_indextoname(ifindex, buf);
|
||||
|
||||
if (n)
|
||||
fprintf(f, "active_slave %s ", n);
|
||||
else
|
||||
fprintf(f, "active_slave %u ", ifindex);
|
||||
}
|
||||
}
|
||||
|
||||
struct link_util bond_link_util = {
|
||||
.id = "bond",
|
||||
.maxattr = IFLA_BOND_MAX,
|
||||
.parse_opt = bond_parse_opt,
|
||||
.print_opt = bond_print_opt,
|
||||
};
|
||||
|
|
@ -51,6 +51,7 @@ ip-link \- network device configuration
|
|||
.ti -8
|
||||
.IR TYPE " := [ "
|
||||
.BR bridge " | "
|
||||
.BR bond " ]"
|
||||
.BR can " | "
|
||||
.BR dummy " | "
|
||||
.BR ifb " | "
|
||||
|
|
@ -155,6 +156,9 @@ Link types:
|
|||
.B bridge
|
||||
- Ethernet Bridge device
|
||||
.sp
|
||||
.B bond
|
||||
- Bonding device
|
||||
.sp
|
||||
.B can
|
||||
- Controller Area Network interface
|
||||
.sp
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ TCMODULES += f_u32.o
|
|||
TCMODULES += f_route.o
|
||||
TCMODULES += f_fw.o
|
||||
TCMODULES += f_basic.o
|
||||
TCMODULES += f_bpf.o
|
||||
TCMODULES += f_flow.o
|
||||
TCMODULES += f_cgroup.o
|
||||
TCMODULES += q_dsmark.o
|
||||
|
|
|
|||
|
|
@ -0,0 +1,288 @@
|
|||
/*
|
||||
* f_bpf.c BPF-based Classifier
|
||||
*
|
||||
* This program is free software; you can distribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Authors: Daniel Borkmann <dborkman@redhat.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/if.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "tc_util.h"
|
||||
|
||||
static void explain(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: ... bpf ...\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, " [inline]: run bytecode BPF_BYTECODE\n");
|
||||
fprintf(stderr, " [from file]: run bytecode-file FILE\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, " [ police POLICE_SPEC ] [ action ACTION_SPEC ]\n");
|
||||
fprintf(stderr, " [ classid CLASSID ]\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Where BPF_BYTECODE := \'s,c t f k,c t f k,c t f k,...\'\n");
|
||||
fprintf(stderr, " c,t,f,k and s are decimals; s denotes number of 4-tuples\n");
|
||||
fprintf(stderr, "Where FILE points to a file containing the BPF_BYTECODE string\n");
|
||||
fprintf(stderr, "\nNOTE: CLASSID is parsed as hexadecimal input.\n");
|
||||
}
|
||||
|
||||
static int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len,
|
||||
char **bpf_string, bool *need_release,
|
||||
const char separator)
|
||||
{
|
||||
char sp;
|
||||
|
||||
if (from_file) {
|
||||
size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,");
|
||||
char *tmp_string;
|
||||
FILE *fp;
|
||||
|
||||
tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len;
|
||||
tmp_string = malloc(tmp_len);
|
||||
if (tmp_string == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(tmp_string, 0, tmp_len);
|
||||
|
||||
fp = fopen(arg, "r");
|
||||
if (fp == NULL) {
|
||||
perror("Cannot fopen");
|
||||
free(tmp_string);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (!fgets(tmp_string, tmp_len, fp)) {
|
||||
free(tmp_string);
|
||||
fclose(fp);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
*need_release = true;
|
||||
*bpf_string = tmp_string;
|
||||
} else {
|
||||
*need_release = false;
|
||||
*bpf_string = arg;
|
||||
}
|
||||
|
||||
if (sscanf(*bpf_string, "%hu%c", bpf_len, &sp) != 2 ||
|
||||
sp != separator) {
|
||||
if (*need_release)
|
||||
free(*bpf_string);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bpf_parse_ops(int argc, char **argv, struct nlmsghdr *n,
|
||||
bool from_file)
|
||||
{
|
||||
char *bpf_string, *token, separator = ',';
|
||||
struct sock_filter bpf_ops[BPF_MAXINSNS];
|
||||
int ret = 0, i = 0;
|
||||
bool need_release;
|
||||
__u16 bpf_len = 0;
|
||||
|
||||
if (argc < 1)
|
||||
return -EINVAL;
|
||||
if (bpf_parse_string(argv[0], from_file, &bpf_len, &bpf_string,
|
||||
&need_release, separator))
|
||||
return -EINVAL;
|
||||
if (bpf_len == 0 || bpf_len > BPF_MAXINSNS) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
token = bpf_string;
|
||||
while ((token = strchr(token, separator)) && (++token)[0]) {
|
||||
if (i >= bpf_len) {
|
||||
fprintf(stderr, "Real program length exceeds encoded "
|
||||
"length parameter!\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sscanf(token, "%hu %hhu %hhu %u,",
|
||||
&bpf_ops[i].code, &bpf_ops[i].jt,
|
||||
&bpf_ops[i].jf, &bpf_ops[i].k) != 4) {
|
||||
fprintf(stderr, "Error at instruction %d!\n", i);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i != bpf_len) {
|
||||
fprintf(stderr, "Parsed program length is less than encoded"
|
||||
"length parameter!\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
addattr_l(n, MAX_MSG, TCA_BPF_OPS_LEN, &bpf_len, sizeof(bpf_len));
|
||||
addattr_l(n, MAX_MSG, TCA_BPF_OPS, &bpf_ops,
|
||||
bpf_len * sizeof(struct sock_filter));
|
||||
out:
|
||||
if (need_release)
|
||||
free(bpf_string);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len)
|
||||
{
|
||||
struct sock_filter *ops = (struct sock_filter *) RTA_DATA(bpf_ops);
|
||||
int i;
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
fprintf(f, "bytecode \'%u,", len);
|
||||
|
||||
for (i = 0; i < len - 1; i++)
|
||||
fprintf(f, "%hu %hhu %hhu %u,", ops[i].code, ops[i].jt,
|
||||
ops[i].jf, ops[i].k);
|
||||
|
||||
fprintf(f, "%hu %hhu %hhu %u\'\n", ops[i].code, ops[i].jt,
|
||||
ops[i].jf, ops[i].k);
|
||||
}
|
||||
|
||||
static int bpf_parse_opt(struct filter_util *qu, char *handle,
|
||||
int argc, char **argv, struct nlmsghdr *n)
|
||||
{
|
||||
struct tcmsg *t = NLMSG_DATA(n);
|
||||
struct rtattr *tail;
|
||||
long h = 0;
|
||||
|
||||
if (argc == 0)
|
||||
return 0;
|
||||
|
||||
if (handle) {
|
||||
h = strtol(handle, NULL, 0);
|
||||
if (h == LONG_MIN || h == LONG_MAX) {
|
||||
fprintf(stderr, "Illegal handle \"%s\", must be "
|
||||
"numeric.\n", handle);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
t->tcm_handle = h;
|
||||
|
||||
tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
|
||||
addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);
|
||||
|
||||
while (argc > 0) {
|
||||
if (matches(*argv, "run") == 0) {
|
||||
bool from_file;
|
||||
NEXT_ARG();
|
||||
if (strcmp(*argv, "bytecode-file") == 0) {
|
||||
from_file = true;
|
||||
} else if (strcmp(*argv, "bytecode") == 0) {
|
||||
from_file = false;
|
||||
} else {
|
||||
fprintf(stderr, "What is \"%s\"?\n", *argv);
|
||||
explain();
|
||||
return -1;
|
||||
}
|
||||
NEXT_ARG();
|
||||
if (bpf_parse_ops(argc, argv, n, from_file)) {
|
||||
fprintf(stderr, "Illegal \"bytecode\"\n");
|
||||
return -1;
|
||||
}
|
||||
} else if (matches(*argv, "classid") == 0 ||
|
||||
strcmp(*argv, "flowid") == 0) {
|
||||
unsigned handle;
|
||||
NEXT_ARG();
|
||||
if (get_tc_classid(&handle, *argv)) {
|
||||
fprintf(stderr, "Illegal \"classid\"\n");
|
||||
return -1;
|
||||
}
|
||||
addattr_l(n, MAX_MSG, TCA_BPF_CLASSID, &handle, 4);
|
||||
} else if (matches(*argv, "action") == 0) {
|
||||
NEXT_ARG();
|
||||
if (parse_action(&argc, &argv, TCA_BPF_ACT, n)) {
|
||||
fprintf(stderr, "Illegal \"action\"\n");
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
} else if (matches(*argv, "police") == 0) {
|
||||
NEXT_ARG();
|
||||
if (parse_police(&argc, &argv, TCA_BPF_POLICE, n)) {
|
||||
fprintf(stderr, "Illegal \"police\"\n");
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
} else if (strcmp(*argv, "help") == 0) {
|
||||
explain();
|
||||
return -1;
|
||||
} else {
|
||||
fprintf(stderr, "What is \"%s\"?\n", *argv);
|
||||
explain();
|
||||
return -1;
|
||||
}
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
tail->rta_len = (((void*)n)+n->nlmsg_len) - (void*)tail;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bpf_print_opt(struct filter_util *qu, FILE *f,
|
||||
struct rtattr *opt, __u32 handle)
|
||||
{
|
||||
struct rtattr *tb[TCA_BPF_MAX + 1];
|
||||
|
||||
if (opt == NULL)
|
||||
return 0;
|
||||
|
||||
parse_rtattr_nested(tb, TCA_BPF_MAX, opt);
|
||||
|
||||
if (handle)
|
||||
fprintf(f, "handle 0x%x ", handle);
|
||||
|
||||
if (tb[TCA_BPF_CLASSID]) {
|
||||
SPRINT_BUF(b1);
|
||||
fprintf(f, "flowid %s ",
|
||||
sprint_tc_classid(rta_getattr_u32(tb[TCA_BPF_CLASSID]), b1));
|
||||
}
|
||||
|
||||
if (tb[TCA_BPF_OPS] && tb[TCA_BPF_OPS_LEN])
|
||||
bpf_print_ops(f, tb[TCA_BPF_OPS],
|
||||
rta_getattr_u16(tb[TCA_BPF_OPS_LEN]));
|
||||
|
||||
if (tb[TCA_BPF_POLICE]) {
|
||||
fprintf(f, "\n");
|
||||
tc_print_police(f, tb[TCA_BPF_POLICE]);
|
||||
}
|
||||
|
||||
if (tb[TCA_BPF_ACT]) {
|
||||
tc_print_action(f, tb[TCA_BPF_ACT]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct filter_util bpf_filter_util = {
|
||||
.id = "bpf",
|
||||
.parse_fopt = bpf_parse_opt,
|
||||
.print_fopt = bpf_print_opt,
|
||||
};
|
||||
Loading…
Reference in New Issue