/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; see the file COPYING; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "lib/zebra.h" #include "lib/prefix.h" #include "lib/agg_table.h" #include "lib/memory.h" #include "lib/vty.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_route.h" #include "bgpd/rfapi/vnc_export_table.h" #include "bgpd/rfapi/rfapi_private.h" #include "bgpd/rfapi/rfapi_import.h" #include "bgpd/rfapi/vnc_debug.h" struct agg_node *vnc_etn_get(struct bgp *bgp, vnc_export_type_t type, const struct prefix *p) { struct agg_table *t = NULL; struct agg_node *rn = NULL; afi_t afi; if (!bgp || !bgp->rfapi) return NULL; afi = family2afi(p->family); assert(afi == AFI_IP || afi == AFI_IP6); switch (type) { case EXPORT_TYPE_BGP: if (!bgp->rfapi->rt_export_bgp[afi]) bgp->rfapi->rt_export_bgp[afi] = agg_table_init(); t = bgp->rfapi->rt_export_bgp[afi]; break; case EXPORT_TYPE_ZEBRA: if (!bgp->rfapi->rt_export_zebra[afi]) bgp->rfapi->rt_export_zebra[afi] = agg_table_init(); t = bgp->rfapi->rt_export_zebra[afi]; break; } if (t) rn = agg_node_get(t, p); return rn; } struct agg_node *vnc_etn_lookup(struct bgp *bgp, vnc_export_type_t type, const struct prefix *p) { struct agg_table *t = NULL; struct agg_node *rn = NULL; afi_t afi; if (!bgp || !bgp->rfapi) return NULL; afi = family2afi(p->family); assert(afi == AFI_IP || afi == AFI_IP6); switch (type) { case EXPORT_TYPE_BGP: if (!bgp->rfapi->rt_export_bgp[afi]) bgp->rfapi->rt_export_bgp[afi] = agg_table_init(); t = bgp->rfapi->rt_export_bgp[afi]; break; case EXPORT_TYPE_ZEBRA: if (!bgp->rfapi->rt_export_zebra[afi]) bgp->rfapi->rt_export_zebra[afi] = agg_table_init(); t = bgp->rfapi->rt_export_zebra[afi]; break; } if (t) rn = agg_node_lookup(t, p); return rn; } struct vnc_export_info *vnc_eti_get(struct bgp *bgp, vnc_export_type_t etype, const struct prefix *p, struct peer *peer, uint8_t type, uint8_t subtype) { struct agg_node *etn; struct vnc_export_info *eti; etn = vnc_etn_get(bgp, etype, p); assert(etn); for (eti = etn->info; eti; eti = eti->next) { if (peer == eti->peer && type == eti->type && subtype == eti->subtype) { break; } } if (eti) { agg_unlock_node(etn); } else { eti = XCALLOC(MTYPE_RFAPI_ETI, sizeof(struct vnc_export_info)); eti->node = etn; eti->peer = peer; peer_lock(peer); eti->type = type; eti->subtype = subtype; eti->next = etn->info; etn->info = eti; } return eti; } void vnc_eti_delete(struct vnc_export_info *goner) { struct agg_node *etn; struct vnc_export_info *eti; struct vnc_export_info *eti_prev = NULL; etn = goner->node; for (eti = etn->info; eti; eti_prev = eti, eti = eti->next) { if (eti == goner) break; } if (!eti) { vnc_zlog_debug_verbose("%s: COULDN'T FIND ETI", __func__); return; } if (eti_prev) { eti_prev->next = goner->next; } else { etn->info = goner->next; } peer_unlock(eti->peer); goner->node = NULL; XFREE(MTYPE_RFAPI_ETI, goner); agg_unlock_node(etn); } struct vnc_export_info *vnc_eti_checktimer(struct bgp *bgp, vnc_export_type_t etype, const struct prefix *p, struct peer *peer, uint8_t type, uint8_t subtype) { struct agg_node *etn; struct vnc_export_info *eti; etn = vnc_etn_lookup(bgp, etype, p); if (!etn) return NULL; for (eti = etn->info; eti; eti = eti->next) { if (peer == eti->peer && type == eti->type && subtype == eti->subtype) { break; } } agg_unlock_node(etn); if (eti && eti->timer) return eti; return NULL; }