* [PATCH iproute2 0/2] Add support for bridge port link information
@ 2013-03-13 20:36 Vlad Yasevich
2013-03-13 20:36 ` [PATCH iproute2 1/2] bridge: Add support for setting bridge port attributes Vlad Yasevich
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Vlad Yasevich @ 2013-03-13 20:36 UTC (permalink / raw)
To: netdev; +Cc: shemminger, john.r.fastabend
Bridge ports provide unique link information about the properties and flags of
the port. This patch set allows bridge utility to configure and disaplay
this information.
Vlad Yasevich (2):
bridge: Add support for setting bridge port attributes
bridge: Add support for printing bridge port attributes
bridge/br_common.h | 1 +
bridge/bridge.c | 3 +-
bridge/link.c | 289 ++++++++++++++++++++++++++++++++++++++++++++++++-
include/libnetlink.h | 2 +
lib/libnetlink.c | 13 ++-
5 files changed, 299 insertions(+), 9 deletions(-)
--
1.7.7.6
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH iproute2 1/2] bridge: Add support for setting bridge port attributes
2013-03-13 20:36 [PATCH iproute2 0/2] Add support for bridge port link information Vlad Yasevich
@ 2013-03-13 20:36 ` Vlad Yasevich
2013-03-13 20:36 ` [PATCH iproute2 2/2] bridge: Add support for printing " Vlad Yasevich
2013-03-14 18:49 ` [PATCH iproute2 0/2] Add support for bridge port link information Vlad Yasevich
2 siblings, 0 replies; 4+ messages in thread
From: Vlad Yasevich @ 2013-03-13 20:36 UTC (permalink / raw)
To: netdev; +Cc: shemminger, john.r.fastabend
Add netlink support bridge port attributes such as cost, priority, state
and flags. This also adds support for HW mode such as VEPA or VEB.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
---
bridge/br_common.h | 1 +
bridge/bridge.c | 3 +-
bridge/link.c | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 221 insertions(+), 1 deletions(-)
diff --git a/bridge/br_common.h b/bridge/br_common.h
index 8764563..12fce3e 100644
--- a/bridge/br_common.h
+++ b/bridge/br_common.h
@@ -10,6 +10,7 @@ extern int do_fdb(int argc, char **argv);
extern int do_mdb(int argc, char **argv);
extern int do_monitor(int argc, char **argv);
extern int do_vlan(int argc, char **argv);
+extern int do_link(int argc, char **argv);
extern int preferred_family;
extern int show_stats;
diff --git a/bridge/bridge.c b/bridge/bridge.c
index 06b7a54..77e260f 100644
--- a/bridge/bridge.c
+++ b/bridge/bridge.c
@@ -27,7 +27,7 @@ static void usage(void)
{
fprintf(stderr,
"Usage: bridge [ OPTIONS ] OBJECT { COMMAND | help }\n"
-"where OBJECT := { fdb | mdb | vlan | monitor }\n"
+"where OBJECT := { link | fdb | mdb | vlan | monitor }\n"
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails]\n" );
exit(-1);
}
@@ -42,6 +42,7 @@ static const struct cmd {
const char *cmd;
int (*func)(int argc, char **argv);
} cmds[] = {
+ { "link", do_link },
{ "fdb", do_fdb },
{ "mdb", do_mdb },
{ "vlan", do_vlan },
diff --git a/bridge/link.c b/bridge/link.c
index edb6fbf..72f2a02 100644
--- a/bridge/link.c
+++ b/bridge/link.c
@@ -9,10 +9,14 @@
#include <linux/if.h>
#include <linux/if_bridge.h>
#include <string.h>
+#include <stdbool.h>
+#include "libnetlink.h"
#include "utils.h"
#include "br_common.h"
+unsigned int filter_index;
+
static const char *port_states[] = {
[BR_STATE_DISABLED] = "disabled",
[BR_STATE_LISTENING] = "listening",
@@ -87,6 +91,9 @@ int print_linkinfo(const struct sockaddr_nl *who,
if (!(ifi->ifi_family == AF_BRIDGE || ifi->ifi_family == AF_UNSPEC))
return 0;
+ if (filter_index && filter_index != ifi->ifi_index)
+ return 0;
+
parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
if (tb[IFLA_IFNAME] == NULL) {
@@ -136,3 +143,214 @@ int print_linkinfo(const struct sockaddr_nl *who,
fflush(fp);
return 0;
}
+
+static void usage(void)
+{
+ fprintf(stderr, "Usage: bridge link set dev DEV [guard {on | off}] [hairpin {on | off}] \n");
+ fprintf(stderr, " [fastleave {on | off}] [cost COST]\n");
+ fprintf(stderr, " [priority PRIO] [state STATE] [mode <vepa | veb>]\n");
+ fprintf(stderr, " [master] [self]\n");
+ fprintf(stderr, " bridge link show [dev DEV]\n");
+ exit(-1);
+}
+
+static bool on_off(char *arg, __s8 *attr, char *val)
+{
+ if (strcmp(val, "on") == 0)
+ *attr = 1;
+ else if (strcmp(val, "off") == 0)
+ *attr = 0;
+ else {
+ fprintf(stderr,
+ "Error: argument of \"%s\" must be \"on\" or \"off\"\n",
+ arg);
+ return false;
+ }
+
+ return true;
+}
+
+static int brlink_modify(int argc, char **argv)
+{
+ struct {
+ struct nlmsghdr n;
+ struct ifinfomsg ifm;
+ char buf[512];
+ } req;
+ char *d = NULL;
+ __s8 hairpin = -1;
+ __s8 bpdu_guard = -1;
+ __s8 fast_leave = -1;
+ __u32 cost = 0;
+ __s16 priority = -1;
+ __s8 state = -1;
+ __s16 mode = -1;
+ __u16 flags = 0;
+ struct rtattr *nest;
+
+ memset(&req, 0, sizeof(req));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = RTM_SETLINK;
+ req.ifm.ifi_family = PF_BRIDGE;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "dev") == 0) {
+ NEXT_ARG();
+ d = *argv;
+ } else if (strcmp(*argv, "guard") == 0) {
+ NEXT_ARG();
+ if (!on_off("guard", &bpdu_guard, *argv))
+ exit(-1);
+ } else if (strcmp(*argv, "hairpin") == 0) {
+ NEXT_ARG();
+ if (!on_off("hairping", &hairpin, *argv))
+ exit(-1);
+ } else if (strcmp(*argv, "fastleave") == 0) {
+ NEXT_ARG();
+ if (!on_off("fastleave", &fast_leave, *argv))
+ exit(-1);
+ } else if (strcmp(*argv, "cost")) {
+ NEXT_ARG();
+ cost = atoi(*argv);
+ } else if (strcmp(*argv, "priority")) {
+ NEXT_ARG();
+ priority = atoi(*argv);
+ } else if (strcmp(*argv, "state")) {
+ NEXT_ARG();
+ state = atoi(*argv);
+ } else if (strcmp(*argv, "mode")) {
+ NEXT_ARG();
+ if (strcmp(*argv, "vepa") == 0)
+ mode = BRIDGE_MODE_VEPA;
+ else if (strcmp(*argv, "veb") == 0)
+ mode = BRIDGE_MODE_VEB;
+ else {
+ fprintf(stderr,
+ "Mode argument must be \"vepa\" or "
+ "\"veb\".\n");
+ exit(-1);
+ }
+ } else if (strcmp(*argv, "master")) {
+ flags |= BRIDGE_FLAGS_MASTER;
+ } else if (strcmp(*argv, "self")) {
+ flags |= BRIDGE_FLAGS_SELF;
+ } else {
+ usage();
+ }
+ argc--; argv++;
+ }
+ if (d == NULL) {
+ fprintf(stderr, "Device is a required argument.\n");
+ exit(-1);
+ }
+
+ req.ifm.ifi_index = ll_name_to_index(d);
+ if (req.ifm.ifi_index == 0) {
+ fprintf(stderr, "Cannot find bridge device \"%s\"\n", d);
+ exit(-1);
+ }
+
+ /* Nested PROTINFO attribute. Contains: port flags, cost, priority and
+ * state.
+ */
+ nest = addattr_nest(&req.n, sizeof(req),
+ IFLA_PROTINFO | NLA_F_NESTED);
+ /* Flags first */
+ if (bpdu_guard >= 0)
+ addattr8(&req.n, sizeof(req), IFLA_BRPORT_GUARD, bpdu_guard);
+ if (hairpin >= 0)
+ addattr8(&req.n, sizeof(req), IFLA_BRPORT_MODE, hairpin);
+ if (fast_leave >= 0)
+ addattr8(&req.n, sizeof(req), IFLA_BRPORT_FAST_LEAVE,
+ fast_leave);
+
+ if (cost > 0)
+ addattr32(&req.n, sizeof(req), IFLA_BRPORT_COST, cost);
+
+ if (priority >= 0)
+ addattr16(&req.n, sizeof(req), IFLA_BRPORT_PRIORITY, priority);
+
+ if (state >= 0)
+ addattr8(&req.n, sizeof(req), IFLA_BRPORT_STATE, state);
+
+ addattr_nest_end(&req.n, nest);
+
+ /* IFLA_AF_SPEC nested attribute. Contains IFLA_BRIDGE_FLAGS that
+ * designates master or self operation as well as 'vepa' or 'veb'
+ * operation modes. These are only valid in 'self' mode on some
+ * devices so far.
+ */
+ if (flags || mode >= 0) {
+ nest = addattr_nest(&req.n, sizeof(req), IFLA_AF_SPEC);
+
+ if (flags)
+ addattr16(&req.n, sizeof(req), IFLA_BRIDGE_FLAGS,
+ flags);
+
+ if (mode >= 0)
+ addattr16(&req.n, sizeof(req), IFLA_BRIDGE_MODE, mode);
+
+ addattr_nest_end(&req.n, nest);
+ }
+
+ if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+ exit(2);
+
+ return 0;
+}
+
+static int brlink_show(int argc, char **argv)
+{
+ char *filter_dev = NULL;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "dev") == 0) {
+ NEXT_ARG();
+ if (filter_dev)
+ duparg("dev", *argv);
+ filter_dev = *argv;
+ }
+ argc--; argv++;
+ }
+
+ if (filter_dev) {
+ if ((filter_index = ll_name_to_index(filter_dev)) == 0) {
+ fprintf(stderr, "Cannot find device \"%s\"\n",
+ filter_dev);
+ return -1;
+ }
+ }
+
+ if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETLINK) < 0) {
+ perror("Cannon send dump request");
+ exit(1);
+ }
+
+ if (rtnl_dump_filter(&rth, print_linkinfo, stdout) < 0) {
+ fprintf(stderr, "Dump terminated\n");
+ exit(1);
+ }
+ return 0;
+}
+
+int do_link(int argc, char **argv)
+{
+ ll_init_map(&rth);
+ if (argc > 0) {
+ if (matches(*argv, "set") == 0 ||
+ matches(*argv, "change") == 0)
+ return brlink_modify(argc-1, argv+1);
+ if (matches(*argv, "show") == 0 ||
+ matches(*argv, "lst") == 0 ||
+ matches(*argv, "list") == 0)
+ return brlink_show(argc-1, argv+1);
+ if (matches(*argv, "help") == 0)
+ usage();
+ } else
+ return brlink_show(0, NULL);
+
+ fprintf(stderr, "Command \"%s\" is unknown, try \"bridge link help\".\n", *argv);
+ exit(-1);
+}
--
1.7.7.6
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH iproute2 2/2] bridge: Add support for printing bridge port attributes
2013-03-13 20:36 [PATCH iproute2 0/2] Add support for bridge port link information Vlad Yasevich
2013-03-13 20:36 ` [PATCH iproute2 1/2] bridge: Add support for setting bridge port attributes Vlad Yasevich
@ 2013-03-13 20:36 ` Vlad Yasevich
2013-03-14 18:49 ` [PATCH iproute2 0/2] Add support for bridge port link information Vlad Yasevich
2 siblings, 0 replies; 4+ messages in thread
From: Vlad Yasevich @ 2013-03-13 20:36 UTC (permalink / raw)
To: netdev; +Cc: shemminger, john.r.fastabend
Output new nested bridge port attributes.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
---
bridge/link.c | 71 +++++++++++++++++++++++++++++++++++++++++++++----
include/libnetlink.h | 2 +
lib/libnetlink.c | 13 ++++++++-
3 files changed, 78 insertions(+), 8 deletions(-)
diff --git a/bridge/link.c b/bridge/link.c
index 72f2a02..48b98f2 100644
--- a/bridge/link.c
+++ b/bridge/link.c
@@ -65,6 +65,8 @@ static const char *oper_states[] = {
"TESTING", "DORMANT", "UP"
};
+static const char *hw_mode[] = {"VEB", "VEPA"};
+
static void print_operstate(FILE *f, __u8 state)
{
if (state >= sizeof(oper_states)/sizeof(oper_states[0]))
@@ -73,6 +75,28 @@ static void print_operstate(FILE *f, __u8 state)
fprintf(f, "state %s ", oper_states[state]);
}
+static void print_portstate(FILE *f, __u8 state)
+{
+ if (state <= BR_STATE_BLOCKING)
+ fprintf(f, "state %s ", port_states[state]);
+ else
+ fprintf(f, "state (%d) ", state);
+}
+
+static void print_portflag(FILE *f, char *flag, __u8 val)
+{
+ if (val)
+ fprintf(f, "%s ", flag);
+}
+
+static void print_hwmode(FILE *f, __u16 mode)
+{
+ if (mode >= sizeof(hw_mode)/sizeof(hw_mode[0]))
+ fprintf(f, "HW mode %#hx ", mode);
+ else
+ fprintf(f, "HW mode %s ", hw_mode[mode]);
+}
+
int print_linkinfo(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg)
{
@@ -94,7 +118,7 @@ int print_linkinfo(const struct sockaddr_nl *who,
if (filter_index && filter_index != ifi->ifi_index)
return 0;
- parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
+ parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(ifi), len, NLA_F_NESTED);
if (tb[IFLA_IFNAME] == NULL) {
fprintf(stderr, "BUG: nil ifname\n");
@@ -131,13 +155,48 @@ int print_linkinfo(const struct sockaddr_nl *who,
if_indextoname(rta_getattr_u32(tb[IFLA_MASTER]), b1));
if (tb[IFLA_PROTINFO]) {
- __u8 state = rta_getattr_u8(tb[IFLA_PROTINFO]);
- if (state <= BR_STATE_BLOCKING)
- fprintf(fp, "state %s", port_states[state]);
- else
- fprintf(fp, "state (%d)", state);
+ if (tb[IFLA_PROTINFO]->rta_type & NLA_F_NESTED) {
+ struct rtattr *prtb[IFLA_BRPORT_MAX+1];
+
+ parse_rtattr_nested(prtb, IFLA_BRPORT_MAX,
+ tb[IFLA_PROTINFO]);
+
+ if (prtb[IFLA_BRPORT_STATE])
+ print_portstate(fp,
+ rta_getattr_u8(prtb[IFLA_BRPORT_STATE]));
+ if (prtb[IFLA_BRPORT_PRIORITY])
+ fprintf(fp, "priority %hu ",
+ rta_getattr_u16(prtb[IFLA_BRPORT_PRIORITY]));
+ if (prtb[IFLA_BRPORT_COST])
+ fprintf(fp, "cost %u ",
+ rta_getattr_u32(prtb[IFLA_BRPORT_COST]));
+ if (prtb[IFLA_BRPORT_MODE])
+ print_portflag(fp, "hairpin mode",
+ rta_getattr_u8(prtb[IFLA_BRPORT_MODE]));
+ if (prtb[IFLA_BRPORT_GUARD])
+ print_portflag(fp, "bpdu guard",
+ rta_getattr_u8(prtb[IFLA_BRPORT_GUARD]));
+ if (prtb[IFLA_BRPORT_PROTECT])
+ print_portflag(fp, "root block",
+ rta_getattr_u8(prtb[IFLA_BRPORT_PROTECT]));
+ if (prtb[IFLA_BRPORT_FAST_LEAVE])
+ print_portflag(fp, "multicast fast leave",
+ rta_getattr_u8(prtb[IFLA_BRPORT_FAST_LEAVE]));
+ } else
+ print_portstate(fp, rta_getattr_u8(tb[IFLA_PROTINFO]));
}
+ if (tb[IFLA_AF_SPEC]) {
+ /* This is reported by HW devices that have some bridging
+ * capabilities.
+ */
+ struct rtattr *aftb[IFLA_BRIDGE_MAX+1];
+
+ parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, tb[IFLA_AF_SPEC]);
+
+ if (tb[IFLA_BRIDGE_MODE])
+ print_hwmode(fp, rta_getattr_u16(tb[IFLA_BRIDGE_MODE]));
+ }
fprintf(fp, "\n");
fflush(fp);
diff --git a/include/libnetlink.h b/include/libnetlink.h
index 8d15ee5..ec3d657 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -65,6 +65,8 @@ extern int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data);
extern int rta_addattr_l(struct rtattr *rta, int maxlen, int type, const void *data, int alen);
extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len);
+extern int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta,
+ int len, unsigned short flags);
extern int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len);
extern int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, int len);
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index 67f046f..f262959 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -658,10 +658,19 @@ int rta_addattr_l(struct rtattr *rta, int maxlen, int type,
int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
{
+ return parse_rtattr_flags(tb, max, rta, len, 0);
+}
+
+int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta,
+ int len, unsigned short flags)
+{
+ unsigned short type;
+
memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
while (RTA_OK(rta, len)) {
- if ((rta->rta_type <= max) && (!tb[rta->rta_type]))
- tb[rta->rta_type] = rta;
+ type = rta->rta_type & ~flags;
+ if ((type <= max) && (!tb[type]))
+ tb[type] = rta;
rta = RTA_NEXT(rta,len);
}
if (len)
--
1.7.7.6
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH iproute2 0/2] Add support for bridge port link information
2013-03-13 20:36 [PATCH iproute2 0/2] Add support for bridge port link information Vlad Yasevich
2013-03-13 20:36 ` [PATCH iproute2 1/2] bridge: Add support for setting bridge port attributes Vlad Yasevich
2013-03-13 20:36 ` [PATCH iproute2 2/2] bridge: Add support for printing " Vlad Yasevich
@ 2013-03-14 18:49 ` Vlad Yasevich
2 siblings, 0 replies; 4+ messages in thread
From: Vlad Yasevich @ 2013-03-14 18:49 UTC (permalink / raw)
To: netdev; +Cc: shemminger, john.r.fastabend
On 03/13/2013 04:36 PM, Vlad Yasevich wrote:
> Bridge ports provide unique link information about the properties and flags of
> the port. This patch set allows bridge utility to configure and disaplay
> this information.
>
> Vlad Yasevich (2):
> bridge: Add support for setting bridge port attributes
> bridge: Add support for printing bridge port attributes
>
> bridge/br_common.h | 1 +
> bridge/bridge.c | 3 +-
> bridge/link.c | 289 ++++++++++++++++++++++++++++++++++++++++++++++++-
> include/libnetlink.h | 2 +
> lib/libnetlink.c | 13 ++-
> 5 files changed, 299 insertions(+), 9 deletions(-)
>
Oh, forgot to write the doc patch. I'll write that up and update the
series.
-vlad
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-03-14 18:49 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-13 20:36 [PATCH iproute2 0/2] Add support for bridge port link information Vlad Yasevich
2013-03-13 20:36 ` [PATCH iproute2 1/2] bridge: Add support for setting bridge port attributes Vlad Yasevich
2013-03-13 20:36 ` [PATCH iproute2 2/2] bridge: Add support for printing " Vlad Yasevich
2013-03-14 18:49 ` [PATCH iproute2 0/2] Add support for bridge port link information Vlad Yasevich
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.