forked from Mirror/frr
lib: if: track oper-state inline
Signed-off-by: Christian Hopps <chopps@labn.net>
This commit is contained in:
parent
e64966876c
commit
80c6f98ea7
128
lib/if.c
128
lib/if.c
|
@ -29,6 +29,10 @@
|
||||||
#include "admin_group.h"
|
#include "admin_group.h"
|
||||||
#include "lib/if_clippy.c"
|
#include "lib/if_clippy.c"
|
||||||
|
|
||||||
|
|
||||||
|
/* Set by the owner (zebra). */
|
||||||
|
bool if_notify_oper_changes;
|
||||||
|
|
||||||
DEFINE_MTYPE_STATIC(LIB, IF, "Interface");
|
DEFINE_MTYPE_STATIC(LIB, IF, "Interface");
|
||||||
DEFINE_MTYPE_STATIC(LIB, IFDESC, "Intf Desc");
|
DEFINE_MTYPE_STATIC(LIB, IFDESC, "Intf Desc");
|
||||||
DEFINE_MTYPE_STATIC(LIB, CONNECTED, "Connected");
|
DEFINE_MTYPE_STATIC(LIB, CONNECTED, "Connected");
|
||||||
|
@ -208,6 +212,104 @@ void if_down_via_zapi(struct interface *ifp)
|
||||||
hook_call(if_down, ifp);
|
hook_call(if_down, ifp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void if_update_state_metric(struct interface *ifp, uint32_t metric)
|
||||||
|
{
|
||||||
|
if (ifp->metric == metric)
|
||||||
|
return;
|
||||||
|
ifp->metric = metric;
|
||||||
|
if (ifp->state && if_notify_oper_changes)
|
||||||
|
nb_op_updatef(ifp->state, "metric", "%u", ifp->metric);
|
||||||
|
}
|
||||||
|
|
||||||
|
void if_update_state_mtu(struct interface *ifp, uint mtu)
|
||||||
|
{
|
||||||
|
if (ifp->mtu == mtu)
|
||||||
|
return;
|
||||||
|
ifp->mtu = mtu;
|
||||||
|
if (ifp->state && if_notify_oper_changes)
|
||||||
|
nb_op_updatef(ifp->state, "mtu", "%u", ifp->mtu);
|
||||||
|
}
|
||||||
|
|
||||||
|
void if_update_state_mtu6(struct interface *ifp, uint mtu)
|
||||||
|
{
|
||||||
|
if (ifp->mtu6 == mtu)
|
||||||
|
return;
|
||||||
|
ifp->mtu6 = mtu;
|
||||||
|
if (ifp->state && if_notify_oper_changes)
|
||||||
|
nb_op_updatef(ifp->state, "mtu6", "%u", ifp->mtu);
|
||||||
|
}
|
||||||
|
|
||||||
|
void if_update_state_hw_addr(struct interface *ifp, const uint8_t *hw_addr, uint len)
|
||||||
|
{
|
||||||
|
if (len == (uint)ifp->hw_addr_len && (len == 0 || !memcmp(hw_addr, ifp->hw_addr, len)))
|
||||||
|
return;
|
||||||
|
memcpy(ifp->hw_addr, hw_addr, len);
|
||||||
|
ifp->hw_addr_len = len;
|
||||||
|
if (ifp->state && if_notify_oper_changes)
|
||||||
|
nb_op_updatef(ifp->state, "phy-address", "%pEA", (struct ethaddr *)ifp->hw_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void if_update_state_speed(struct interface *ifp, uint32_t speed)
|
||||||
|
{
|
||||||
|
if (ifp->speed == speed)
|
||||||
|
return;
|
||||||
|
ifp->speed = speed;
|
||||||
|
if (ifp->state && if_notify_oper_changes)
|
||||||
|
nb_op_updatef(ifp->state, "speed", "%u", ifp->speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void if_update_state(struct interface *ifp)
|
||||||
|
{
|
||||||
|
struct lyd_node *state = ifp->state;
|
||||||
|
|
||||||
|
if (!state || !if_notify_oper_changes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove top level container update when we have patch support, for now
|
||||||
|
* this keeps us from generating 6 separate REPLACE messages though.
|
||||||
|
*/
|
||||||
|
// nb_op_update(state, ".", NULL);
|
||||||
|
nb_op_updatef(state, "if-index", "%d", ifp->ifindex);
|
||||||
|
nb_op_updatef(state, "mtu", "%u", ifp->mtu);
|
||||||
|
nb_op_updatef(state, "mtu6", "%u", ifp->mtu);
|
||||||
|
nb_op_updatef(state, "speed", "%u", ifp->speed);
|
||||||
|
nb_op_updatef(state, "metric", "%u", ifp->metric);
|
||||||
|
nb_op_updatef(state, "phy-address", "%pEA", (struct ethaddr *)ifp->hw_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void if_update_state_remove(struct interface *ifp)
|
||||||
|
{
|
||||||
|
if (!if_notify_oper_changes || ifp->name[0] == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (vrf_is_backend_netns())
|
||||||
|
nb_op_update_delete_pathf(NULL, "/frr-interface:lib/interface[name=\"%s:%s\"]/state",
|
||||||
|
ifp->vrf->name, ifp->name);
|
||||||
|
else
|
||||||
|
nb_op_update_delete_pathf(NULL, "/frr-interface:lib/interface[name=\"%s\"]/state",
|
||||||
|
ifp->name);
|
||||||
|
if (ifp->state) {
|
||||||
|
lyd_free_all(ifp->state);
|
||||||
|
ifp->state = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void if_update_state_add(struct interface *ifp)
|
||||||
|
{
|
||||||
|
if (!if_notify_oper_changes || ifp->name[0] == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (vrf_is_backend_netns())
|
||||||
|
ifp->state = nb_op_update_pathf(NULL,
|
||||||
|
"/frr-interface:lib/interface[name=\"%s:%s\"]/state",
|
||||||
|
NULL, ifp->vrf->name, ifp->name);
|
||||||
|
else
|
||||||
|
ifp->state = nb_op_update_pathf(NULL,
|
||||||
|
"/frr-interface:lib/interface[name=\"%s\"]/state",
|
||||||
|
NULL, ifp->name);
|
||||||
|
}
|
||||||
|
|
||||||
static struct interface *if_create_name(const char *name, struct vrf *vrf)
|
static struct interface *if_create_name(const char *name, struct vrf *vrf)
|
||||||
{
|
{
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
|
@ -216,7 +318,11 @@ static struct interface *if_create_name(const char *name, struct vrf *vrf)
|
||||||
|
|
||||||
if_set_name(ifp, name);
|
if_set_name(ifp, name);
|
||||||
|
|
||||||
|
if (if_notify_oper_changes && ifp->state)
|
||||||
|
if_update_state(ifp);
|
||||||
|
|
||||||
hook_call(if_add, ifp);
|
hook_call(if_add, ifp);
|
||||||
|
|
||||||
return ifp;
|
return ifp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,8 +334,10 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
|
||||||
/* remove interface from old master vrf list */
|
/* remove interface from old master vrf list */
|
||||||
old_vrf = ifp->vrf;
|
old_vrf = ifp->vrf;
|
||||||
|
|
||||||
if (ifp->name[0] != '\0')
|
if (ifp->name[0] != '\0') {
|
||||||
IFNAME_RB_REMOVE(old_vrf, ifp);
|
IFNAME_RB_REMOVE(old_vrf, ifp);
|
||||||
|
if_update_state_remove(ifp);
|
||||||
|
}
|
||||||
|
|
||||||
if (ifp->ifindex != IFINDEX_INTERNAL)
|
if (ifp->ifindex != IFINDEX_INTERNAL)
|
||||||
IFINDEX_RB_REMOVE(old_vrf, ifp);
|
IFINDEX_RB_REMOVE(old_vrf, ifp);
|
||||||
|
@ -237,8 +345,11 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
|
||||||
vrf = vrf_get(vrf_id, NULL);
|
vrf = vrf_get(vrf_id, NULL);
|
||||||
ifp->vrf = vrf;
|
ifp->vrf = vrf;
|
||||||
|
|
||||||
if (ifp->name[0] != '\0')
|
if (ifp->name[0] != '\0') {
|
||||||
IFNAME_RB_INSERT(vrf, ifp);
|
IFNAME_RB_INSERT(vrf, ifp);
|
||||||
|
if_update_state_add(ifp);
|
||||||
|
if_update_state(ifp);
|
||||||
|
}
|
||||||
|
|
||||||
if (ifp->ifindex != IFINDEX_INTERNAL)
|
if (ifp->ifindex != IFINDEX_INTERNAL)
|
||||||
IFINDEX_RB_INSERT(vrf, ifp);
|
IFINDEX_RB_INSERT(vrf, ifp);
|
||||||
|
@ -280,6 +391,8 @@ void if_delete(struct interface **ifp)
|
||||||
|
|
||||||
XFREE(MTYPE_IFDESC, ptr->desc);
|
XFREE(MTYPE_IFDESC, ptr->desc);
|
||||||
|
|
||||||
|
if_update_state_remove(ptr);
|
||||||
|
|
||||||
XFREE(MTYPE_IF, ptr);
|
XFREE(MTYPE_IF, ptr);
|
||||||
*ifp = NULL;
|
*ifp = NULL;
|
||||||
}
|
}
|
||||||
|
@ -630,6 +743,9 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex)
|
||||||
|
|
||||||
ifp->ifindex = ifindex;
|
ifp->ifindex = ifindex;
|
||||||
|
|
||||||
|
if (if_notify_oper_changes)
|
||||||
|
nb_op_updatef(ifp->state, "if-index", "%d", ifp->ifindex);
|
||||||
|
|
||||||
if (ifp->ifindex != IFINDEX_INTERNAL) {
|
if (ifp->ifindex != IFINDEX_INTERNAL) {
|
||||||
/*
|
/*
|
||||||
* This should never happen, since we checked if there was
|
* This should never happen, since we checked if there was
|
||||||
|
@ -648,13 +764,17 @@ static void if_set_name(struct interface *ifp, const char *name)
|
||||||
if (if_cmp_name_func(ifp->name, name) == 0)
|
if (if_cmp_name_func(ifp->name, name) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ifp->name[0] != '\0')
|
if (ifp->name[0] != '\0') {
|
||||||
IFNAME_RB_REMOVE(ifp->vrf, ifp);
|
IFNAME_RB_REMOVE(ifp->vrf, ifp);
|
||||||
|
if_update_state_remove(ifp);
|
||||||
|
}
|
||||||
|
|
||||||
strlcpy(ifp->name, name, sizeof(ifp->name));
|
strlcpy(ifp->name, name, sizeof(ifp->name));
|
||||||
|
|
||||||
if (ifp->name[0] != '\0')
|
if (ifp->name[0] != '\0') {
|
||||||
IFNAME_RB_INSERT(ifp->vrf, ifp);
|
IFNAME_RB_INSERT(ifp->vrf, ifp);
|
||||||
|
if_update_state_add(ifp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Does interface up ? */
|
/* Does interface up ? */
|
||||||
|
|
10
lib/if.h
10
lib/if.h
|
@ -297,6 +297,8 @@ struct interface {
|
||||||
|
|
||||||
struct vrf *vrf;
|
struct vrf *vrf;
|
||||||
|
|
||||||
|
struct lyd_node *state;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Has the end users entered `interface XXXX` from the cli in some
|
* Has the end users entered `interface XXXX` from the cli in some
|
||||||
* fashion?
|
* fashion?
|
||||||
|
@ -633,6 +635,14 @@ extern void if_up_via_zapi(struct interface *ifp);
|
||||||
extern void if_down_via_zapi(struct interface *ifp);
|
extern void if_down_via_zapi(struct interface *ifp);
|
||||||
extern void if_destroy_via_zapi(struct interface *ifp);
|
extern void if_destroy_via_zapi(struct interface *ifp);
|
||||||
|
|
||||||
|
extern void if_update_state(struct interface *ifp);
|
||||||
|
extern void if_update_state_metric(struct interface *ifp, uint32_t metric);
|
||||||
|
extern void if_update_state_mtu(struct interface *ifp, uint mtu);
|
||||||
|
extern void if_update_state_mtu6(struct interface *ifp, uint mtu);
|
||||||
|
extern void if_update_state_hw_addr(struct interface *ifp, const uint8_t *hw_addr, uint len);
|
||||||
|
extern void if_update_state_speed(struct interface *ifp, uint32_t speed);
|
||||||
|
|
||||||
|
extern bool if_notify_oper_changes;
|
||||||
extern const struct frr_yang_module_info frr_interface_info;
|
extern const struct frr_yang_module_info frr_interface_info;
|
||||||
extern const struct frr_yang_module_info frr_interface_cli_info;
|
extern const struct frr_yang_module_info frr_interface_cli_info;
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ static void if_zebra_speed_update(struct event *thread)
|
||||||
if (new_speed != ifp->speed) {
|
if (new_speed != ifp->speed) {
|
||||||
zlog_info("%s: %s old speed: %u new speed: %u", __func__,
|
zlog_info("%s: %s old speed: %u new speed: %u", __func__,
|
||||||
ifp->name, ifp->speed, new_speed);
|
ifp->name, ifp->speed, new_speed);
|
||||||
ifp->speed = new_speed;
|
if_update_state_speed(ifp, new_speed);
|
||||||
if_add_update(ifp);
|
if_add_update(ifp);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
@ -1563,17 +1563,20 @@ static inline void zebra_if_set_ziftype(struct interface *ifp,
|
||||||
static void interface_update_hw_addr(struct zebra_dplane_ctx *ctx,
|
static void interface_update_hw_addr(struct zebra_dplane_ctx *ctx,
|
||||||
struct interface *ifp)
|
struct interface *ifp)
|
||||||
{
|
{
|
||||||
int i;
|
uint8_t hw_addr[INTERFACE_HWADDR_MAX];
|
||||||
|
uint i, hw_addr_len;
|
||||||
|
|
||||||
ifp->hw_addr_len = dplane_ctx_get_ifp_hw_addr_len(ctx);
|
hw_addr_len = dplane_ctx_get_ifp_hw_addr_len(ctx);
|
||||||
memcpy(ifp->hw_addr, dplane_ctx_get_ifp_hw_addr(ctx), ifp->hw_addr_len);
|
memcpy(hw_addr, dplane_ctx_get_ifp_hw_addr(ctx), hw_addr_len);
|
||||||
|
|
||||||
for (i = 0; i < ifp->hw_addr_len; i++)
|
for (i = 0; i < hw_addr_len; i++)
|
||||||
if (ifp->hw_addr[i] != 0)
|
if (hw_addr[i] != 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (i == ifp->hw_addr_len)
|
if (i == hw_addr_len)
|
||||||
ifp->hw_addr_len = 0;
|
hw_addr_len = 0;
|
||||||
|
|
||||||
|
if_update_state_hw_addr(ifp, hw_addr, hw_addr_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void interface_update_l2info(struct zebra_dplane_ctx *ctx,
|
static void interface_update_l2info(struct zebra_dplane_ctx *ctx,
|
||||||
|
@ -1984,9 +1987,10 @@ static void zebra_if_dplane_ifp_handling(struct zebra_dplane_ctx *ctx)
|
||||||
/* Update interface information. */
|
/* Update interface information. */
|
||||||
set_ifindex(ifp, ifindex, zns);
|
set_ifindex(ifp, ifindex, zns);
|
||||||
ifp->flags = flags;
|
ifp->flags = flags;
|
||||||
ifp->mtu6 = ifp->mtu = mtu;
|
if_update_state_mtu(ifp, mtu);
|
||||||
ifp->metric = 0;
|
if_update_state_mtu6(ifp, mtu);
|
||||||
ifp->speed = kernel_get_speed(ifp, NULL);
|
if_update_state_metric(ifp, 0);
|
||||||
|
if_update_state_speed(ifp, kernel_get_speed(ifp, NULL));
|
||||||
ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
|
ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
|
||||||
ifp->txqlen = dplane_ctx_get_intf_txqlen(ctx);
|
ifp->txqlen = dplane_ctx_get_intf_txqlen(ctx);
|
||||||
|
|
||||||
|
@ -2036,6 +2040,7 @@ static void zebra_if_dplane_ifp_handling(struct zebra_dplane_ctx *ctx)
|
||||||
IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(
|
IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(
|
||||||
zif));
|
zif));
|
||||||
}
|
}
|
||||||
|
// if_update_state(ifp);
|
||||||
} else if (ifp->vrf->vrf_id != vrf_id) {
|
} else if (ifp->vrf->vrf_id != vrf_id) {
|
||||||
/* VRF change for an interface. */
|
/* VRF change for an interface. */
|
||||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||||
|
@ -2058,8 +2063,9 @@ static void zebra_if_dplane_ifp_handling(struct zebra_dplane_ctx *ctx)
|
||||||
(unsigned long long)flags);
|
(unsigned long long)flags);
|
||||||
|
|
||||||
set_ifindex(ifp, ifindex, zns);
|
set_ifindex(ifp, ifindex, zns);
|
||||||
ifp->mtu6 = ifp->mtu = mtu;
|
if_update_state_mtu(ifp, mtu);
|
||||||
ifp->metric = 0;
|
if_update_state_mtu6(ifp, mtu);
|
||||||
|
if_update_state_metric(ifp, 0);
|
||||||
ifp->txqlen = dplane_ctx_get_intf_txqlen(ctx);
|
ifp->txqlen = dplane_ctx_get_intf_txqlen(ctx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -356,6 +356,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
zserv_path = NULL;
|
zserv_path = NULL;
|
||||||
|
|
||||||
|
if_notify_oper_changes = true;
|
||||||
vrf_notify_oper_changes = true;
|
vrf_notify_oper_changes = true;
|
||||||
|
|
||||||
vrf_configure_backend(VRF_BACKEND_VRF_LITE);
|
vrf_configure_backend(VRF_BACKEND_VRF_LITE);
|
||||||
|
|
Loading…
Reference in a new issue