Skip to content

Commit

Permalink
vrrp: Add interface group option for VMACs and ipvlans.
Browse files Browse the repository at this point in the history
Now that the interface group of a VMAC or ipvlan is set, by default,
to match its parent interface, this option now allows the group of
the VMAC or ipvlan to be explicitly configured and set.

Signed-off-by: Quentin Armitage <[email protected]>
  • Loading branch information
pqarmitage committed Mar 1, 2024
1 parent f8689e1 commit 5fcaa2d
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 22 deletions.
10 changes: 7 additions & 3 deletions doc/man/man5/keepalived.conf.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -1625,8 +1625,11 @@ 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.
# The name option can be specified if you want to avoid ambiguity.
\fBuse_vmac \fR[[name] <VMAC_INTERFACE_NAME>] [MAC_ADDRESS] [netlink_notify_msg]
# By default the VMAC is created in the same link group as the parent interface.
# Specifying group GROUP_ID (where GROUP_ID is either a valid group number, or a
# name in /etc/iproute2/group) will create the interface in the specied group.
# The name option can be specified if you want to use an interface name "group".
\fBuse_vmac \fR[[name] <VMAC_INTERFACE_NAME>] [MAC_ADDRESS] [netlink_notify_msg] [group GROUP_ID]

# 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 Down Expand Up @@ -1657,7 +1660,8 @@ The syntax for vrrp_instance is :
# created interface.
# 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]
# For a description of the group option, see use_vmac.
\fBuse_ipvlan \fR[[name] <INTERFACE_NAME>] [IP_ADDRESS] [bridge|private|vepa] [group GROUP_ID]

# force instance to use IPv6 (this option is deprecated since
# the virtual ip addresses determine whether IPv4 or IPv6 is used).
Expand Down
2 changes: 2 additions & 0 deletions keepalived/include/vrrp.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ enum vrrp_flags_bits {
VRRP_VMAC_XMITBASE_BIT,
VRRP_VMAC_ADDR_BIT,
VRRP_VMAC_NETLINK_NOTIFY,
VRRP_VMAC_GROUP,
#ifdef _HAVE_VRRP_IPVLAN_
VRRP_IPVLAN_BIT,
#endif
Expand Down Expand Up @@ -260,6 +261,7 @@ typedef struct _vrrp_t {
#ifdef _HAVE_VRRP_VMAC_
char vmac_ifname[IFNAMSIZ]; /* Name of VRRP VMAC interface */
u_char ll_addr[ETH_ALEN]; /* Override MAC address */
uint32_t vmac_group; /* interface group for VMAC/ipvlan */
#ifdef _HAVE_VRRP_IPVLAN_
struct _ip_address *ipvlan_addr; /* Address to configure on an ipvlan interface */
int ipvlan_type; /* Bridge, private or VEPA mode */
Expand Down
21 changes: 14 additions & 7 deletions keepalived/vrrp/vrrp_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -648,13 +648,6 @@ dump_vrrp(FILE *fp, const vrrp_t *vrrp)
vrrp->ll_addr[0], vrrp->ll_addr[1], vrrp->ll_addr[2], vrrp->ll_addr[3], vrrp->ll_addr[4], vrrp->ll_addr[5],
__test_bit(VRRP_VMAC_MAC_USE_VRID, &vrrp->flags) ? " (using VRID)" : "");
}

/* The following two flags should only be set on VMACs, but
* we check them for any interface type, just incase ... */
if (__test_bit(VRRP_VMAC_NETLINK_NOTIFY, &vrrp->flags))
conf_write(fp, " Force netlink update for base interface");
if (__test_bit(VRRP_VMAC_ADDR_BIT, &vrrp->flags))
conf_write(fp, " Use VMAC for VIPs on other interfaces");
#ifdef _HAVE_VRRP_IPVLAN_
else if (__test_bit(VRRP_IPVLAN_BIT, &vrrp->flags))
conf_write(fp, " Use IPVLAN, i/f %s, is_up = %s%s%s, type %s",
Expand All @@ -669,6 +662,20 @@ dump_vrrp(FILE *fp, const vrrp_t *vrrp)
#endif
);
#endif

/* The following two flags should only be set on VMACs, but
* we check them for any interface type, just incase ... */
if (__test_bit(VRRP_VMAC_NETLINK_NOTIFY, &vrrp->flags))
conf_write(fp, " Force netlink update for base interface");
if (__test_bit(VRRP_VMAC_ADDR_BIT, &vrrp->flags))
conf_write(fp, " Use VMAC for VIPs on other interfaces");

/* The following should only be specified for VMACs and ipvlans */
if (__test_bit(VRRP_VMAC_GROUP, &vrrp->flags))
conf_write(fp, " Interface group %u", vrrp->vmac_group);
else if (vrrp->ifp->base_ifp->group)
conf_write(fp, " Interface group %u (copied from parent)", vrrp->ifp->base_ifp->group);

