Skip to content

Commit

Permalink
vrrp: Addd name option for use_vmac and use_ipvlan
Browse files Browse the repository at this point in the history
This is to allow an interface name of "bridge" etc.

Signed-off-by: Quentin Armitage <[email protected]>
  • Loading branch information
pqarmitage committed Mar 1, 2024
1 parent c30a60d commit f8689e1
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 38 deletions.
9 changes: 6 additions & 3 deletions doc/man/man5/keepalived.conf.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -1625,7 +1625,8 @@ The syntax for vrrp_instance is :
# interface it will force a netlink message to be sent for the base interface
# since the kernel does not send one, even if the promiscuity of the base
# interface has been updated.
\fBuse_vmac \fR[<VMAC_INTERFACE_NAME>] [MAC_ADDRESS] [netlink_notify_msg]
# The name option can be specified if you want to avoid ambiguity.
\fBuse_vmac \fR[[name] <VMAC_INTERFACE_NAME>] [MAC_ADDRESS] [netlink_notify_msg]

# use_vmac_addr is used to create VMAC (macvlan) interfaces for
# each interface that is used by a VIP or eVIP where the interface
Expand All @@ -1649,12 +1650,14 @@ The syntax for vrrp_instance is :
# For IPv4 instances, an IP address is required, for IPv6
# the address is optional, in which case the link local
# address will be used.
# The mode flags default to bridge. NOTE: the mode flags must be the
# The mode flags defaults to bridge. NOTE: the mode flags must be the
# same for all ipvlans on the same underlying interface.
# It is safer to configure an interface name, in case keepalived crashes
# and restarts, in which case it can more reliably find a previously
# created interface.
\fBuse_ipvlan \fR[<INTERFACE_NAME>] [IP_ADDRESS] [bridge|private|vepa]
# The name option can be specified if you want to use a name that would cause
# a parsing error (e.g. "bridge").
\fBuse_ipvlan \fR[[name] <INTERFACE_NAME>] [IP_ADDRESS] [bridge|private|vepa]

# force instance to use IPv6 (this option is deprecated since
# the virtual ip addresses determine whether IPv4 or IPv6 is used).
Expand Down
77 changes: 42 additions & 35 deletions keepalived/vrrp/vrrp_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -560,49 +560,54 @@ vrrp_vmac_handler(const vector_t *strvec)
report_config_error(CONFIG_GENERAL_ERROR, "VMAC MAC address not allowed to be RFC5798 address (%s) - ignoring", strvec_slot(strvec, i));
else
__set_bit(VRRP_VMAC_MAC_SPECIFIED, &current_vrrp->flags);
} else {
name = strvec_slot(strvec, i);

/* The string "netlink_notify_msg" needs to be longer than IFNAMSIZ
* so that it cannot be a valid interface name. */
if (!strcmp(name, "netlink_notify_msg")) {
__set_bit(VRRP_VMAC_NETLINK_NOTIFY, &current_vrrp->flags);
continue;
}
continue;
}

if (current_vrrp->vmac_ifname[0]) {
report_config_error(CONFIG_GENERAL_ERROR, "VMAC interface name already specified");
continue;
}
if (!strcmp(strvec_slot(strvec, i), "netlink_notify_msg")) {
__set_bit(VRRP_VMAC_NETLINK_NOTIFY, &current_vrrp->flags);
continue;
}

if (!dev_name_valid(name)) {
report_config_error(CONFIG_GENERAL_ERROR, "VMAC interface name '%s' too long or invalid characters - ignoring", name);
continue;
}
if (!strcmp(strvec_slot(strvec, i), "name")) {
/* Skip over "name" */
i++;
}

/* Check another vrrp instance isn't using this name */
list_for_each_entry(ovrrp, &vrrp_data->vrrp, e_list) {
if (!strcmp(name, ovrrp->vmac_ifname)) {
report_config_error(CONFIG_GENERAL_ERROR, "(%s) VRRP instance %s is already using %s - ignoring name", current_vrrp->iname, ovrrp->iname, name);
name = NULL;
break;
}
}
if (current_vrrp->vmac_ifname[0]) {
report_config_error(CONFIG_GENERAL_ERROR, "VMAC interface name already specified");
continue;
}

if (!name)
continue;
name = strvec_slot(strvec, i);

strcpy(current_vrrp->vmac_ifname, name);
if (!dev_name_valid(name)) {
report_config_error(CONFIG_GENERAL_ERROR, "VMAC interface name '%s' too long or invalid characters - ignoring", name);
continue;
}

/* Check if the interface exists and is a macvlan we can use */
if ((ifp = if_get_by_ifname(current_vrrp->vmac_ifname, IF_NO_CREATE)) &&
(ifp->if_type != IF_TYPE_MACVLAN ||
ifp->vmac_type != MACVLAN_MODE_PRIVATE)) {
/* ??? also check ADDR_GEN_MODE and VRF enslavement matches parent */
report_config_error(CONFIG_GENERAL_ERROR, "(%s) interface %s already exists and is not a private macvlan; ignoring vmac if_name", current_vrrp->iname, current_vrrp->vmac_ifname);
current_vrrp->vmac_ifname[0] = '\0';
/* Check another vrrp instance isn't using this name */
list_for_each_entry(ovrrp, &vrrp_data->vrrp, e_list) {
if (!strcmp(name, ovrrp->vmac_ifname)) {
report_config_error(CONFIG_GENERAL_ERROR, "(%s) VRRP instance %s is already using %s - ignoring name", current_vrrp->iname, ovrrp->iname, name);
name = NULL;
break;
}
}

if (!name)
continue;

strcpy(current_vrrp->vmac_ifname, name);

/* Check if the interface exists and is a macvlan we can use */
if ((ifp = if_get_by_ifname(current_vrrp->vmac_ifname, IF_NO_CREATE)) &&
(ifp->if_type != IF_TYPE_MACVLAN ||
ifp->vmac_type != MACVLAN_MODE_PRIVATE)) {
/* ??? also check ADDR_GEN_MODE and VRF enslavement matches parent */
report_config_error(CONFIG_GENERAL_ERROR, "(%s) interface %s already exists and is not a private macvlan; ignoring vmac if_name", current_vrrp->iname, current_vrrp->vmac_ifname);
current_vrrp->vmac_ifname[0] = '\0';
}
}
}

Expand Down Expand Up @@ -677,7 +682,9 @@ vrrp_ipvlan_handler(const vector_t *strvec)
continue;
}

if (check_valid_ipaddress(strvec_slot(strvec, i), true)) {
if (!strcmp(strvec_slot(strvec, i), "name")) {
i++;
} else if (check_valid_ipaddress(strvec_slot(strvec, i), true)) {
parse_ipaddress(&addr, strvec_slot(strvec, i), true);
if (current_vrrp->ipvlan_addr) {
report_config_error(CONFIG_GENERAL_ERROR, "(%s) ipvlan address already specified - ignoring '%s'", current_vrrp->iname, strvec_slot(strvec, i));
Expand Down

0 comments on commit f8689e1

Please sign in to comment.