Skip to content

Commit

Permalink
Merge pull request #17297 from mjstapp/mjs_ifp_table
Browse files Browse the repository at this point in the history
zebra, lib: use internal rbtree for per-NS tree of ifps
  • Loading branch information
donaldsharp authored Nov 12, 2024
2 parents d1d8aee + b7263c0 commit ac6314d
Show file tree
Hide file tree
Showing 11 changed files with 591 additions and 480 deletions.
1 change: 1 addition & 0 deletions isisd/isis_route.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#ifndef _ZEBRA_ISIS_ROUTE_H
#define _ZEBRA_ISIS_ROUTE_H

#include "lib/table.h"
#include "lib/nexthop.h"

struct isis_nexthop {
Expand Down
6 changes: 0 additions & 6 deletions lib/if.c
Original file line number Diff line number Diff line change
Expand Up @@ -1002,12 +1002,6 @@ void if_terminate(struct vrf *vrf)

while (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) {
ifp = RB_ROOT(if_name_head, &vrf->ifaces_by_name);

if (ifp->node) {
ifp->node->info = NULL;
route_unlock_node(ifp->node);
ifp->node = NULL;
}
if_delete(&ifp);
}
}
Expand Down
2 changes: 0 additions & 2 deletions lib/if.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,6 @@ struct interface {
struct if_data stats;
#endif /* HAVE_NET_RT_IFLIST */

struct route_node *node;

struct vrf *vrf;

/*
Expand Down
66 changes: 42 additions & 24 deletions zebra/if_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1568,46 +1568,64 @@ static int netlink_request_tunneldump(struct zebra_ns *zns, int family,
return netlink_request(&zns->netlink_cmd, &req);
}

/* Prototype for tunneldump walker */
static int tunneldump_walk_cb(struct interface *ifp, void *arg);

struct tunneldump_ctx {
struct zebra_ns *zns;
struct zebra_dplane_info *dp_info;
int ret;
};

/*
* Currently we only ask for vxlan l3svd vni information.
* In the future this can be expanded.
*/
int netlink_tunneldump_read(struct zebra_ns *zns)
{
int ret = 0;
struct tunneldump_ctx ctx = {};
struct zebra_dplane_info dp_info;
struct route_node *rn;
struct interface *tmp_if = NULL;
struct zebra_if *zif;
struct nlsock *netlink_cmd = &zns->netlink_cmd;

zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);

for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
tmp_if = (struct interface *)rn->info;
if (!tmp_if)
continue;
zif = tmp_if->info;
if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
continue;
/* Set up context and call iterator */
ctx.zns = zns;
ctx.dp_info = &dp_info;

ret = netlink_request_tunneldump(zns, PF_BRIDGE,
tmp_if->ifindex);
if (ret < 0) {
route_unlock_node(rn);
return ret;
}
zebra_ns_ifp_walk(zns, tunneldump_walk_cb, &ctx);

ret = netlink_parse_info(netlink_link_change, netlink_cmd,
&dp_info, 0, true);
ret = ctx.ret;

if (ret < 0) {
route_unlock_node(rn);
return ret;
}
return ret;
}

static int tunneldump_walk_cb(struct interface *ifp, void *arg)
{
int ret;
struct tunneldump_ctx *ctx = arg;
struct zebra_if *zif;

zif = ifp->info;
if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
goto done;

ret = netlink_request_tunneldump(ctx->zns, PF_BRIDGE, ifp->ifindex);
if (ret < 0) {
ctx->ret = ret;
return NS_WALK_STOP;
}

return 0;
ret = netlink_parse_info(netlink_link_change, &(ctx->zns->netlink_cmd),
ctx->dp_info, 0, true);

if (ret < 0) {
ctx->ret = ret;
return NS_WALK_STOP;
}

done:
return NS_WALK_CONTINUE;
}

static uint8_t netlink_get_dplane_vlan_state(uint8_t state)
Expand Down
149 changes: 49 additions & 100 deletions zebra/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ DEFINE_MTYPE_STATIC(ZEBRA, ZINFO, "Zebra Interface Information");
DEFINE_HOOK(zebra_if_extra_info, (struct vty * vty, struct interface *ifp),
(vty, ifp));

DEFINE_MTYPE(ZEBRA, ZIF_DESC, "Intf desc");
DEFINE_MTYPE_STATIC(ZEBRA, ZIF_DESC, "Intf desc");

