bridge: add support for backup port

This patch adds support for the new backup port option that can be set
on a bridge port. If the port's carrier goes down all of the traffic
gets redirected to the configured backup port. We add the following new
arguments:
$ ip link set dev brport type bridge_slave backup_port brport2
$ ip link set dev brport type bridge_slave nobackup_port

$ bridge link set dev brport backup_port brport2
$ bridge link set dev brport nobackup_port

The man pages are updated respectively.
Also 2 minor style adjustments:
- add missing space to bridge man page's state argument
- use lower starting case for vlan_tunnel in ip-link man page (to be
consistent with the rest)

Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
Nikolay Aleksandrov 2018-10-12 14:42:55 +03:00 committed by David Ahern
parent 4c45b684f9
commit d13d52d0d5
4 changed files with 68 additions and 3 deletions

View File

@ -152,6 +152,16 @@ static void print_protinfo(FILE *fp, struct rtattr *attr)
if (prtb[IFLA_BRPORT_VLAN_TUNNEL]) if (prtb[IFLA_BRPORT_VLAN_TUNNEL])
print_onoff(fp, "vlan_tunnel", print_onoff(fp, "vlan_tunnel",
rta_getattr_u8(prtb[IFLA_BRPORT_VLAN_TUNNEL])); rta_getattr_u8(prtb[IFLA_BRPORT_VLAN_TUNNEL]));
if (prtb[IFLA_BRPORT_BACKUP_PORT]) {
int ifidx;
ifidx = rta_getattr_u32(prtb[IFLA_BRPORT_BACKUP_PORT]);
print_string(PRINT_ANY,
"backup_port", "backup_port %s ",
ll_index_to_name(ifidx));
}
if (prtb[IFLA_BRPORT_ISOLATED]) if (prtb[IFLA_BRPORT_ISOLATED])
print_onoff(fp, "isolated", print_onoff(fp, "isolated",
rta_getattr_u8(prtb[IFLA_BRPORT_ISOLATED])); rta_getattr_u8(prtb[IFLA_BRPORT_ISOLATED]));
@ -255,6 +265,7 @@ static void usage(void)
fprintf(stderr, " [ vlan_tunnel {on | off} ]\n"); fprintf(stderr, " [ vlan_tunnel {on | off} ]\n");
fprintf(stderr, " [ isolated {on | off} ]\n"); fprintf(stderr, " [ isolated {on | off} ]\n");
fprintf(stderr, " [ hwmode {vepa | veb} ]\n"); fprintf(stderr, " [ hwmode {vepa | veb} ]\n");
fprintf(stderr, " [ backup_port DEVICE ] [ nobackup_port ]\n");
fprintf(stderr, " [ self ] [ master ]\n"); fprintf(stderr, " [ self ] [ master ]\n");
fprintf(stderr, " bridge link show [dev DEV]\n"); fprintf(stderr, " bridge link show [dev DEV]\n");
exit(-1); exit(-1);
@ -289,6 +300,7 @@ static int brlink_modify(int argc, char **argv)
.ifm.ifi_family = PF_BRIDGE, .ifm.ifi_family = PF_BRIDGE,
}; };
char *d = NULL; char *d = NULL;
int backup_port_idx = -1;
__s8 neigh_suppress = -1; __s8 neigh_suppress = -1;
__s8 learning = -1; __s8 learning = -1;
__s8 learning_sync = -1; __s8 learning_sync = -1;
@ -395,6 +407,16 @@ static int brlink_modify(int argc, char **argv)
NEXT_ARG(); NEXT_ARG();
if (!on_off("isolated", &isolated, *argv)) if (!on_off("isolated", &isolated, *argv))
return -1; return -1;
} else if (strcmp(*argv, "backup_port") == 0) {
NEXT_ARG();
backup_port_idx = ll_name_to_index(*argv);
if (!backup_port_idx) {
fprintf(stderr, "Error: device %s does not exist\n",
*argv);
return -1;
}
} else if (strcmp(*argv, "nobackup_port") == 0) {
backup_port_idx = 0;
} else { } else {
usage(); usage();
} }
@ -456,6 +478,10 @@ static int brlink_modify(int argc, char **argv)
if (isolated != -1) if (isolated != -1)
addattr8(&req.n, sizeof(req), IFLA_BRPORT_ISOLATED, isolated); addattr8(&req.n, sizeof(req), IFLA_BRPORT_ISOLATED, isolated);
if (backup_port_idx != -1)
addattr32(&req.n, sizeof(req), IFLA_BRPORT_BACKUP_PORT,
backup_port_idx);
addattr_nest_end(&req.n, nest); addattr_nest_end(&req.n, nest);
/* IFLA_AF_SPEC nested attribute. Contains IFLA_BRIDGE_FLAGS that /* IFLA_AF_SPEC nested attribute. Contains IFLA_BRIDGE_FLAGS that

View File

@ -41,6 +41,7 @@ static void print_explain(FILE *f)
" [ neigh_suppress {on | off} ]\n" " [ neigh_suppress {on | off} ]\n"
" [ vlan_tunnel {on | off} ]\n" " [ vlan_tunnel {on | off} ]\n"
" [ isolated {on | off} ]\n" " [ isolated {on | off} ]\n"
" [ backup_port DEVICE ] [ nobackup_port ]\n"
); );
} }
@ -279,6 +280,13 @@ static void bridge_slave_print_opt(struct link_util *lu, FILE *f,
if (tb[IFLA_BRPORT_ISOLATED]) if (tb[IFLA_BRPORT_ISOLATED])
_print_onoff(f, "isolated", "isolated", _print_onoff(f, "isolated", "isolated",
rta_getattr_u8(tb[IFLA_BRPORT_ISOLATED])); rta_getattr_u8(tb[IFLA_BRPORT_ISOLATED]));
if (tb[IFLA_BRPORT_BACKUP_PORT]) {
int backup_p = rta_getattr_u32(tb[IFLA_BRPORT_BACKUP_PORT]);
print_string(PRINT_ANY, "backup_port", "backup_port %s ",
ll_index_to_name(backup_p));
}
} }
static void bridge_slave_parse_on_off(char *arg_name, char *arg_val, static void bridge_slave_parse_on_off(char *arg_name, char *arg_val,
@ -388,6 +396,16 @@ static int bridge_slave_parse_opt(struct link_util *lu, int argc, char **argv,
NEXT_ARG(); NEXT_ARG();
bridge_slave_parse_on_off("isolated", *argv, n, bridge_slave_parse_on_off("isolated", *argv, n,
IFLA_BRPORT_ISOLATED); IFLA_BRPORT_ISOLATED);
} else if (matches(*argv, "backup_port") == 0) {
int ifindex;
NEXT_ARG();
ifindex = ll_name_to_index(*argv);
if (!ifindex)
invarg("Device does not exist\n", *argv);
addattr32(n, 1024, IFLA_BRPORT_BACKUP_PORT, ifindex);
} else if (matches(*argv, "nobackup_port") == 0) {
addattr32(n, 1024, IFLA_BRPORT_BACKUP_PORT, 0);
} else if (matches(*argv, "help") == 0) { } else if (matches(*argv, "help") == 0) {
explain(); explain();
return -1; return -1;

View File

@ -37,7 +37,7 @@ bridge \- show / manipulate bridge addresses and devices
.B priority .B priority
.IR PRIO " ] [ " .IR PRIO " ] [ "
.B state .B state
.IR STATE "] [" .IR STATE " ] [ "
.BR guard " { " on " | " off " } ] [ " .BR guard " { " on " | " off " } ] [ "
.BR hairpin " { " on " | " off " } ] [ " .BR hairpin " { " on " | " off " } ] [ "
.BR fastleave " { " on " | " off " } ] [ " .BR fastleave " { " on " | " off " } ] [ "
@ -50,6 +50,9 @@ bridge \- show / manipulate bridge addresses and devices
.BR neigh_suppress " { " on " | " off " } ] [ " .BR neigh_suppress " { " on " | " off " } ] [ "
.BR vlan_tunnel " { " on " | " off " } ] [ " .BR vlan_tunnel " { " on " | " off " } ] [ "
.BR isolated " { " on " | " off " } ] [ " .BR isolated " { " on " | " off " } ] [ "
.B backup_port
.IR DEVICE " ] ["
.BR nobackup_port " ] [ "
.BR self " ] [ " master " ]" .BR self " ] [ " master " ]"
.ti -8 .ti -8
@ -373,6 +376,14 @@ Controls whether vlan to tunnel mapping is enabled on the port. By default this
Controls whether a given port will be isolated, which means it will be able to communicate with non-isolated ports only. Controls whether a given port will be isolated, which means it will be able to communicate with non-isolated ports only.
By default this flag is off. By default this flag is off.
.TP
.BI backup_port " DEVICE"
If the port loses carrier all traffic will be redirected to the configured backup port
.TP
.BR nobackup_port
Removes the currently configured backup port
.TP .TP
.BI self .BI self
link setting is configured on specified physical device link setting is configured on specified physical device

View File

@ -2076,7 +2076,11 @@ the following additional arguments are supported:
] [ ] [
.BR vlan_tunnel " { " on " | " off " }" .BR vlan_tunnel " { " on " | " off " }"
] [ ] [
.BR isolated " { " on " | " off " } ]" .BR isolated " { " on " | " off " }"
] [
.BR backup_port " DEVICE"
] [
.BR nobackup_port " ]"
.in +8 .in +8
.sp .sp
@ -2158,7 +2162,13 @@ option above.
- controls whether neigh discovery (arp and nd) proxy and suppression is enabled on the port. By default this flag is off. - controls whether neigh discovery (arp and nd) proxy and suppression is enabled on the port. By default this flag is off.
.BR vlan_tunnel " { " on " | " off " }" .BR vlan_tunnel " { " on " | " off " }"
- Controls whether vlan to tunnel mapping is enabled on the port. By default this flag is off. - controls whether vlan to tunnel mapping is enabled on the port. By default this flag is off.
.BI backup_port " DEVICE"
- if the port loses carrier all traffic will be redirected to the configured backup port
.BR nobackup_port
- removes the currently configured backup port
.in -8 .in -8