Merge branch 'master' into net-next

This commit is contained in:
Stephen Hemminger 2016-07-06 21:29:32 -07:00
commit d5b62e6439
12 changed files with 257 additions and 14 deletions

View File

@ -90,6 +90,9 @@ struct link_util *get_link_slave_kind(const char *slave_kind);
void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len);
__u32 ipvrf_get_table(const char *name);
bool name_is_vrf(const char *name);
#ifndef INFINITY_LIFE_TIME
#define INFINITY_LIFE_TIME 0xFFFFFFFFU
#endif

View File

@ -80,7 +80,7 @@ static void usage(void)
fprintf(stderr, " [ to PREFIX ] [ FLAG-LIST ] [ label LABEL ] [up]\n");
fprintf(stderr, " ip address [ show [ dev IFNAME ] [ scope SCOPE-ID ] [ master DEVICE ]\n");
fprintf(stderr, " [ type TYPE ] [ to PREFIX ] [ FLAG-LIST ]\n");
fprintf(stderr, " [ label LABEL ] [up] ]\n");
fprintf(stderr, " [ label LABEL ] [up] [ vrf NAME ] ]\n");
fprintf(stderr, " ip address {showdump|restore}\n");
fprintf(stderr, "IFADDR := PREFIX | ADDR peer PREFIX\n");
fprintf(stderr, " [ broadcast ADDR ] [ anycast ADDR ]\n");
@ -1620,6 +1620,16 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
if (!ifindex)
invarg("Device does not exist\n", *argv);
filter.master = ifindex;
} else if (strcmp(*argv, "vrf") == 0) {
int ifindex;
NEXT_ARG();
ifindex = ll_name_to_index(*argv);
if (!ifindex)
invarg("Not a valid VRF name\n", *argv);
if (!name_is_vrf(*argv))
invarg("Not a valid VRF name\n", *argv);
filter.master = ifindex;
} else if (strcmp(*argv, "type") == 0) {
int soff;

View File

@ -82,11 +82,11 @@ void iplink_usage(void)
fprintf(stderr, " [ query_rss { on | off} ]\n");
fprintf(stderr, " [ state { auto | enable | disable} ] ]\n");
fprintf(stderr, " [ trust { on | off} ] ]\n");
fprintf(stderr, " [ master DEVICE ]\n");
fprintf(stderr, " [ master DEVICE ][ vrf NAME ]\n");
fprintf(stderr, " [ nomaster ]\n");
fprintf(stderr, " [ addrgenmode { eui64 | none | stable_secret | random } ]\n");
fprintf(stderr, " [ protodown { on | off } ]\n");
fprintf(stderr, " ip link show [ DEVICE | group GROUP ] [up] [master DEV] [type TYPE]\n");
fprintf(stderr, " ip link show [ DEVICE | group GROUP ] [up] [master DEV] [vrf NAME] [type TYPE]\n");
if (iplink_have_newlink()) {
fprintf(stderr, " ip link help [ TYPE ]\n");
@ -603,6 +603,17 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
invarg("Device does not exist\n", *argv);
addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
&ifindex, 4);
} else if (strcmp(*argv, "vrf") == 0) {
int ifindex;
NEXT_ARG();
ifindex = ll_name_to_index(*argv);
if (!ifindex)
invarg("Not a valid VRF name\n", *argv);
if (!name_is_vrf(*argv))
invarg("Not a valid VRF name\n", *argv);
addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
&ifindex, sizeof(ifindex));
} else if (matches(*argv, "nomaster") == 0) {
int ifindex = 0;

View File

@ -96,3 +96,116 @@ struct link_util vrf_slave_link_util = {
.print_opt = vrf_slave_print_opt,
.slave = true,
};
/* returns table id if name is a VRF device */
__u32 ipvrf_get_table(const char *name)
{
struct {
struct nlmsghdr n;
struct ifinfomsg i;
char buf[1024];
} req = {
.n = {
.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
.nlmsg_flags = NLM_F_REQUEST,
.nlmsg_type = RTM_GETLINK,
},
.i = {
.ifi_family = preferred_family,
},
};
struct {
struct nlmsghdr n;
char buf[8192];
} answer;
struct rtattr *tb[IFLA_MAX+1];
struct rtattr *li[IFLA_INFO_MAX+1];
struct rtattr *vrf_attr[IFLA_VRF_MAX + 1];
struct ifinfomsg *ifi;
__u32 tb_id = 0;
int len;
addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, strlen(name) + 1);
if (rtnl_talk(&rth, &req.n, &answer.n, sizeof(answer)) < 0)
return 0;
ifi = NLMSG_DATA(&answer.n);
len = answer.n.nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
if (len < 0) {
fprintf(stderr, "BUG: Invalid response to link query.\n");
return 0;
}
parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
if (!tb[IFLA_LINKINFO])
return 0;
parse_rtattr_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
if (!li[IFLA_INFO_KIND] || !li[IFLA_INFO_DATA])
return 0;
if (strcmp(RTA_DATA(li[IFLA_INFO_KIND]), "vrf"))
return 0;
parse_rtattr_nested(vrf_attr, IFLA_VRF_MAX, li[IFLA_INFO_DATA]);
if (vrf_attr[IFLA_VRF_TABLE])
tb_id = rta_getattr_u32(vrf_attr[IFLA_VRF_TABLE]);
if (!tb_id)
fprintf(stderr, "BUG: VRF %s is missing table id\n", name);
return tb_id;
}
bool name_is_vrf(const char *name)
{
struct {
struct nlmsghdr n;
struct ifinfomsg i;
char buf[1024];
} req = {
.n = {
.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
.nlmsg_flags = NLM_F_REQUEST,
.nlmsg_type = RTM_GETLINK,
},
.i = {
.ifi_family = preferred_family,
},
};
struct {
struct nlmsghdr n;
char buf[8192];
} answer;
struct rtattr *tb[IFLA_MAX+1];
struct rtattr *li[IFLA_INFO_MAX+1];
struct ifinfomsg *ifi;
int len;
addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, strlen(name) + 1);
if (rtnl_talk(&rth, &req.n, &answer.n, sizeof(answer)) < 0)
return false;
ifi = NLMSG_DATA(&answer.n);
len = answer.n.nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
if (len < 0) {
fprintf(stderr, "BUG: Invalid response to link query.\n");
return false;
}
parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
if (!tb[IFLA_LINKINFO])
return false;
parse_rtattr_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
if (!li[IFLA_INFO_KIND])
return false;
return strcmp(RTA_DATA(li[IFLA_INFO_KIND]), "vrf") == 0;
}