static void if_down_del_nbr_connected(struct interface *ifp);

Expand Down Expand Up @@ -215,6 +215,8 @@ static int if_zebra_delete_hook(struct interface *ifp)
if_nhg_dependents_release(ifp);
nhg_connected_tree_free(&zebra_if->nhg_dependents);

zebra_ns_unlink_ifp(ifp);

XFREE(MTYPE_ZIF_DESC, zebra_if->desc);

EVENT_OFF(zebra_if->speed_update);
Expand All @@ -225,81 +227,26 @@ static int if_zebra_delete_hook(struct interface *ifp)
return 0;
}

/* Build the table key */
static void if_build_key(uint32_t ifindex, struct prefix *p)
{
p->family = AF_INET;
p->prefixlen = IPV4_MAX_BITLEN;
p->u.prefix4.s_addr = ifindex;
}

/* Link an interface in a per NS interface tree */
struct interface *if_link_per_ns(struct zebra_ns *ns, struct interface *ifp)
{
struct prefix p;
struct route_node *rn;

if (ifp->ifindex == IFINDEX_INTERNAL)
return NULL;

if_build_key(ifp->ifindex, &p);
rn = route_node_get(ns->if_table, &p);
if (rn->info) {
ifp = (struct interface *)rn->info;
route_unlock_node(rn); /* get */
return ifp;
}

rn->info = ifp;
ifp->node = rn;

return ifp;
}

/* Delete a VRF. This is called in vrf_terminate(). */
void if_unlink_per_ns(struct interface *ifp)
{
if (!ifp->node)
return;

ifp->node->info = NULL;
route_unlock_node(ifp->node);
ifp->node = NULL;
}

/* Look up an interface by identifier within a NS */
struct interface *if_lookup_by_index_per_ns(struct zebra_ns *ns,
uint32_t ifindex)
{
struct prefix p;
struct route_node *rn;
struct interface *ifp = NULL;

if_build_key(ifindex, &p);
rn = route_node_lookup(ns->if_table, &p);
if (rn) {
ifp = (struct interface *)rn->info;
route_unlock_node(rn); /* lookup */
}
ifp = zebra_ns_lookup_ifp(ns, ifindex);

return ifp;
}

/* Look up an interface by name within a NS */
struct interface *if_lookup_by_name_per_ns(struct zebra_ns *ns,
const char *ifname)
{
struct route_node *rn;
struct interface *ifp;

for (rn = route_top(ns->if_table); rn; rn = route_next(rn)) {
ifp = (struct interface *)rn->info;
if (ifp && strcmp(ifp->name, ifname) == 0) {
route_unlock_node(rn);
return (ifp);
}
}
ifp = zebra_ns_lookup_ifp_name(ns, ifname);

return NULL;
return ifp;
}

struct interface *if_lookup_by_index_per_nsid(ns_id_t ns_id, uint32_t ifindex)
Expand Down Expand Up @@ -571,7 +518,8 @@ void if_add_update(struct interface *ifp)
zns = zvrf->zns;
else
zns = zebra_ns_lookup(NS_DEFAULT);
if_link_per_ns(zns, ifp);

zebra_ns_link_ifp(zns, ifp);
if_data = ifp->info;
assert(if_data);

Expand Down Expand Up @@ -776,15 +724,14 @@ void if_delete_update(struct interface **pifp)
/* Send out notification on interface delete. */
zebra_interface_delete_update(ifp);

if_unlink_per_ns(ifp);
zebra_ns_unlink_ifp(ifp);

/* Update ifindex after distributing the delete message. This is in
case any client needs to have the old value of ifindex available
while processing the deletion. Each client daemon is responsible
for setting ifindex to IFINDEX_INTERNAL after processing the
interface deletion message. */
if_set_index(ifp, IFINDEX_INTERNAL);
ifp->node = NULL;

UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);

Expand Down Expand Up @@ -1082,50 +1029,52 @@ void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex,
}

