* 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 GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * 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 <zebra.h>
#include "linklist.h"
#include "command.h"
#include "memory.h"
+#include "srcdest_table.h"
+#include "vty.h"
#include "zebra/debug.h"
#include "zebra/zserv.h"
#include "zebra/rib.h"
#include "zebra/zebra_vrf.h"
+#include "zebra/zebra_rnh.h"
#include "zebra/router-id.h"
#include "zebra/zebra_memory.h"
#include "zebra/zebra_static.h"
+#include "zebra/interface.h"
#include "zebra/zebra_mpls.h"
extern struct zebra_t zebrad;
(si->ifindex != ifp->ifindex))
{
si->ifindex = ifp->ifindex;
- static_install_route (afi, safi, &rn->p, si);
+ static_install_route (afi, safi, &rn->p, NULL, si);
}
}
}
zebra_vrf_enable (struct vrf *vrf)
{
struct zebra_vrf *zvrf = vrf->info;
- struct route_table *stable = NULL;
- struct route_node *rn = NULL;
- struct static_route *si = NULL;
- struct interface *ifp = NULL;
+ struct route_table *stable;
+ struct route_node *rn;
+ struct static_route *si;
+ struct interface *ifp;
afi_t afi;
safi_t safi;
zebra_vrf_add_update (zvrf);
for (afi = AFI_IP; afi < AFI_MAX; afi++)
- {
- for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
- {
- stable = zvrf->stable[afi][safi];
- if (stable)
+ for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+ {
+ stable = zvrf->stable[afi][safi];
+ if (! stable)
+ continue;
+
+ for (rn = route_top (stable); rn; rn = route_next (rn))
+ for (si = rn->info; si; si = si->next)
{
- for (rn = route_top (stable); rn; rn = route_next (rn))
+ si->vrf_id = vrf->vrf_id;
+ if (si->ifindex)
{
- if (rn->info)
- {
- si = rn->info;
- si->vrf_id = vrf->vrf_id;
- if (si->ifindex)
- {
- ifp = if_lookup_by_name_vrf (si->ifname, si->vrf_id);
- if (ifp)
- si->ifindex = ifp->ifindex;
- else
- continue;
- }
- static_install_route (afi, safi, &rn->p, si);
- }
+ ifp = if_lookup_by_name (si->ifname, si->vrf_id);
+ if (ifp)
+ si->ifindex = ifp->ifindex;
+ else
+ continue;
}
+ static_install_route (afi, safi, &rn->p, NULL, si);
}
- }
- }
+ }
+
return 0;
}
zebra_vrf_disable (struct vrf *vrf)
{
struct zebra_vrf *zvrf = vrf->info;
- struct route_table *stable = NULL;
- struct route_node *rn = NULL;
+ struct route_table *stable;
+ struct route_node *rn;
+ struct static_route *si;
afi_t afi;
safi_t safi;
zvrf_name (zvrf), zvrf_id (zvrf));
for (afi = AFI_IP; afi < AFI_MAX; afi++)
- {
- for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
- {
- stable = zvrf->stable[afi][safi];
- if (stable)
- {
- for (rn = route_top (stable); rn; rn = route_next (rn))
- {
- if (rn->info)
- static_uninstall_route(afi, safi, &rn->p, rn->info);
- }
- }
- }
- }
+ for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+ {
+ stable = zvrf->stable[afi][safi];
+ if (! stable)
+ continue;
+
+ for (rn = route_top (stable); rn; rn = route_next (rn))
+ for (si = rn->info; si; si = si->next)
+ static_uninstall_route(afi, safi, &rn->p, NULL, si);
+ }
+
return 0;
}
zebra_vrf_delete (struct vrf *vrf)
{
struct zebra_vrf *zvrf = vrf->info;
+ struct route_table *table;
+ u_int32_t table_id;
+ afi_t afi;
+ safi_t safi;
+ unsigned i;
assert (zvrf);
zebra_vrf_delete_update (zvrf);
- rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
- rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
+ /* uninstall everything */
+ if (! CHECK_FLAG (zvrf->flags, ZEBRA_VRF_RETAIN))
+ {
+ struct listnode *node;
+ struct interface *ifp;
+
+ for (afi = AFI_IP; afi <= AFI_IP6; afi++)
+ {
+ for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
+ rib_close_table (zvrf->table[afi][safi]);
+
+ if (vrf->vrf_id == VRF_DEFAULT)
+ for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++)
+ if (zvrf->other_table[afi][table_id])
+ rib_close_table (zvrf->other_table[afi][table_id]);
+ }
+
+ zebra_mpls_close_tables (zvrf);
+
+ for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp))
+ if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp);
+ }
+
+ /* clean-up work queues */
+ for (i = 0; i < MQ_SIZE; i++)
+ {
+ struct listnode *lnode, *nnode;
+ struct route_node *rnode;
+ rib_dest_t *dest;
+
+ for (ALL_LIST_ELEMENTS (zebrad.mq->subq[i], lnode, nnode, rnode))
+ {
+ dest = rib_dest_from_rnode (rnode);
+ if (dest && rib_dest_vrf (dest) == zvrf)
+ {
+ route_unlock_node (rnode);
+ list_delete_node (zebrad.mq->subq[i], lnode);
+ zebrad.mq->size--;
+ }
+ }
+ }
+
+ /* release allocated memory */
+ for (afi = AFI_IP; afi <= AFI_IP6; afi++)
+ {
+ void *table_info;
+
+ for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
+ {
+ table = zvrf->table[afi][safi];
+ table_info = table->info;
+ route_table_finish (table);
+ XFREE (MTYPE_RIB_TABLE_INFO, table_info);
+
+ table = zvrf->stable[afi][safi];
+ route_table_finish (table);
+ }
+ for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++)
+ if (zvrf->other_table[afi][table_id])
+ {
+ table = zvrf->other_table[afi][table_id];
+ table_info = table->info;
+ route_table_finish (table);
+ XFREE (MTYPE_RIB_TABLE_INFO, table_info);
+ }
+
+ route_table_finish (zvrf->rnh_table[afi]);
+ route_table_finish (zvrf->import_check_table[afi]);
+ }
list_delete_all_node (zvrf->rid_all_sorted_list);
list_delete_all_node (zvrf->rid_lo_sorted_list);
-
- vrf->vrf_id = VRF_UNKNOWN;
+ XFREE (MTYPE_ZEBRA_VRF, zvrf);
vrf->info = NULL;
return 0;
return table;
}
+static void
+zebra_rtable_node_cleanup (struct route_table *table, struct route_node *node)
+{
+ struct rib *rib, *next;
+
+ RNODE_FOREACH_RIB_SAFE (node, rib, next)
+ rib_unlink (node, rib);
+
+ if (node->info)
+ XFREE (MTYPE_RIB_DEST, node->info);
+}
+
+static void
+zebra_stable_node_cleanup (struct route_table *table, struct route_node *node)
+{
+ struct static_route *si, *next;
+
+ if (node->info)
+ for (si = node->info; si; si = next)
+ {
+ next = si->next;
+ XFREE (MTYPE_STATIC_ROUTE, si);
+ }
+}
+
+static void
+zebra_rnhtable_node_cleanup (struct route_table *table, struct route_node *node)
+{
+ if (node->info)
+ zebra_free_rnh (node->info);
+}
+
/*
* Create a routing table for the specific AFI/SAFI in the given VRF.
*/
assert (!zvrf->table[afi][safi]);
- table = route_table_init ();
+ if (afi == AFI_IP6)
+ table = srcdest_table_init();
+ else
+ table = route_table_init();
+ table->cleanup = zebra_rtable_node_cleanup;
zvrf->table[afi][safi] = table;
info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
zebra_vrf_alloc (void)
{
struct zebra_vrf *zvrf;
+ afi_t afi;
+ safi_t safi;
+ struct route_table *table;
zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf));
- /* Allocate routing table and static table. */
- zebra_vrf_table_create (zvrf, AFI_IP, SAFI_UNICAST);
- zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_UNICAST);
- zvrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
- zvrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
- zebra_vrf_table_create (zvrf, AFI_IP, SAFI_MULTICAST);
- zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_MULTICAST);
- zvrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init ();
- zvrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init ();
+ for (afi = AFI_IP; afi <= AFI_IP6; afi++)
+ {
+ for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
+ {
+ zebra_vrf_table_create (zvrf, afi, safi);
+ if (afi == AFI_IP6)
+ table = srcdest_table_init();
+ else
+ table = route_table_init();
+ table->cleanup = zebra_stable_node_cleanup;
+ zvrf->stable[afi][safi] = table;
+ }
- zvrf->rnh_table[AFI_IP] = route_table_init();
- zvrf->rnh_table[AFI_IP6] = route_table_init();
+ table = route_table_init();
+ table->cleanup = zebra_rnhtable_node_cleanup;
+ zvrf->rnh_table[afi] = table;
- zvrf->import_check_table[AFI_IP] = route_table_init();
- zvrf->import_check_table[AFI_IP6] = route_table_init();
+ table = route_table_init();
+ table->cleanup = zebra_rnhtable_node_cleanup;
+ zvrf->import_check_table[afi] = table;
+ }
zebra_mpls_init_tables (zvrf);
{
if (zvrf->other_table[afi][table_id] == NULL)
{
- table = route_table_init();
+ table = (afi == AFI_IP6) ? srcdest_table_init() : route_table_init();
info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info));
info->zvrf = zvrf;
info->afi = afi;
return zvrf->table[afi][SAFI_UNICAST];
}
-/* Wrapper hook point for zebra daemon so that ifindex can be set
- * DEFUN macro not used as extract.pl HAS to ignore this
- * See also interface_cmd in lib/if.c
- */
-DEFUN_NOSH (zebra_vrf,
- zebra_vrf_cmd,
- "vrf NAME",
- "Select a VRF to configure\n"
- "VRF's name\n")
-{
- // VTY_DECLVAR_CONTEXT (vrf, vrfp);
- int ret;
-
- /* Call lib vrf() */
- if ((ret = vrf_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS)
- return ret;
-
- return ret;
-}
-
static int
vrf_config_write (struct vty *vty)
{
return 0;
}
-struct cmd_node vrf_node =
-{
- VRF_NODE,
- "%s(config-vrf)# ",
- 1
-};
-
/* Zebra VRF initialization. */
void
zebra_vrf_init (void)
{
- vrf_add_hook (VRF_NEW_HOOK, zebra_vrf_new);
- vrf_add_hook (VRF_ENABLE_HOOK, zebra_vrf_enable);
- vrf_add_hook (VRF_DISABLE_HOOK, zebra_vrf_disable);
- vrf_add_hook (VRF_DELETE_HOOK, zebra_vrf_delete);
-
- vrf_init ();
+ vrf_init (zebra_vrf_new,
+ zebra_vrf_enable,
+ zebra_vrf_disable,
+ zebra_vrf_delete);
- install_node (&vrf_node, vrf_config_write);
- install_default (VRF_NODE);
- install_element (CONFIG_NODE, &zebra_vrf_cmd);
- install_element (CONFIG_NODE, &no_vrf_cmd);
+ vrf_cmd_init (vrf_config_write);
}