View File

@ -48,7 +48,8 @@ static void usage(void)
{
fprintf(stderr, "Usage: ip neigh { add | del | change | replace }\n"
" { ADDR [ lladdr LLADDR ] [ nud STATE ] | proxy ADDR } [ dev DEV ]\n");
fprintf(stderr, " ip neigh { show | flush } [ proxy ] [ to PREFIX ] [ dev DEV ] [ nud STATE ]\n\n");
fprintf(stderr, " ip neigh { show | flush } [ proxy ] [ to PREFIX ] [ dev DEV ] [ nud STATE ]\n");
fprintf(stderr, " [ vrf NAME ]\n\n");
fprintf(stderr, "STATE := { permanent | noarp | stale | reachable | none |\n"
" incomplete | delay | probe | failed }\n");
exit(-1);
@ -385,6 +386,17 @@ static int do_show_or_flush(int argc, char **argv, int flush)
invarg("Device does not exist\n", *argv);
addattr32(&req.n, sizeof(req), NDA_MASTER, ifindex);
filter.master = ifindex;
} else if (strcmp(*argv, "vrf") == 0) {
int ifindex;
NEXT_ARG();
ifindex = ll_name_to_index(*argv);
if (!ifindex)
invarg("Not a valid VRF name\n", *argv);
if (!name_is_vrf(*argv))
invarg("Not a valid VRF name\n", *argv);
addattr32(&req.n, sizeof(req), NDA_MASTER, ifindex);
filter.master = ifindex;
} else if (strcmp(*argv, "unused") == 0) {
filter.unused_only = 1;
} else if (strcmp(*argv, "nud") == 0) {

View File

@ -67,10 +67,10 @@ static void usage(void)
fprintf(stderr, " ip route showdump\n");
fprintf(stderr, " ip route get ADDRESS [ from ADDRESS iif STRING ]\n");
fprintf(stderr, " [ oif STRING ] [ tos TOS ]\n");
fprintf(stderr, " [ mark NUMBER ]\n");
fprintf(stderr, " [ mark NUMBER ] [ vrf NAME ]\n");
fprintf(stderr, " ip route { add | del | change | append | replace } ROUTE\n");
fprintf(stderr, "SELECTOR := [ root PREFIX ] [ match PREFIX ] [ exact PREFIX ]\n");
fprintf(stderr, " [ table TABLE_ID ] [ proto RTPROTO ]\n");
fprintf(stderr, " [ table TABLE_ID ] [ vrf NAME ] [ proto RTPROTO ]\n");
fprintf(stderr, " [ type TYPE ] [ scope SCOPE ]\n");
fprintf(stderr, "ROUTE := NODE_SPEC [ INFO_SPEC ]\n");
fprintf(stderr, "NODE_SPEC := [ TYPE ] PREFIX [ tos TOS ]\n");
@ -113,7 +113,7 @@ static struct
int flushe;
int protocol, protocolmask;
int scope, scopemask;
int type, typemask;
__u64 typemask;
int tos, tosmask;
int iif, iifmask;
int oif, oifmask;
@ -178,7 +178,8 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
return 0;
if ((filter.scope^r->rtm_scope)&filter.scopemask)
return 0;
if ((filter.type^r->rtm_type)&filter.typemask)
if (filter.typemask && !(filter.typemask & (1 << r->rtm_type)))
return 0;
if ((filter.tos^r->rtm_tos)&filter.tosmask)
return 0;
@ -365,7 +366,8 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
if (n->nlmsg_type == RTM_DELROUTE)
fprintf(fp, "Deleted ");
if ((r->rtm_type != RTN_UNICAST || show_details > 0) && !filter.type)
if ((r->rtm_type != RTN_UNICAST || show_details > 0) &&
(!filter.typemask || (filter.typemask & (1 << r->rtm_type))))
fprintf(fp, "%s ", rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
if (tb[RTA_DST]) {
@ -1136,6 +1138,20 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv)
addattr32(&req.n, sizeof(req), RTA_TABLE, tid);
}
table_ok = 1;
} else if (matches(*argv, "vrf") == 0) {
__u32 tid;
NEXT_ARG();
tid = ipvrf_get_table(*argv);
if (tid == 0)
invarg("Invalid VRF\n", *argv);
if (tid < 256)
req.r.rtm_table = tid;
else {
req.r.rtm_table = RT_TABLE_UNSPEC;
addattr32(&req.n, sizeof(req), RTA_TABLE, tid);
}
table_ok = 1;
} else if (strcmp(*argv, "dev") == 0 ||
strcmp(*argv, "oif") == 0) {
NEXT_ARG();
@ -1390,6 +1406,15 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
}
} else
filter.tb = tid;
} else if (matches(*argv, "vrf") == 0) {
__u32 tid;
NEXT_ARG();
tid = ipvrf_get_table(*argv);
if (tid == 0)
invarg("Invalid VRF\n", *argv);
filter.tb = tid;
filter.typemask = ~(1 << RTN_LOCAL | 1<<RTN_BROADCAST);
} else if (matches(*argv, "cached") == 0 ||
matches(*argv, "cloned") == 0) {
filter.cloned = 1;
@ -1430,10 +1455,9 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
int type;
NEXT_ARG();
filter.typemask = -1;
if (rtnl_rtntype_a2n(&type, *argv))
invarg("node type value is invalid\n", *argv);
filter.type = type;
filter.typemask = (1<<type);
} else if (strcmp(*argv, "dev") == 0 ||
strcmp(*argv, "oif") == 0) {
NEXT_ARG();
@ -1677,6 +1701,11 @@ static int iproute_get(int argc, char **argv)
req.r.rtm_flags |= RTM_F_NOTIFY;
} else if (matches(*argv, "connected") == 0) {
connected = 1;
} else if (matches(*argv, "vrf") == 0) {
NEXT_ARG();
if (!name_is_vrf(*argv))
invarg("Invalid VRF\n", *argv);
odev = *argv;
} else {
inet_prefix addr;

View File

@ -45,6 +45,8 @@ ip-address \- protocol address management
.IR DEVICE " ] [ "
.B type
.IR TYPE " ] [ "
.B vrf
.IR NAME " ] [ "
.BR up " ] ]"
.ti -8
@ -279,6 +281,10 @@ is a usual shell style pattern.
.BI master " DEVICE"
only list interfaces enslaved to this master device.
.TP
.BI vrf " NAME "
only list interfaces enslaved to this vrf.
.TP
.BI type " TYPE"
only list interfaces of the given type.

View File

@ -154,6 +154,9 @@ ip-link \- network device configuration
.br
.RB "[ " nomaster " ]"
.br
.RB "[ " vrf
.IR NAME " ]"
.br
.RB "[ " addrgenmode " { " eui64 " | " none " | " stable_secret " | " random " } ]"
@ -167,6 +170,8 @@ ip-link \- network device configuration
.IR DEVICE " ] ["
.B type
.IR TYPE " ]"
.B vrf
.IR NAME " ]"
.ti -8
.B ip link help
@ -1255,6 +1260,11 @@ only display running interfaces.
.I DEVICE
specifies the master device which enslaves devices to show.
.TP
.BI vrf " NAME "
.I NAME
speficies the VRF which enslaves devices to show.
.TP
.BI type " TYPE "
.I TYPE

View File

@ -31,7 +31,9 @@ ip-neighbour \- neighbour/arp tables management.
.B dev
.IR DEV " ] [ "
.B nud
.IR STATE " ]"
.IR STATE " ] [ "
.B vrf
.IR NAME " ] "
.ti -8
.IR STATE " := {"
@ -163,6 +165,10 @@ the prefix selecting the neighbours to list.
.BI dev " NAME"
only list the neighbours attached to this device.
.TP
.BI vrf " NAME"
only list the neighbours for given VRF.
.TP
.BI proxy
list neighbour proxies.

View File

@ -33,7 +33,9 @@ ip-route \- routing table management
.RB " ] [ " oif
.IR STRING " ] [ "
.B tos
.IR TOS " ]"
.IR TOS " ] [ "
.B vrf
.IR NAME " ] "
.ti -8
.BR "ip route" " { " add " | " del " | " change " | " append " | "\
@ -50,6 +52,8 @@ replace " } "
.IR PREFIX " ] [ "
.B table
.IR TABLE_ID " ] [ "
.B vrf
.IR NAME " ] [ "
.B proto
.IR RTPROTO " ] [ "
.B type
@ -368,6 +372,11 @@ routes, which are put into the
.B local
table by default.
.TP
.BI vrf " NAME"
the vrf name to add this route to. Implicitly means the table
associated with the VRF.
.TP
.BI dev " NAME"
the output device name.
@ -745,6 +754,10 @@ may either be the ID of a real table or one of the special values:
- dump the routing cache.
.in -8
.TP
.BI vrf " NAME"
show the routes for the table associated with the vrf name
.TP
.B cloned
.TP
@ -854,6 +867,10 @@ the device from which this packet is expected to arrive.
.BI oif " NAME"
force the output device on which this packet will be routed.
.TP
.BI vrf " NAME"
force the vrf device on which this packet will be routed.
.TP
.B connected
if no source address

View File

@ -18,7 +18,9 @@ flower \- flow based traffic control filter
.ti -8
.IR MATCH " := { "
.B indev
.IR ifname " | { "
.IR ifname " | "
.BR skip_sw " | " skip_hw
.R " | { "
.BR dst_mac " | " src_mac " } "
.IR mac_address " | "
.BR eth_type " { " ipv4 " | " ipv6 " | "
@ -55,6 +57,13 @@ is the name of an interface which must exist at the time of
.B tc
invocation.
.TP
.BI skip_sw
Do not process filter by software. If hardware has no offload support for this
filter, or TC offload is not enabled for the interface, operation will fail.
.TP
.BI skip_hw
Do not process filter by hardware.
.TP
.BI dst_mac " mac_address"
.TQ
.BI src_mac " mac_address"

View File

@ -25,6 +25,7 @@
static void explain(void)
{
fprintf(stderr, "Usage: ... flower [ MATCH-LIST ]\n");
fprintf(stderr, " [ skip_sw | skip_hw ]\n");
fprintf(stderr, " [ action ACTION-SPEC ] [ classid CLASSID ]\n");
fprintf(stderr, "\n");
fprintf(stderr, "Where: MATCH-LIST := [ MATCH-LIST ] MATCH\n");
@ -167,6 +168,7 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
struct rtattr *tail;
__be16 eth_type = TC_H_MIN(t->tcm_info);
__u8 ip_proto = 0xff;
__u32 flags = 0;
if (handle) {
ret = get_u32(&t->tcm_handle, handle, 0);
@ -196,6 +198,10 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
return -1;
}
addattr_l(n, MAX_MSG, TCA_FLOWER_CLASSID, &handle, 4);
} else if (matches(*argv, "skip_hw") == 0) {
flags |= TCA_CLS_FLAGS_SKIP_HW;
} else if (matches(*argv, "skip_sw") == 0) {
flags |= TCA_CLS_FLAGS_SKIP_SW;
} else if (matches(*argv, "indev") == 0) {
char ifname[IFNAMSIZ];
@ -294,6 +300,8 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
}
parse_done:
addattr32(n, MAX_MSG, TCA_FLOWER_FLAGS, flags);
ret = addattr16(n, MAX_MSG, TCA_FLOWER_KEY_ETH_TYPE, eth_type);
if (ret) {
fprintf(stderr, "Illegal \"eth_type\"(0x%x)\n",
@ -498,6 +506,15 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
tb[TCA_FLOWER_KEY_TCP_SRC],
tb[TCA_FLOWER_KEY_UDP_SRC]);
if (tb[TCA_FLOWER_FLAGS]) {
__u32 flags = rta_getattr_u32(tb[TCA_FLOWER_FLAGS]);
if (flags & TCA_CLS_FLAGS_SKIP_HW)
fprintf(f, "\n skip_hw");
if (flags & TCA_CLS_FLAGS_SKIP_SW)
fprintf(f, "\n skip_sw");
}
if (tb[TCA_FLOWER_ACT]) {
tc_print_action(f, tb[TCA_FLOWER_ACT]);
}