mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 16:04:49 +00:00
vrrpd: autoconfig support
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
parent
8ec512164c
commit
53e60e5c58
4
lib/if.h
4
lib/if.h
@ -225,6 +225,10 @@ struct interface {
|
|||||||
not work as expected.
|
not work as expected.
|
||||||
*/
|
*/
|
||||||
ifindex_t ifindex;
|
ifindex_t ifindex;
|
||||||
|
/*
|
||||||
|
* ifindex of parent interface, if any
|
||||||
|
*/
|
||||||
|
ifindex_t link_ifindex;
|
||||||
#define IFINDEX_INTERNAL 0
|
#define IFINDEX_INTERNAL 0
|
||||||
|
|
||||||
/* Zebra internal interface status */
|
/* Zebra internal interface status */
|
||||||
|
@ -1400,6 +1400,8 @@ stream_failure:
|
|||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* | bandwidth |
|
* | bandwidth |
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* | parent ifindex |
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* | Link Layer Type |
|
* | Link Layer Type |
|
||||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
* | Harware Address Length |
|
* | Harware Address Length |
|
||||||
@ -1580,6 +1582,7 @@ void zebra_interface_if_set_value(struct stream *s, struct interface *ifp)
|
|||||||
ifp->mtu = stream_getl(s);
|
ifp->mtu = stream_getl(s);
|
||||||
ifp->mtu6 = stream_getl(s);
|
ifp->mtu6 = stream_getl(s);
|
||||||
ifp->bandwidth = stream_getl(s);
|
ifp->bandwidth = stream_getl(s);
|
||||||
|
ifp->link_ifindex = stream_getl(s);
|
||||||
ifp->ll_type = stream_getl(s);
|
ifp->ll_type = stream_getl(s);
|
||||||
ifp->hw_addr_len = stream_getl(s);
|
ifp->hw_addr_len = stream_getl(s);
|
||||||
if (ifp->hw_addr_len)
|
if (ifp->hw_addr_len)
|
||||||
|
76
vrrpd/vrrp.c
76
vrrpd/vrrp.c
@ -1297,6 +1297,81 @@ int vrrp_event(struct vrrp_router *r, int event)
|
|||||||
|
|
||||||
/* Other ------------------------------------------------------------------- */
|
/* Other ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static struct vrrp_vrouter *
|
||||||
|
vrrp_autoconfig_autocreate(struct interface *mvl_ifp)
|
||||||
|
{
|
||||||
|
struct interface *p;
|
||||||
|
struct vrrp_vrouter *vr;
|
||||||
|
|
||||||
|
p = if_lookup_by_index(mvl_ifp->link_ifindex, VRF_DEFAULT);
|
||||||
|
uint8_t vrid = mvl_ifp->hw_addr[5];
|
||||||
|
|
||||||
|
zlog_info(VRRP_LOGPFX "Autoconfiguring VRRP on %s", p->name);
|
||||||
|
|
||||||
|
/* If it already exists, skip it */
|
||||||
|
vr = vrrp_lookup(p, vrid);
|
||||||
|
if (vr) {
|
||||||
|
zlog_info(VRRP_LOGPFX "VRRP instance %" PRIu8
|
||||||
|
"already configured on %s",
|
||||||
|
vrid, p->name);
|
||||||
|
return vr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create a new one */
|
||||||
|
vr = vrrp_vrouter_create(p, vrid, vrrp_autoconfig_version);
|
||||||
|
|
||||||
|
if (!vr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* add connected addresses as vips */
|
||||||
|
struct listnode *ln;
|
||||||
|
struct connected *c = NULL;
|
||||||
|
for (ALL_LIST_ELEMENTS_RO(mvl_ifp->connected, ln, c))
|
||||||
|
if (c->address->family == AF_INET)
|
||||||
|
vrrp_add_ipv4(vr, c->address->u.prefix4, false);
|
||||||
|
else if (c->address->family == AF_INET6) {
|
||||||
|
if (!IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6))
|
||||||
|
vrrp_add_ipv6(vr, c->address->u.prefix6, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vr->v4->addrs->count)
|
||||||
|
vrrp_event(vr->v4, VRRP_EVENT_STARTUP);
|
||||||
|
if (vr->v6->addrs->count)
|
||||||
|
vrrp_event(vr->v6, VRRP_EVENT_STARTUP);
|
||||||
|
|
||||||
|
vr->autoconf = true;
|
||||||
|
|
||||||
|
return vr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool vrrp_ifp_is_mvl(struct interface *ifp)
|
||||||
|
{
|
||||||
|
struct ethaddr vmac4;
|
||||||
|
struct ethaddr vmac6;
|
||||||
|
vrrp_mac_set(&vmac4, 0, 0x00);
|
||||||
|
vrrp_mac_set(&vmac6, 1, 0x00);
|
||||||
|
|
||||||
|
return !memcmp(ifp->hw_addr, vmac4.octet, sizeof(vmac4.octet) - 1)
|
||||||
|
|| !memcmp(ifp->hw_addr, vmac6.octet, sizeof(vmac6.octet) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vrrp_autoconfig(struct interface *ifp)
|
||||||
|
{
|
||||||
|
if (ifp && vrrp_ifp_is_mvl(ifp)) {
|
||||||
|
vrrp_autoconfig_autocreate(ifp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop through interfaces, looking for compatible macvlan devices. */
|
||||||
|
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
||||||
|
|
||||||
|
FOR_ALL_INTERFACES (vrf, ifp)
|
||||||
|
if (vrrp_ifp_is_mvl(ifp))
|
||||||
|
vrrp_autoconfig_autocreate(ifp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned int vrrp_hash_key(void *arg)
|
static unsigned int vrrp_hash_key(void *arg)
|
||||||
{
|
{
|
||||||
struct vrrp_vrouter *vr = arg;
|
struct vrrp_vrouter *vr = arg;
|
||||||
@ -1323,6 +1398,7 @@ static bool vrrp_hash_cmp(const void *arg1, const void *arg2)
|
|||||||
|
|
||||||
void vrrp_init(void)
|
void vrrp_init(void)
|
||||||
{
|
{
|
||||||
|
vrrp_autoconfig_version = 3;
|
||||||
vrrp_vrouters_hash = hash_create(&vrrp_hash_key, vrrp_hash_cmp,
|
vrrp_vrouters_hash = hash_create(&vrrp_hash_key, vrrp_hash_cmp,
|
||||||
"VRRP virtual router hash");
|
"VRRP virtual router hash");
|
||||||
vrf_init(NULL, NULL, NULL, NULL, NULL);
|
vrf_init(NULL, NULL, NULL, NULL, NULL);
|
||||||
|
38
vrrpd/vrrp.h
38
vrrpd/vrrp.h
@ -53,13 +53,17 @@ extern struct zebra_privs_t vrrp_privs;
|
|||||||
/* Global hash of all Virtual Routers */
|
/* Global hash of all Virtual Routers */
|
||||||
struct hash *vrrp_vrouters_hash;
|
struct hash *vrrp_vrouters_hash;
|
||||||
|
|
||||||
/*
|
/* Whether to automatically configure VRRP instances */
|
||||||
* VRRP Router.
|
static bool vrrp_autoconfig_on;
|
||||||
*
|
static int vrrp_autoconfig_version;
|
||||||
* This struct contains all state for a particular VRRP Router operating in a
|
|
||||||
* Virtual Router for either IPv4 or IPv6.
|
/*
|
||||||
*/
|
* VRRP Router.
|
||||||
struct vrrp_router {
|
*
|
||||||
|
* This struct contains all state for a particular VRRP Router operating
|
||||||
|
* in a Virtual Router for either IPv4 or IPv6.
|
||||||
|
*/
|
||||||
|
struct vrrp_router {
|
||||||
/*
|
/*
|
||||||
* Whether this VRRP Router is active.
|
* Whether this VRRP Router is active.
|
||||||
*/
|
*/
|
||||||
@ -164,6 +168,9 @@ struct vrrp_router {
|
|||||||
* implementations.
|
* implementations.
|
||||||
*/
|
*/
|
||||||
struct vrrp_vrouter {
|
struct vrrp_vrouter {
|
||||||
|
/* Whether this instance was automatically configured */
|
||||||
|
bool autoconf;
|
||||||
|
|
||||||
/* Interface */
|
/* Interface */
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
|
|
||||||
@ -417,6 +424,23 @@ int vrrp_event(struct vrrp_router *r, int event);
|
|||||||
|
|
||||||
/* Other ------------------------------------------------------------------- */
|
/* Other ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Search for and automatically configure VRRP instances on interfaces.
|
||||||
|
*
|
||||||
|
* ifp
|
||||||
|
* Interface to autoconfig. If it is a macvlan interface and has a VRRP MAC,
|
||||||
|
* a VRRP instance corresponding to VMAC assigned to macvlan will be created
|
||||||
|
* on the parent interface and all addresses on the macvlan interface except
|
||||||
|
* the v6 link local will be configured as VRRP addresses. If NULL, this
|
||||||
|
* treatment will be applied to all existing interfaces matching the above
|
||||||
|
* criterion.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* -1 on failure
|
||||||
|
* 0 otherwise
|
||||||
|
*/
|
||||||
|
int vrrp_autoconfig(struct interface *ifp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find VRRP Virtual Router by Virtual Router ID
|
* Find VRRP Virtual Router by Virtual Router ID
|
||||||
*/
|
*/
|
||||||
|
@ -287,6 +287,26 @@ DEFPY(vrrp_preempt,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFPY(vrrp_autoconf,
|
||||||
|
vrrp_autoconf_cmd,
|
||||||
|
"[no] vrrp autoconfig [version (2-3)]",
|
||||||
|
NO_STR
|
||||||
|
VRRP_STR
|
||||||
|
"Automatically set up VRRP instances on VRRP-compatible interfaces\n"
|
||||||
|
"Version for automatically configured instances\n"
|
||||||
|
VRRP_VERSION_STR)
|
||||||
|
{
|
||||||
|
vrrp_autoconfig_on = !no;
|
||||||
|
version = version ? version : 3;
|
||||||
|
|
||||||
|
if (vrrp_autoconfig_on)
|
||||||
|
vrrp_autoconfig(NULL);
|
||||||
|
|
||||||
|
vrrp_autoconfig_version = !no ? version : vrrp_autoconfig_version;
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static void vrrp_show(struct vty *vty, struct vrrp_vrouter *vr)
|
static void vrrp_show(struct vty *vty, struct vrrp_vrouter *vr)
|
||||||
{
|
{
|
||||||
char ethstr4[ETHER_ADDR_STRLEN];
|
char ethstr4[ETHER_ADDR_STRLEN];
|
||||||
@ -401,6 +421,7 @@ void vrrp_vty_init(void)
|
|||||||
if_cmd_init();
|
if_cmd_init();
|
||||||
install_element(VIEW_NODE, &show_debugging_vrrpd_cmd);
|
install_element(VIEW_NODE, &show_debugging_vrrpd_cmd);
|
||||||
install_element(VIEW_NODE, &vrrp_vrid_show_cmd);
|
install_element(VIEW_NODE, &vrrp_vrid_show_cmd);
|
||||||
|
install_element(CONFIG_NODE, &vrrp_autoconf_cmd);
|
||||||
install_element(INTERFACE_NODE, &vrrp_vrid_cmd);
|
install_element(INTERFACE_NODE, &vrrp_vrid_cmd);
|
||||||
install_element(INTERFACE_NODE, &vrrp_priority_cmd);
|
install_element(INTERFACE_NODE, &vrrp_priority_cmd);
|
||||||
install_element(INTERFACE_NODE, &vrrp_advertisement_interval_cmd);
|
install_element(INTERFACE_NODE, &vrrp_advertisement_interval_cmd);
|
||||||
|
@ -61,7 +61,8 @@ static int vrrp_zebra_if_add(int command, struct zclient *zclient,
|
|||||||
if (!ifp)
|
if (!ifp)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* FIXME: handle subinterface creation here */
|
if (vrrp_autoconfig_on)
|
||||||
|
vrrp_autoconfig(ifp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,7 @@
|
|||||||
static void zserv_encode_interface(struct stream *s, struct interface *ifp)
|
static void zserv_encode_interface(struct stream *s, struct interface *ifp)
|
||||||
{
|
{
|
||||||
/* Interface information. */
|
/* Interface information. */
|
||||||
|
struct zebra_if *zif = ifp->info;
|
||||||
stream_put(s, ifp->name, INTERFACE_NAMSIZ);
|
stream_put(s, ifp->name, INTERFACE_NAMSIZ);
|
||||||
stream_putl(s, ifp->ifindex);
|
stream_putl(s, ifp->ifindex);
|
||||||
stream_putc(s, ifp->status);
|
stream_putc(s, ifp->status);
|
||||||
@ -82,6 +83,7 @@ static void zserv_encode_interface(struct stream *s, struct interface *ifp)
|
|||||||
stream_putl(s, ifp->mtu);
|
stream_putl(s, ifp->mtu);
|
||||||
stream_putl(s, ifp->mtu6);
|
stream_putl(s, ifp->mtu6);
|
||||||
stream_putl(s, ifp->bandwidth);
|
stream_putl(s, ifp->bandwidth);
|
||||||
|
stream_putl(s, zif->link_ifindex);
|
||||||
stream_putl(s, ifp->ll_type);
|
stream_putl(s, ifp->ll_type);
|
||||||
stream_putl(s, ifp->hw_addr_len);
|
stream_putl(s, ifp->hw_addr_len);
|
||||||
if (ifp->hw_addr_len)
|
if (ifp->hw_addr_len)
|
||||||
|
Loading…
Reference in New Issue
Block a user