2023-02-08 13:17:09 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2018-11-19 21:51:52 +01:00
|
|
|
/*
|
2019-01-29 20:59:01 +01:00
|
|
|
* VRRP Zebra interfacing.
|
|
|
|
* Copyright (C) 2018-2019 Cumulus Networks, Inc.
|
|
|
|
* Quentin Young
|
2018-11-19 21:51:52 +01:00
|
|
|
*/
|
|
|
|
#include <zebra.h>
|
|
|
|
|
2018-12-04 21:41:37 +01:00
|
|
|
#include "lib/if.h"
|
2019-01-29 20:59:01 +01:00
|
|
|
#include "lib/linklist.h"
|
2018-12-04 21:41:37 +01:00
|
|
|
#include "lib/log.h"
|
|
|
|
#include "lib/prefix.h"
|
|
|
|
#include "lib/vty.h"
|
2019-01-29 20:59:01 +01:00
|
|
|
#include "lib/zclient.h"
|
2018-11-19 21:51:52 +01:00
|
|
|
|
2018-12-04 21:41:37 +01:00
|
|
|
#include "vrrp.h"
|
2019-02-19 22:08:36 +01:00
|
|
|
#include "vrrp_debug.h"
|
2018-11-19 21:51:52 +01:00
|
|
|
#include "vrrp_zebra.h"
|
|
|
|
|
2019-02-19 22:08:36 +01:00
|
|
|
#define VRRP_LOGPFX "[ZEBRA] "
|
|
|
|
|
2025-03-27 16:18:34 +01:00
|
|
|
static struct zclient *vrrp_zclient;
|
2018-12-04 21:41:37 +01:00
|
|
|
|
2021-10-22 00:17:40 +02:00
|
|
|
static void vrrp_zebra_debug_if_state(struct interface *ifp, const char *func)
|
2019-02-19 22:08:36 +01:00
|
|
|
{
|
|
|
|
DEBUGD(&vrrp_dbg_zebra,
|
2021-10-22 00:17:40 +02:00
|
|
|
"%s: %s index %d vrf %s(%u) parent %d mac %02x:%02x:%02x:%02x:%02x:%02x flags %ld metric %d mtu %d operative %d",
|
|
|
|
func, ifp->name, ifp->ifindex, ifp->vrf->name, ifp->vrf->vrf_id,
|
|
|
|
ifp->link_ifindex, ifp->hw_addr[0], ifp->hw_addr[1],
|
|
|
|
ifp->hw_addr[2], ifp->hw_addr[3], ifp->hw_addr[4],
|
|
|
|
ifp->hw_addr[5], (long)ifp->flags, ifp->metric, ifp->mtu,
|
|
|
|
if_is_operative(ifp));
|
2019-02-19 22:08:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void vrrp_zebra_debug_if_dump_address(struct interface *ifp,
|
|
|
|
const char *func)
|
|
|
|
{
|
|
|
|
struct connected *ifc;
|
|
|
|
|
|
|
|
DEBUGD(&vrrp_dbg_zebra, "%s: interface %s addresses:", func, ifp->name);
|
|
|
|
|
2023-11-22 19:05:41 +01:00
|
|
|
frr_each (if_connected, ifp->connected, ifc) {
|
2019-02-19 22:08:36 +01:00
|
|
|
struct prefix *p = ifc->address;
|
|
|
|
|
2020-10-15 17:40:36 +02:00
|
|
|
DEBUGD(&vrrp_dbg_zebra, "%s: interface %s address %pFX %s",
|
|
|
|
func, ifp->name, p,
|
2019-02-19 22:08:36 +01:00
|
|
|
CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? "secondary"
|
|
|
|
: "primary");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-12-04 21:41:37 +01:00
|
|
|
static void vrrp_zebra_connected(struct zclient *zclient)
|
|
|
|
{
|
|
|
|
zclient_send_reg_requests(zclient, VRF_DEFAULT);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Router-id update message from zebra. */
|
|
|
|
static int vrrp_router_id_update_zebra(int command, struct zclient *zclient,
|
|
|
|
zebra_size_t length, vrf_id_t vrf_id)
|
|
|
|
{
|
|
|
|
struct prefix router_id;
|
|
|
|
|
|
|
|
zebra_router_id_update_read(zclient->ibuf, &router_id);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-19 04:26:55 +02:00
|
|
|
int vrrp_ifp_create(struct interface *ifp)
|
2018-12-04 21:41:37 +01:00
|
|
|
{
|
2021-10-22 00:17:40 +02:00
|
|
|
vrrp_zebra_debug_if_state(ifp, __func__);
|
2019-02-19 22:08:36 +01:00
|
|
|
|
2019-02-14 23:28:51 +01:00
|
|
|
vrrp_if_add(ifp);
|
2018-12-04 21:41:37 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-19 15:40:57 +02:00
|
|
|
int vrrp_ifp_destroy(struct interface *ifp)
|
2018-12-04 21:41:37 +01:00
|
|
|
{
|
2021-10-22 00:17:40 +02:00
|
|
|
vrrp_zebra_debug_if_state(ifp, __func__);
|
2019-02-11 21:44:49 +01:00
|
|
|
|
2019-02-19 22:08:36 +01:00
|
|
|
vrrp_if_del(ifp);
|
2018-12-04 21:41:37 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-19 05:07:44 +02:00
|
|
|
int vrrp_ifp_up(struct interface *ifp)
|
2018-12-04 21:41:37 +01:00
|
|
|
{
|
2021-10-22 00:17:40 +02:00
|
|
|
vrrp_zebra_debug_if_state(ifp, __func__);
|
2019-02-11 21:44:49 +01:00
|
|
|
|
2019-02-19 22:08:36 +01:00
|
|
|
vrrp_if_up(ifp);
|
2018-12-04 21:41:37 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-19 05:55:34 +02:00
|
|
|
int vrrp_ifp_down(struct interface *ifp)
|
2018-12-04 21:41:37 +01:00
|
|
|
{
|
2021-10-22 00:17:40 +02:00
|
|
|
vrrp_zebra_debug_if_state(ifp, __func__);
|
2019-02-11 21:44:49 +01:00
|
|
|
|
2019-02-19 22:08:36 +01:00
|
|
|
vrrp_if_down(ifp);
|
2018-12-04 21:41:37 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int vrrp_zebra_if_address_add(int command, struct zclient *zclient,
|
|
|
|
zebra_size_t length, vrf_id_t vrf_id)
|
|
|
|
{
|
|
|
|
struct connected *c;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* zebra api notifies address adds/dels events by using the same call
|
|
|
|
* interface_add_read below, see comments in lib/zclient.c
|
|
|
|
*
|
|
|
|
* zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
|
|
|
|
* will add address to interface list by calling
|
|
|
|
* connected_add_by_prefix()
|
|
|
|
*/
|
|
|
|
c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
|
2019-02-19 22:08:36 +01:00
|
|
|
|
2018-12-04 21:41:37 +01:00
|
|
|
if (!c)
|
|
|
|
return 0;
|
|
|
|
|
2021-10-22 00:17:40 +02:00
|
|
|
vrrp_zebra_debug_if_state(c->ifp, __func__);
|
2019-02-19 22:08:36 +01:00
|
|
|
vrrp_zebra_debug_if_dump_address(c->ifp, __func__);
|
2018-12-04 21:41:37 +01:00
|
|
|
|
2019-02-19 22:08:36 +01:00
|
|
|
vrrp_if_address_add(c->ifp);
|
2018-12-04 21:41:37 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int vrrp_zebra_if_address_del(int command, struct zclient *client,
|
|
|
|
zebra_size_t length, vrf_id_t vrf_id)
|
|
|
|
{
|
|
|
|
struct connected *c;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* zebra api notifies address adds/dels events by using the same call
|
|
|
|
* interface_add_read below, see comments in lib/zclient.c
|
|
|
|
*
|
|
|
|
* zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
|
|
|
|
* will remove address from interface list by calling
|
|
|
|
* connected_delete_by_prefix()
|
|
|
|
*/
|
|
|
|
c = zebra_interface_address_read(command, client->ibuf, vrf_id);
|
2019-02-19 22:08:36 +01:00
|
|
|
|
2018-12-04 21:41:37 +01:00
|
|
|
if (!c)
|
|
|
|
return 0;
|
|
|
|
|
2021-10-22 00:17:40 +02:00
|
|
|
vrrp_zebra_debug_if_state(c->ifp, __func__);
|
2019-02-19 22:08:36 +01:00
|
|
|
vrrp_zebra_debug_if_dump_address(c->ifp, __func__);
|
|
|
|
|
2019-02-14 23:28:51 +01:00
|
|
|
vrrp_if_address_del(c->ifp);
|
2019-02-11 21:44:49 +01:00
|
|
|
|
2018-12-04 21:41:37 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2018-11-19 21:51:52 +01:00
|
|
|
|
2019-01-28 21:15:00 +01:00
|
|
|
void vrrp_zebra_radv_set(struct vrrp_router *r, bool enable)
|
|
|
|
{
|
2019-02-19 22:08:36 +01:00
|
|
|
DEBUGD(&vrrp_dbg_zebra,
|
|
|
|
VRRP_LOGPFX VRRP_LOGPFX_VRID
|
|
|
|
"Requesting Zebra to turn router advertisements %s for %s",
|
|
|
|
r->vr->vrid, enable ? "on" : "off", r->mvl_ifp->name);
|
|
|
|
|
2025-03-27 16:18:34 +01:00
|
|
|
zclient_send_interface_radv_req(vrrp_zclient, r->mvl_ifp->vrf->vrf_id,
|
2021-10-22 00:17:40 +02:00
|
|
|
r->mvl_ifp, enable, VRRP_RADV_INT);
|
2019-01-28 21:15:00 +01:00
|
|
|
}
|
|
|
|
|
2020-11-11 20:14:37 +01:00
|
|
|
void vrrp_zclient_send_interface_protodown(struct interface *ifp, bool down)
|
2019-02-05 23:02:40 +01:00
|
|
|
{
|
2019-02-19 22:08:36 +01:00
|
|
|
DEBUGD(&vrrp_dbg_zebra,
|
|
|
|
VRRP_LOGPFX "Requesting Zebra to set %s protodown %s", ifp->name,
|
|
|
|
down ? "on" : "off");
|
|
|
|
|
2025-03-27 16:18:34 +01:00
|
|
|
zclient_send_interface_protodown(vrrp_zclient, ifp->vrf->vrf_id, ifp, down);
|
2019-02-05 23:02:40 +01:00
|
|
|
}
|
|
|
|
|
2021-10-20 13:07:47 +02:00
|
|
|
static zclient_handler *const vrrp_handlers[] = {
|
|
|
|
[ZEBRA_ROUTER_ID_UPDATE] = vrrp_router_id_update_zebra,
|
|
|
|
[ZEBRA_INTERFACE_ADDRESS_ADD] = vrrp_zebra_if_address_add,
|
|
|
|
[ZEBRA_INTERFACE_ADDRESS_DELETE] = vrrp_zebra_if_address_del,
|
|
|
|
};
|
|
|
|
|
2018-11-19 21:51:52 +01:00
|
|
|
void vrrp_zebra_init(void)
|
|
|
|
{
|
2023-11-02 21:49:28 +01:00
|
|
|
hook_register_prio(if_real, 0, vrrp_ifp_create);
|
|
|
|
hook_register_prio(if_up, 0, vrrp_ifp_up);
|
|
|
|
hook_register_prio(if_down, 0, vrrp_ifp_down);
|
|
|
|
hook_register_prio(if_unreal, 0, vrrp_ifp_destroy);
|
2019-09-18 22:20:04 +02:00
|
|
|
|
2018-12-04 21:41:37 +01:00
|
|
|
/* Socket for receiving updates from Zebra daemon */
|
2025-03-27 16:18:34 +01:00
|
|
|
vrrp_zclient = zclient_new(master, &zclient_options_default, vrrp_handlers,
|
|
|
|
array_size(vrrp_handlers));
|
2018-11-19 21:51:52 +01:00
|
|
|
|
2025-03-27 16:18:34 +01:00
|
|
|
vrrp_zclient->zebra_connected = vrrp_zebra_connected;
|
2018-11-19 21:51:52 +01:00
|
|
|
|
2025-03-27 16:18:34 +01:00
|
|
|
zclient_init(vrrp_zclient, ZEBRA_ROUTE_VRRP, 0, &vrrp_privs);
|
2018-11-19 21:51:52 +01:00
|
|
|
|
2020-03-05 19:17:54 +01:00
|
|
|
zlog_notice("%s: zclient socket initialized", __func__);
|
2018-12-04 21:41:37 +01:00
|
|
|
}
|