if (vrrp->ifp && vrrp->ifp->is_ours) {
conf_write(fp, " Interface = %s, %s on %s%s", IF_NAME(vrrp->ifp),
__test_bit(VRRP_VMAC_BIT, &vrrp->flags) ? "vmac" : "ipvlan",
Expand Down
24 changes: 24 additions & 0 deletions keepalived/vrrp/vrrp_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
#include "global_data.h"
#include "global_parser.h"

#include "rttables.h"

#include "vrrp_data.h"
#include "vrrp_ipaddress.h"
#include "vrrp_sync.h"
Expand Down Expand Up @@ -569,6 +571,17 @@ vrrp_vmac_handler(const vector_t *strvec)
continue;
}

if (!strcmp(strvec_slot(strvec, i), "group")) {
uint32_t group;
if (!find_rttables_group(strvec_slot(strvec, ++i), &group)) {
report_config_error(CONFIG_GENERAL_ERROR, "VMAC group %s not found", strvec_slot(strvec, i));
continue;
}
__set_bit(VRRP_VMAC_GROUP, &current_vrrp->flags);
current_vrrp->vmac_group = group;
continue;
}

if (!strcmp(strvec_slot(strvec, i), "name")) {
/* Skip over "name" */
i++;
Expand Down Expand Up @@ -682,6 +695,17 @@ vrrp_ipvlan_handler(const vector_t *strvec)
continue;
}

if (!strcmp(strvec_slot(strvec, i), "group")) {
uint32_t group;
if (!find_rttables_group(strvec_slot(strvec, ++i), &group)) {
report_config_error(CONFIG_GENERAL_ERROR, "ipvlan group %s not found", strvec_slot(strvec, i));
continue;
}
__set_bit(VRRP_VMAC_GROUP, &current_vrrp->flags);
current_vrrp->vmac_group = group;
continue;
}

if (!strcmp(strvec_slot(strvec, i), "name")) {
i++;
} else if (check_valid_ipaddress(strvec_slot(strvec, i), true)) {
Expand Down
8 changes: 6 additions & 2 deletions keepalived/vrrp/vrrp_vmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,9 @@ netlink_link_add_vmac(vrrp_t *vrrp, const interface_t *old_interface)
* (iptables devgroup or nftables iifgroup, oifgroup) to continue
* working regardless of the use_vmac setting.
*/
addattr32(&req.n, sizeof(req), IFLA_GROUP, vrrp->configured_ifp->base_ifp->group);
addattr32(&req.n, sizeof(req), IFLA_GROUP,
__test_bit(VRRP_VMAC_GROUP, &vrrp->flags) ? vrrp->vmac_group
: vrrp->configured_ifp->base_ifp->group);
addattr_l(&req.n, sizeof(req), IFLA_ADDRESS, if_ll_addr, ETH_ALEN);

#ifdef _HAVE_VRF_
Expand Down Expand Up @@ -622,7 +624,9 @@ netlink_link_add_ipvlan(vrrp_t *vrrp)
* working regardless of the use_vmac setting. */
addattr32(&req.n, sizeof(req), IFLA_LINK, vrrp->configured_ifp->ifindex);
addattr_l(&req.n, sizeof(req), IFLA_IFNAME, vrrp->vmac_ifname, strlen(vrrp->vmac_ifname));
addattr32(&req.n, sizeof(req), IFLA_GROUP, vrrp->configured_ifp->base_ifp->group);
addattr32(&req.n, sizeof(req), IFLA_GROUP,
__test_bit(VRRP_VMAC_GROUP, &vrrp->flags) ? vrrp->vmac_group
: vrrp->configured_ifp->base_ifp->group);
linkinfo = PTR_CAST(struct rtattr, NLMSG_TAIL(&req.n));
addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, (const void *)ipvlan_ll_kind, strlen(ipvlan_ll_kind));
Expand Down
4 changes: 1 addition & 3 deletions lib/rttables.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,13 +322,11 @@ find_rttables_dsfield(const char *name, uint8_t *id)
return ret;
}

#if HAVE_DECL_FRA_SUPPRESS_IFGROUP
bool
find_rttables_group(const char *name, uint32_t *id)
{
return find_entry(name, id, &rt_groups, RT_GROUPS_FILE, NULL, INT32_MAX);
}
#endif

bool
find_rttables_realms(const char *name, uint32_t *id)
Expand Down Expand Up @@ -386,7 +384,7 @@ get_entry(unsigned int id, list_head_t *l, const char* file_name, const rt_entry
return ret_buf;
}

#if HAVE_DECL_FRA_SUPPRESS_IFGROUP
#if HAVE_DECL_FRA_SUPPRESS_IFGROUP && defined _WITH_SNMP_VRRP_
const char *
get_rttables_group(uint32_t id)
{
Expand Down
8 changes: 1 addition & 7 deletions lib/rttables.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,18 @@
#include <stdint.h>

extern void clear_rt_names(void);
#ifdef _WITH_VRRP_
extern bool find_rttables_table(const char *, uint32_t *);
extern bool find_rttables_dsfield(const char *, uint8_t *);
extern bool find_rttables_realms(const char *, uint32_t *);
#if HAVE_DECL_FRA_SUPPRESS_IFGROUP
extern bool find_rttables_group(const char *, uint32_t *);
#endif
extern bool find_rttables_proto(const char *, uint8_t *);
extern bool find_rttables_rtntype(const char *, uint8_t *);
#endif
extern bool find_rttables_scope(const char *, uint8_t *);

extern const char *get_rttables_scope(uint32_t);
#ifdef _WITH_VRRP_
#if HAVE_DECL_FRA_SUPPRESS_IFGROUP
#if HAVE_DECL_FRA_SUPPRESS_IFGROUP && defined _WITH_SNMP_VRRP_
extern const char *get_rttables_group(uint32_t);
#endif
extern const char *get_rttables_rtntype(uint8_t);
#endif

#endif

0 comments on commit 5fcaa2d

Please sign in to comment.