/*
* during initial link dump kernel does not order lower devices before
* upper devices so we need to fixup link dependencies at the end of dump
* Callback for per-ns link fixup iteration
*/
void zebra_if_update_all_links(struct zebra_ns *zns)
static int zif_link_fixup_cb(struct interface *ifp, void *arg)
{
struct route_node *rn;
struct interface *ifp;
struct zebra_if *zif;

if (IS_ZEBRA_DEBUG_KERNEL)
zlog_info("fixup link dependencies");
zif = ifp->info;
/* update bond-member to bond linkages */
if ((IS_ZEBRA_IF_BOND_SLAVE(ifp)) &&
(zif->bondslave_info.bond_ifindex != IFINDEX_INTERNAL) &&
!zif->bondslave_info.bond_if) {
if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("bond mbr %s map to bond %d", zif->ifp->name,
zif->bondslave_info.bond_ifindex);
zebra_l2_map_slave_to_bond(zif, ifp->vrf->vrf_id);
}

for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
ifp = (struct interface *)rn->info;
if (!ifp)
continue;
zif = ifp->info;
/* update bond-member to bond linkages */
if ((IS_ZEBRA_IF_BOND_SLAVE(ifp))
&& (zif->bondslave_info.bond_ifindex != IFINDEX_INTERNAL)
&& !zif->bondslave_info.bond_if) {
if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("bond mbr %s map to bond %d",
zif->ifp->name,
zif->bondslave_info.bond_ifindex);
zebra_l2_map_slave_to_bond(zif, ifp->vrf->vrf_id);
}
/* update SVI linkages */
if ((zif->link_ifindex != IFINDEX_INTERNAL) && !zif->link) {
zif->link = if_lookup_by_index_per_nsid(zif->link_nsid,
zif->link_ifindex);
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("interface %s/%d's lower fixup to %s/%d",
ifp->name, ifp->ifindex,
zif->link ? zif->link->name : "unk",
zif->link_ifindex);
}

/* update SVI linkages */
if ((zif->link_ifindex != IFINDEX_INTERNAL) && !zif->link) {
zif->link = if_lookup_by_index_per_nsid(
zif->link_nsid, zif->link_ifindex);
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("interface %s/%d's lower fixup to %s/%d",
ifp->name, ifp->ifindex,
zif->link?zif->link->name:"unk",
zif->link_ifindex);
}
/* Update VLAN<=>SVI map */
if (IS_ZEBRA_IF_VLAN(ifp))
zebra_evpn_acc_bd_svi_set(zif, NULL,
!!if_is_operative(ifp));

/* Update VLAN<=>SVI map */
if (IS_ZEBRA_IF_VLAN(ifp))
zebra_evpn_acc_bd_svi_set(zif, NULL,
!!if_is_operative(ifp));
}
return NS_WALK_CONTINUE;
}

/*
* during initial link dump kernel does not order lower devices before
* upper devices so we need to fixup link dependencies at the end of dump
*/
void zebra_if_update_all_links(struct zebra_ns *zns)
{
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("fixup link dependencies");

zebra_ns_ifp_walk(zns, zif_link_fixup_cb, NULL);
}

static bool if_ignore_set_protodown(const struct interface *ifp, bool new_down,
Expand Down
8 changes: 3 additions & 5 deletions zebra/interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,6 @@ enum zebra_if_flags {
#define ZEBRA_IF_IS_PROTODOWN_ONLY_EXTERNAL(zif) \
((zif)->protodown_rc == ZEBRA_PROTODOWN_EXTERNAL)

/* Mem type for zif desc */
DECLARE_MTYPE(ZIF_DESC);

/* `zebra' daemon local interface structure. */
struct zebra_if {
/* back pointer to the interface */
Expand Down Expand Up @@ -215,6 +212,9 @@ struct zebra_if {
char neigh_mac[6];
struct in6_addr v6_2_v4_ll_addr6;

/* Linkage for per-vrf/per-NS ifp container */
struct ifp_tree_link *ns_tree_link;

/* The description of the interface */
char *desc;
};
Expand Down Expand Up @@ -262,12 +262,10 @@ extern void zebra_if_init(void);
extern struct interface *if_lookup_by_index_per_ns(struct zebra_ns *, uint32_t);
extern struct interface *if_lookup_by_name_per_ns(struct zebra_ns *,
const char *);
extern struct interface *if_link_per_ns(struct zebra_ns *, struct interface *);
extern struct interface *if_lookup_by_index_per_nsid(ns_id_t nsid,
uint32_t ifindex);
extern const char *ifindex2ifname_per_ns(struct zebra_ns *, unsigned int);

extern void if_unlink_per_ns(struct interface *);
extern void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *fip,
char mac[6],
struct in6_addr *address,
Expand Down
Loading

0 comments on commit ac6314d

Please sign in to comment.