diff --git a/doc/man/man5/keepalived.conf.5.in b/doc/man/man5/keepalived.conf.5.in index 76570fec2..00d6d7781 100644 --- a/doc/man/man5/keepalived.conf.5.in +++ b/doc/man/man5/keepalived.conf.5.in @@ -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[] [MAC_ADDRESS] [netlink_notify_msg] + # The name option can be specified if you want to avoid ambiguity. + \fBuse_vmac \fR[[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 @@ -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[] [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] ] [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). diff --git a/keepalived/vrrp/vrrp_parser.c b/keepalived/vrrp/vrrp_parser.c index a43edc7df..8e39412a9 100644 --- a/keepalived/vrrp/vrrp_parser.c +++ b/keepalived/vrrp/vrrp_parser.c @@ -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, ¤t_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, ¤t_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, ¤t_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'; + } } } @@ -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));