From b72ede27fd39c2e97dbf31715464573c30de557f Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:39:56 +0200 Subject: lib, zebra: move "struct vrf" to be a lib module Previously "struct vrf" is defined locally in zebra. Now it is moved to be a lib module. This is the first step to support multi-VRF in quagga. The implementation is splitted into small patches for the purpose of easy review. * lib: "struct vrf" with basic members is defined in vrf.c. The member "void *info" is for user data. Some basic functions are defined in vrf.c for adding/deleting/ looking up a VRF, scanning the VRF table and initializing the VRF module. The type "vrf_id_t" is defined specificly for VRF ID. * zebra: The previous "struct vrf" is re-defined as "struct zebra_vrf"; and previous "vrf" variables are renamed to "zvrf". The previous "struct vrf" related functions are removed from zbera_rib.c. New functions are defined to maintain the new "struct zebra_vrf". The names vrf_xxx are reserved for the functions in VRF module. So: - the previous vrf_table() are renamed to zebra_vrf_table(); - the previous vrf_static_table() are renamed to zebra_vrf_static_table(). The main logic is not changed. BTW: Add a statement to zebra_snmp.c telling that the SNMP is running only for the MIBs in the default VRF. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter Conflicts: lib/Makefile.am zebra/zebra_rib.c zebra/zebra_vty.c Conflicts: lib/Makefile.am lib/memtypes.c zebra/rib.h zebra/zebra_rib.c zebra/zebra_rnh.c zebra/zebra_rnh.h zebra/zebra_vty.c --- zebra/zebra_rib.c | 365 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 188 insertions(+), 177 deletions(-) (limited to 'zebra/zebra_rib.c') diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index a69dead1a6..b15cbd3cdb 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -35,6 +35,7 @@ #include "prefix.h" #include "routemap.h" #include "nexthop.h" +#include "vrf.h" #include "zebra/rib.h" #include "zebra/rt.h" @@ -79,136 +80,31 @@ static const struct }; /* Vector for routing table. */ -static vector vrf_vector; +static vector zebra_vrf_vector; /* - * vrf_table_create + * nexthop_type_to_str */ -static void -vrf_table_create (struct vrf *vrf, afi_t afi, safi_t safi) -{ - rib_table_info_t *info; - struct route_table *table; - - assert (!vrf->table[afi][safi]); - - table = route_table_init (); - vrf->table[afi][safi] = table; - - info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info)); - info->vrf = vrf; - info->afi = afi; - info->safi = safi; - table->info = info; -} - -/* Allocate new VRF. */ -static struct vrf * -vrf_alloc (const char *name) -{ - struct vrf *vrf; - - vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf)); - - /* Put name. */ - if (name) - vrf->name = XSTRDUP (MTYPE_VRF_NAME, name); - - /* Allocate routing table and static table. */ - vrf_table_create (vrf, AFI_IP, SAFI_UNICAST); - vrf_table_create (vrf, AFI_IP6, SAFI_UNICAST); - vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init (); - vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init (); - vrf_table_create (vrf, AFI_IP, SAFI_MULTICAST); - vrf_table_create (vrf, AFI_IP6, SAFI_MULTICAST); - vrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init (); - vrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init (); - - vrf->rnh_table[AFI_IP] = route_table_init(); - vrf->rnh_table[AFI_IP6] = route_table_init(); - - vrf->import_check_table[AFI_IP] = route_table_init(); - vrf->import_check_table[AFI_IP6] = route_table_init(); - - return vrf; -} - -/* Lookup VRF by identifier. */ -struct vrf * -vrf_lookup (u_int32_t id) -{ - return vector_lookup (vrf_vector, id); -} - -/* Initialize VRF. */ -static void -vrf_init (void) +const char * +nexthop_type_to_str (enum nexthop_types_t nh_type) { - struct vrf *default_table; - - /* Allocate VRF vector. */ - vrf_vector = vector_init (1); - - /* Allocate default main table. */ - default_table = vrf_alloc ("Default-IP-Routing-Table"); - - /* Default table index must be 0. */ - vector_set_index (vrf_vector, 0, default_table); -} - -/* Lookup route table. */ -struct route_table * -vrf_table (afi_t afi, safi_t safi, u_int32_t id) -{ - struct vrf *vrf; - - vrf = vrf_lookup (id); - if (! vrf) - return NULL; - - if( afi >= AFI_MAX || safi >= SAFI_MAX ) - return NULL; - - return vrf->table[afi][safi]; -} - -/* Lookup static route table. */ -struct route_table * -vrf_static_table (afi_t afi, safi_t safi, u_int32_t id) -{ - struct vrf *vrf; - - vrf = vrf_lookup (id); - if (! vrf) - return NULL; - - if( afi >= AFI_MAX || safi >= SAFI_MAX ) - return NULL; - - return vrf->stable[afi][safi]; -} - -struct route_table * -vrf_other_route_table (afi_t afi, u_int32_t table_id, u_int32_t vrf_id) -{ - struct vrf *vrf; - - vrf = vrf_lookup (vrf_id); - if (! vrf) - return NULL; - - if(afi >= AFI_MAX) - return NULL; - - if (table_id >= ZEBRA_KERNEL_TABLE_MAX) - return NULL; + static const char *desc[] = { + "none", + "Directly connected", + "Interface route", + "IPv4 nexthop", + "IPv4 nexthop with ifindex", + "IPv4 nexthop with ifname", + "IPv6 nexthop", + "IPv6 nexthop with ifindex", + "IPv6 nexthop with ifname", + "Null0 nexthop", + }; - if (vrf->other_table[afi][table_id] == NULL) - { - vrf->other_table[afi][table_id] = route_table_init(); - } + if (nh_type >= ZEBRA_NUM_OF (desc)) + return ""; - return (vrf->other_table[afi][table_id]); + return desc[nh_type]; } int @@ -587,7 +483,7 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, p.prefix = nexthop->gate.ipv4; /* Lookup table. */ - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return 0; @@ -796,7 +692,7 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, p.prefix = nexthop->gate.ipv6; /* Lookup table. */ - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! table) return 0; @@ -960,7 +856,7 @@ rib_match_ipv4 (struct in_addr addr) int recursing; /* Lookup table. */ - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return 0; @@ -1021,7 +917,7 @@ rib_lookup_ipv4 (struct prefix_ipv4 *p) int recursing; /* Lookup table. */ - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return 0; @@ -1078,7 +974,7 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate) int nexthops_active; /* Lookup table. */ - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return ZEBRA_RIB_LOOKUP_ERROR; @@ -1144,7 +1040,7 @@ rib_match_ipv6 (struct in6_addr *addr) int recursing; /* Lookup table. */ - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! table) return 0; @@ -2266,11 +2162,11 @@ rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = vrf_table (AFI_IP, safi, 0); + table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT); } else { - table = vrf_other_route_table (AFI_IP, table_id, 0); + table = zebra_vrf_other_route_table (AFI_IP, table_id, VRF_DEFAULT); } if (! table) return 0; @@ -2442,10 +2338,10 @@ void rib_lookup_and_dump (struct prefix_ipv4 * p) char prefix_buf[INET_ADDRSTRLEN]; /* Lookup table. */ - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) { - zlog_err ("%s: vrf_table() returned NULL", __func__); + zlog_err ("%s: zebra_vrf_table() returned NULL", __func__); return; } @@ -2491,9 +2387,9 @@ void rib_lookup_and_pushup (struct prefix_ipv4 * p) struct rib *rib; unsigned changed = 0; - if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0))) + if (NULL == (table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT))) { - zlog_err ("%s: vrf_table() returned NULL", __func__); + zlog_err ("%s: zebra_vrf_table() returned NULL", __func__); return; } @@ -2543,11 +2439,11 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) /* Lookup table. */ if ((rib->table == zebrad.rtm_table_default) || (rib->table == RT_TABLE_MAIN)) { - table = vrf_table (AFI_IP, safi, 0); + table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT); } else { - table = vrf_other_route_table (AFI_IP, rib->table, 0); + table = zebra_vrf_other_route_table (AFI_IP, rib->table, VRF_DEFAULT); } if (! table) return 0; @@ -2633,11 +2529,11 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = vrf_table (AFI_IP, safi, 0); + table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT); } else { - table = vrf_other_route_table(AFI_IP, table_id, 0); + table = zebra_vrf_other_route_table(AFI_IP, table_id, VRF_DEFAULT); } if (! table) return 0; @@ -2795,7 +2691,7 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si) struct prefix nh_p; /* Lookup table. */ - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return; @@ -2903,7 +2799,7 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si) struct prefix nh_p; /* Lookup table. */ - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return; @@ -2991,7 +2887,7 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, struct route_table *stable; /* Lookup table. */ - stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id); + stable = zebra_vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! stable) return -1; @@ -3084,7 +2980,7 @@ static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, struct route_table *stable; /* Lookup table. */ - stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id); + stable = zebra_vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! stable) return -1; @@ -3175,11 +3071,11 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = vrf_table (AFI_IP6, safi, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); } else { - table = vrf_other_route_table(AFI_IP6, table_id, 0); + table = zebra_vrf_other_route_table(AFI_IP6, table_id, VRF_DEFAULT); } if (! table) return 0; @@ -3295,7 +3191,7 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi, if (!rib) return 0; - table = vrf_table (AFI_IP, safi, 0); + table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT); if (!table) return 0; /* Make it sure prefixlen is applied to the prefix. */ @@ -3311,11 +3207,11 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = vrf_table (AFI_IP6, safi, 0); + table = zebra_vrf_table (AFI_IP6, safi, VRF_DEFAULT); } else { - table = vrf_other_route_table(AFI_IP6, table_id, 0); + table = zebra_vrf_other_route_table(AFI_IP6, table_id, VRF_DEFAULT); } if (! table) @@ -3416,11 +3312,11 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = vrf_table (AFI_IP6, safi, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); } else { - table = vrf_other_route_table(AFI_IP6, table_id, 0); + table = zebra_vrf_other_route_table(AFI_IP6, table_id, VRF_DEFAULT); } if (! table) return 0; @@ -3561,7 +3457,7 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si) struct prefix nh_p; /* Lookup table. */ - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! table) return; @@ -3671,7 +3567,7 @@ static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si) struct prefix nh_p; /* Lookup table. */ - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! table) return; @@ -3757,7 +3653,7 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, struct route_table *stable; /* Lookup table. */ - stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id); + stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! stable) return -1; @@ -3845,7 +3741,7 @@ static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, struct route_table *stable; /* Lookup table. */ - stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id); + stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! stable) return -1; @@ -3898,7 +3794,7 @@ rib_update_static (void) struct route_table *table; struct rib *rib, *next; - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB_SAFE (rn, rib, next) @@ -3908,7 +3804,7 @@ rib_update_static (void) break; } - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB_SAFE (rn, rib, next) @@ -3926,13 +3822,13 @@ rib_update (void) struct route_node *rn; struct route_table *table; - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) if (rnode_to_ribs (rn)) rib_queue_add (&zebrad, rn); - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) if (rnode_to_ribs (rn)) @@ -3965,8 +3861,8 @@ rib_weed_table (struct route_table *table) void rib_weed_tables (void) { - rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0)); - rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0)); + rib_weed_table (zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)); + rib_weed_table (zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT)); } /* Delete self installed routes after zebra is relaunched. */ @@ -3999,8 +3895,8 @@ rib_sweep_table (struct route_table *table) void rib_sweep_route (void) { - rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0)); - rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0)); + rib_sweep_table (zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)); + rib_sweep_table (zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT)); } /* Remove specific by protocol routes from 'table'. */ @@ -4032,8 +3928,8 @@ rib_score_proto_table (u_char proto, u_short instance, struct route_table *table unsigned long rib_score_proto (u_char proto, u_short instance) { - return rib_score_proto_table (proto, instance, vrf_table (AFI_IP, SAFI_UNICAST, 0)) - +rib_score_proto_table (proto, instance, vrf_table (AFI_IP6, SAFI_UNICAST, 0)); + return rib_score_proto_table (proto, instance, zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)) + +rib_score_proto_table (proto, instance, zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT)); } /* Close RIB and clean up kernel routes. */ @@ -4064,8 +3960,8 @@ rib_close (void) struct listnode *node, *nnode; struct interface *ifp; - rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0)); - rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0)); + rib_close_table (zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)); + rib_close_table (zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT)); for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp)) if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp); @@ -4076,8 +3972,6 @@ void rib_init (void) { rib_queue_init (&zebrad); - /* VRF initialization. */ - vrf_init (); } /* @@ -4088,15 +3982,19 @@ rib_init (void) * Returns TRUE if a vrf id was found, FALSE otherwise. */ static inline int -vrf_id_get_next (uint32_t id, uint32_t *next_id_p) +vrf_id_get_next (vrf_id_t vrf_id, vrf_id_t *next_id_p) { - while (++id < vector_active (vrf_vector)) + vrf_iter_t iter = vrf_iterator (vrf_id); + struct zebra_vrf *zvrf = vrf_iter2info (iter); + + /* The same one ? Then find out the next. */ + if (zvrf && (zvrf->vrf_id == vrf_id)) + zvrf = vrf_iter2info (vrf_next (iter)); + + if (zvrf) { - if (vrf_lookup (id)) - { - *next_id_p = id; - return 1; - } + *next_id_p = zvrf->vrf_id; + return 1; } return 0; @@ -4144,7 +4042,7 @@ rib_tables_iter_next (rib_tables_iter_t *iter) while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis)) { - table = vrf_table (afi_safis[iter->afi_safi_ix].afi, + table = zebra_vrf_table (afi_safis[iter->afi_safi_ix].afi, afi_safis[iter->afi_safi_ix].safi, iter->vrf_id); if (table) @@ -4182,3 +4080,116 @@ rib_tables_iter_next (rib_tables_iter_t *iter) return table; } + +/* + * Create a routing table for the specific AFI/SAFI in the given VRF. + */ +static void +zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi) +{ + rib_table_info_t *info; + struct route_table *table; + + assert (!zvrf->table[afi][safi]); + + table = route_table_init (); + zvrf->table[afi][safi] = table; + + info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info)); + info->zvrf = zvrf; + info->afi = afi; + info->safi = safi; + table->info = info; +} + +/* Allocate new zebra VRF. */ +struct zebra_vrf * +zebra_vrf_alloc (vrf_id_t vrf_id) +{ + struct zebra_vrf *zvrf; + + 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 (); + + zvrf->rnh_table[AFI_IP] = route_table_init(); + zvrf->rnh_table[AFI_IP6] = route_table_init(); + + zvrf->import_check_table[AFI_IP] = route_table_init(); + zvrf->import_check_table[AFI_IP6] = route_table_init(); + + /* Set VRF ID */ + zvrf->vrf_id = vrf_id; + + return zvrf; +} + +/* Lookup VRF by identifier. */ +struct zebra_vrf * +zebra_vrf_lookup (vrf_id_t vrf_id) +{ + return vector_lookup (zebra_vrf_vector, vrf_id); +} + +/* Lookup the routing table in an enabled VRF. */ +struct route_table * +zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id) +{ + struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id); + + if (!zvrf) + return NULL; + + if (afi >= AFI_MAX || safi >= SAFI_MAX) + return NULL; + + return zvrf->table[afi][safi]; +} + +/* Lookup the static routing table in a VRF. */ +struct route_table * +zebra_vrf_static_table (afi_t afi, safi_t safi, vrf_id_t vrf_id) +{ + struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id); + + if (!zvrf) + return NULL; + + if (afi >= AFI_MAX || safi >= SAFI_MAX) + return NULL; + + return zvrf->stable[afi][safi]; +} + +struct route_table * +zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, vrf_id_t vrf_id) +{ + struct zebra_vrf *zvrf; + + zvrf = vrf_info_lookup (vrf_id); + if (! zvrf) + return NULL; + + if(afi >= AFI_MAX) + return NULL; + + if (table_id >= ZEBRA_KERNEL_TABLE_MAX) + return NULL; + + if (zvrf->other_table[afi][table_id] == NULL) + { + zvrf->other_table[afi][table_id] = route_table_init(); + } + + return (zvrf->other_table[afi][table_id]); +} + + -- cgit v1.2.3 From 78104b9bad14a3185178cedc0dd41d1b1c5db493 Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:40:02 +0200 Subject: zebra: let FIB stand for its respective VRF A new member "vrf_id" is added to "struct rib", reflecting the VRF which it belongs to. A new parameter "vrf_id" is added to the relative functions where need, except those: - which already have the parameter "vrf_id"; or - which have a parameter in type of "struct rib"; or - which have a parameter in type of "struct interface". All incoming routes are set to default VRF. In fact, all routes in FIB are kept in default VRF. And the logic is not changed. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN [DL: conflicts fixed + compile warning fix] Signed-off-by: David Lamparter Conflicts: zebra/connected.c zebra/kernel_socket.c zebra/rib.h zebra/rt_netlink.c zebra/zebra_rib.c zebra/zserv.c Conflicts: zebra/connected.c zebra/interface.c zebra/kernel_socket.c zebra/rib.h zebra/rt_netlink.c zebra/rtread_getmsg.c zebra/zebra_rib.c zebra/zebra_vty.c zebra/zserv.c --- lib/prefix.c | 7 +- lib/prefix.h | 2 +- zebra/connected.c | 29 ++++---- zebra/interface.c | 4 +- zebra/kernel_socket.c | 17 +++-- zebra/rib.h | 37 ++++++---- zebra/rt_netlink.c | 20 +++-- zebra/rtread_getmsg.c | 3 +- zebra/zebra_rib.c | 199 ++++++++++++++++++++++++++++---------------------- zebra/zebra_vty.c | 16 ++-- zebra/zserv.c | 19 +++-- 11 files changed, 202 insertions(+), 151 deletions(-) (limited to 'zebra/zebra_rib.c') diff --git a/lib/prefix.c b/lib/prefix.c index 739764842d..43331d1552 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -766,14 +766,15 @@ str2prefix (const char *str, struct prefix *p) return 0; } -int -prefix2str (const struct prefix *p, char *str, int size) +const char * +prefix2str (union prefix46constptr pu, char *str, int size) { + const struct prefix *p = pu.p; char buf[BUFSIZ]; inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ); snprintf (str, size, "%s/%d", buf, p->prefixlen); - return 0; + return str; } struct prefix * diff --git a/lib/prefix.h b/lib/prefix.h index cc4bbe280d..7fef37e3ff 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -179,7 +179,7 @@ extern void prefix_free (struct prefix *); extern const char *prefix_family_str (const struct prefix *); extern int prefix_blen (const struct prefix *); extern int str2prefix (const char *, struct prefix *); -extern int prefix2str (const struct prefix *, char *, int); +extern const char *prefix2str (union prefix46constptr, char *, int); extern int prefix_match (const struct prefix *, const struct prefix *); extern int prefix_same (const struct prefix *, const struct prefix *); extern int prefix_cmp (const struct prefix *, const struct prefix *); diff --git a/zebra/connected.c b/zebra/connected.c index 2ec6911d77..0d2407a3e0 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -209,15 +209,15 @@ connected_up_ipv4 (struct interface *ifp, struct connected *ifc) return; rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex, - RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST); + ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST); rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex, - RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST); + ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST); if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update", __func__); - rib_update (); + rib_update (ifp->vrf_id); } /* Add connected IPv4 route to the interface. */ @@ -327,14 +327,16 @@ connected_down_ipv4 (struct interface *ifp, struct connected *ifc) return; /* Same logic as for connected_up_ipv4(): push the changes into the head. */ - rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST); + rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, 0, + SAFI_UNICAST); - rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, 0, SAFI_MULTICAST); + rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, 0, + SAFI_MULTICAST); if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update_static", __func__); - rib_update_static (); + rib_update_static (ifp->vrf_id); } void @@ -397,7 +399,7 @@ connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update_static", __func__); - rib_update_static(); + rib_update_static(ifp->vrf_id); } #ifdef HAVE_IPV6 @@ -420,13 +422,13 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc) return; #endif - rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, RT_TABLE_MAIN, - ifp->metric, 0, SAFI_UNICAST); + rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, + RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST); if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update", __func__); - rib_update (); + rib_update (ifp->vrf_id); } /* Add connected IPv6 route to the interface. */ @@ -509,12 +511,13 @@ connected_down_ipv6 (struct interface *ifp, struct connected *ifc) if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix)) return; - rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST); + rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, + ifp->vrf_id, 0, SAFI_UNICAST); if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update_static", __func__); - rib_update_static (); + rib_update_static (ifp->vrf_id); } void @@ -538,6 +541,6 @@ connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address, if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update_static", __func__); - rib_update_static(); + rib_update_static(ifp->vrf_id); } #endif /* HAVE_IPV6 */ diff --git a/zebra/interface.c b/zebra/interface.c index 2ae2b0bf51..a3d297d327 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -644,7 +644,7 @@ if_up (struct interface *ifp) ifp->name); /* Examine all static routes. */ - rib_update (); + rib_update (ifp->vrf_id); } /* Interface goes down. We have to manage different behavior of based @@ -681,7 +681,7 @@ if_down (struct interface *ifp) zlog_debug ("%s: calling rib_update_static on interface %s down", __func__, ifp->name); - rib_update_static (); + rib_update_static (ifp->vrf_id); if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp); diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 03f3eaeb6a..a1002a4d86 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -32,6 +32,7 @@ #include "table.h" #include "rib.h" #include "privs.h" +#include "vrf.h" #include "zebra/interface.h" #include "zebra/zserv.h" @@ -870,8 +871,8 @@ rtm_read (struct rt_msghdr *rtm) int ret; if (! IS_ZEBRA_DEBUG_RIB) return; - ret = rib_lookup_ipv4_route (&p, &gate); - inet_ntop (AF_INET, &p.prefix, buf, INET_ADDRSTRLEN); + ret = rib_lookup_ipv4_route (&p, &gate, VRF_DEFAULT); + prefix2str (&p, buf, sizeof(buf)); switch (rtm->rtm_type) { case RTM_ADD: @@ -935,16 +936,16 @@ rtm_read (struct rt_msghdr *rtm) */ if (rtm->rtm_type == RTM_CHANGE) rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, - NULL, 0, 0, SAFI_UNICAST); + NULL, 0, VRF_DEFAULT, SAFI_UNICAST); if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin.sin_addr, NULL, 0, 0, 0, 0, SAFI_UNICAST); + &p, &gate.sin.sin_addr, NULL, 0, VRF_DEFAULT, 0, 0, SAFI_UNICAST); else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0 zebra_flags, - &p, &gate.sin.sin_addr, 0, 0, SAFI_UNICAST); + &p, &gate.sin.sin_addr, 0, VRF_DEFAULT, SAFI_UNICAST); } #ifdef HAVE_IPV6 if (dest.sa.sa_family == AF_INET6) @@ -977,16 +978,16 @@ rtm_read (struct rt_msghdr *rtm) */ if (rtm->rtm_type == RTM_CHANGE) rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, - NULL, 0, 0, SAFI_UNICAST); + NULL, 0, VRF_DEFAULT, SAFI_UNICAST); if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin6.sin6_addr, ifindex, 0, 0, 0, SAFI_UNICAST); + &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, 0, 0, SAFI_UNICAST); else rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin6.sin6_addr, ifindex, 0, SAFI_UNICAST); + &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, SAFI_UNICAST); } #endif /* HAVE_IPV6 */ } diff --git a/zebra/rib.h b/zebra/rib.h index 8c82a7eec3..6908e9d816 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -52,6 +52,9 @@ struct rib /* Source protocol instance */ u_short instance; + /* VRF identifier. */ + vrf_id_t vrf_id; + /* Which routing table */ uint32_t table; @@ -367,7 +370,8 @@ extern void rib_lookup_and_pushup (struct prefix_ipv4 *); #define rib_dump(prefix ,rib) _rib_dump(__func__, prefix, rib) extern void _rib_dump (const char *, union prefix46constptr, const struct rib *); -extern int rib_lookup_ipv4_route (struct prefix_ipv4 *, union sockunion *); +extern int rib_lookup_ipv4_route (struct prefix_ipv4 *, union sockunion *, + vrf_id_t); #define ZEBRA_RIB_LOOKUP_ERROR -1 #define ZEBRA_RIB_FOUND_EXACT 0 #define ZEBRA_RIB_FOUND_NOGATE 1 @@ -401,21 +405,21 @@ extern int zebra_check_addr (struct prefix *p); * also implicitly withdraw equal prefix of same type. */ extern int rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, struct in_addr *gate, struct in_addr *src, - unsigned int ifindex, u_int32_t vrf_id, + unsigned int ifindex, vrf_id_t vrf_id, u_int32_t table_id, u_int32_t, u_char, safi_t); extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *, safi_t); extern int rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, struct in_addr *gate, unsigned int ifindex, - u_int32_t, safi_t safi); + vrf_id_t, u_int32_t, safi_t safi); -extern struct rib *rib_match_ipv4 (struct in_addr); +extern struct rib *rib_match_ipv4 (struct in_addr, vrf_id_t); -extern struct rib *rib_lookup_ipv4 (struct prefix_ipv4 *); +extern struct rib *rib_lookup_ipv4 (struct prefix_ipv4 *, vrf_id_t); -extern void rib_update (void); -extern void rib_update_static (void); +extern void rib_update (vrf_id_t); +extern void rib_update_static (vrf_id_t); extern void rib_weed_tables (void); extern void rib_sweep_route (void); extern void rib_close (void); @@ -427,32 +431,33 @@ extern void rib_queue_add (struct zebra_t *zebra, struct route_node *rn); extern int static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, - u_char flags, u_short tag, u_char distance, u_int32_t vrf_id); + u_char flags, u_short tag, u_char distance, vrf_id_t vrf_id); extern int static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, - u_short tag, u_char distance, u_int32_t vrf_id); + u_short tag, u_char distance, vrf_id_t vrf_id); #ifdef HAVE_IPV6 extern int rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, - u_int32_t metric, u_char distance, safi_t safi); + struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, + u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi); extern int rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi); + struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, + u_int32_t table_id, safi_t safi); -extern struct rib *rib_lookup_ipv6 (struct in6_addr *); +extern struct rib *rib_lookup_ipv6 (struct in6_addr *, vrf_id_t); -extern struct rib *rib_match_ipv6 (struct in6_addr *); +extern struct rib *rib_match_ipv6 (struct in6_addr *, vrf_id_t); extern struct route_table *rib_table_ipv6; extern int static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, const char *ifname, u_char flags, u_short tag, - u_char distance, u_int32_t vrf_id); + u_char distance, vrf_id_t vrf_id); extern int rib_add_ipv6_multipath (struct prefix *, struct rib *, safi_t, @@ -461,7 +466,7 @@ rib_add_ipv6_multipath (struct prefix *, struct rib *, safi_t, extern int static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, const char *ifname, u_short tag, u_char distance, - u_int32_t vrf_id); + vrf_id_t vrf_id); #endif /* HAVE_IPV6 */ diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 4c16df61a1..e312801e55 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -37,6 +37,7 @@ #include "thread.h" #include "privs.h" #include "nexthop.h" +#include "vrf.h" #include "zebra/zserv.h" #include "zebra/rt.h" @@ -755,7 +756,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) if (!tb[RTA_MULTIPATH]) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, src, index, - table, metric, 0, SAFI_UNICAST); + VRF_DEFAULT, table, metric, 0, SAFI_UNICAST); else { /* This is a multipath route */ @@ -771,6 +772,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) rib->distance = 0; rib->flags = flags; rib->metric = metric; + rib->vrf_id = VRF_DEFAULT; rib->table = table; rib->nexthop_num = 0; rib->uptime = time (NULL); @@ -821,8 +823,8 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) memcpy (&p.prefix, dest, 16); p.prefixlen = rtm->rtm_dst_len; - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, index, table, - metric, 0, SAFI_UNICAST); + rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, index, VRF_DEFAULT, + table, metric, 0, SAFI_UNICAST); } #endif /* HAVE_IPV6 */ @@ -958,8 +960,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (h->nlmsg_type == RTM_NEWROUTE) { if (!tb[RTA_MULTIPATH]) - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, src, index, table, - metric, 0, SAFI_UNICAST); + rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, src, index, VRF_DEFAULT, + table, metric, 0, SAFI_UNICAST); else { /* This is a multipath route */ @@ -975,6 +977,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) rib->distance = 0; rib->flags = 0; rib->metric = metric; + rib->vrf_id = VRF_DEFAULT; rib->table = table; rib->nexthop_num = 0; rib->uptime = time (NULL); @@ -1020,7 +1023,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) } else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, - table, SAFI_UNICAST); + VRF_DEFAULT, table, SAFI_UNICAST); } #ifdef HAVE_IPV6 @@ -1046,10 +1049,11 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) } if (h->nlmsg_type == RTM_NEWROUTE) - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, index, table, metric, 0, SAFI_UNICAST); + rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, index, VRF_DEFAULT, + table, metric, 0, SAFI_UNICAST); else rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, - table, SAFI_UNICAST); + VRF_DEFAULT, table, SAFI_UNICAST); } #endif /* HAVE_IPV6 */ diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index 17d75b283a..f9bfb338a0 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -25,6 +25,7 @@ #include "prefix.h" #include "log.h" #include "if.h" +#include "vrf.h" #include "zebra/rib.h" #include "zebra/zserv.h" @@ -90,7 +91,7 @@ handle_route_entry (mib2_ipRouteEntry_t *routeEntry) gateway.s_addr = routeEntry->ipRouteNextHop; rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &prefix, - &gateway, NULL, 0, 0, 0, 0, SAFI_UNICAST); + &gateway, NULL, 0, VRF_DEFAULT, 0, 0, 0, SAFI_UNICAST); } void diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index b15cbd3cdb..79aa989814 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -483,7 +483,7 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, p.prefix = nexthop->gate.ipv4; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, rib->vrf_id); if (! table) return 0; @@ -692,7 +692,7 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, p.prefix = nexthop->gate.ipv6; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, rib->vrf_id); if (! table) return 0; @@ -846,7 +846,7 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, #endif /* HAVE_IPV6 */ struct rib * -rib_match_ipv4 (struct in_addr addr) +rib_match_ipv4 (struct in_addr addr, vrf_id_t vrf_id) { struct prefix_ipv4 p; struct route_table *table; @@ -856,7 +856,7 @@ rib_match_ipv4 (struct in_addr addr) int recursing; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) return 0; @@ -908,7 +908,7 @@ rib_match_ipv4 (struct in_addr addr) } struct rib * -rib_lookup_ipv4 (struct prefix_ipv4 *p) +rib_lookup_ipv4 (struct prefix_ipv4 *p, vrf_id_t vrf_id) { struct route_table *table; struct route_node *rn; @@ -917,7 +917,7 @@ rib_lookup_ipv4 (struct prefix_ipv4 *p) int recursing; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) return 0; @@ -964,7 +964,8 @@ rib_lookup_ipv4 (struct prefix_ipv4 *p) * 3: no matches found */ int -rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate) +rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate, + vrf_id_t vrf_id) { struct route_table *table; struct route_node *rn; @@ -974,7 +975,7 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate) int nexthops_active; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) return ZEBRA_RIB_LOOKUP_ERROR; @@ -1030,7 +1031,7 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate) #ifdef HAVE_IPV6 struct rib * -rib_match_ipv6 (struct in6_addr *addr) +rib_match_ipv6 (struct in6_addr *addr, vrf_id_t vrf_id) { struct prefix_ipv6 p; struct route_table *table; @@ -1040,7 +1041,7 @@ rib_match_ipv6 (struct in6_addr *addr) int recursing; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) return 0; @@ -1124,7 +1125,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, switch (nexthop->type) { case NEXTHOP_TYPE_IFINDEX: - ifp = if_lookup_by_index (nexthop->ifindex); + ifp = if_lookup_by_index_vrf (nexthop->ifindex, rib->vrf_id); if (ifp && if_is_operative(ifp)) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); else @@ -1133,7 +1134,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, case NEXTHOP_TYPE_IPV6_IFNAME: family = AFI_IP6; case NEXTHOP_TYPE_IFNAME: - ifp = if_lookup_by_name (nexthop->ifname); + ifp = if_lookup_by_name_vrf (nexthop->ifname, rib->vrf_id); if (ifp && if_is_operative(ifp)) { if (set) @@ -1169,7 +1170,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, family = AFI_IP6; if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6)) { - ifp = if_lookup_by_index (nexthop->ifindex); + ifp = if_lookup_by_index_vrf (nexthop->ifindex, rib->vrf_id); if (ifp && if_is_operative(ifp)) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); else @@ -2150,7 +2151,7 @@ rib_delnode (struct route_node *rn, struct rib *rib) int rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, struct in_addr *gate, struct in_addr *src, - unsigned int ifindex, u_int32_t table_id, + unsigned int ifindex, vrf_id_t vrf_id, u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi) { struct rib *rib; @@ -2162,11 +2163,11 @@ rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, safi, vrf_id); } else { - table = zebra_vrf_other_route_table (AFI_IP, table_id, VRF_DEFAULT); + table = zebra_vrf_other_route_table (AFI_IP, table_id, vrf_id); } if (! table) return 0; @@ -2226,6 +2227,7 @@ rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, rib->flags = flags; rib->metric = metric; rib->table = table_id; + rib->vrf_id = vrf_id; rib->nexthop_num = 0; rib->uptime = time (NULL); @@ -2279,8 +2281,8 @@ void _rib_dump (const char * func, struct nexthop *nexthop, *tnexthop; int recursing; - inet_ntop (p->family, &p->u.prefix, straddr, INET6_ADDRSTRLEN); - zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr, p->prefixlen); + zlog_debug ("%s: dumping RIB entry %p for %s vrf %u", func, rib, + prefix2str(pp, straddr, sizeof(straddr)), rib->vrf_id); zlog_debug ( "%s: refcnt == %lu, uptime == %lu, type == %u, instance == %d, table == %d", @@ -2439,11 +2441,11 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) /* Lookup table. */ if ((rib->table == zebrad.rtm_table_default) || (rib->table == RT_TABLE_MAIN)) { - table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, safi, rib->vrf_id); } else { - table = zebra_vrf_other_route_table (AFI_IP, rib->table, VRF_DEFAULT); + table = zebra_vrf_other_route_table (AFI_IP, rib->table, rib->vrf_id); } if (! table) return 0; @@ -2513,7 +2515,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) /* XXX factor with rib_delete_ipv6 */ int rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, - struct in_addr *gate, unsigned int ifindex, + struct in_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, u_int32_t table_id, safi_t safi) { struct route_table *table; @@ -2529,11 +2531,11 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, safi, vrf_id); } else { - table = zebra_vrf_other_route_table(AFI_IP, table_id, VRF_DEFAULT); + table = zebra_vrf_other_route_table(AFI_IP, table_id, vrf_id); } if (! table) return 0; @@ -2544,15 +2546,13 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, if (IS_ZEBRA_DEBUG_KERNEL) { if (gate) - zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d", - inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u via %s ifindex %d", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, inet_ntoa (*gate), ifindex); else - zlog_debug ("rib_delete_ipv4(): route delete %s/%d ifindex %d", - inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u ifindex %d", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, ifindex); } @@ -2563,15 +2563,13 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, if (IS_ZEBRA_DEBUG_KERNEL) { if (gate) - zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib", - inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN), ifindex); else - zlog_debug ("route %s/%d ifindex %d doesn't exist in rib", - inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, ifindex); } return ZEBRA_ERR_RTNOEXIST; @@ -2656,16 +2654,15 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, if (IS_ZEBRA_DEBUG_KERNEL) { if (gate) - zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib", - inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("route %s vrf %u via %s ifindex %d type %d " + "doesn't exist in rib", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN), ifindex, type); else - zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib", - inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, ifindex, type); } @@ -2742,6 +2739,7 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si) rib->instance = 0; rib->distance = si->distance; rib->metric = 0; + rib->vrf_id = VRF_DEFAULT; rib->table = zebrad.rtm_table_default; rib->nexthop_num = 0; rib->tag = si->tag; @@ -2876,7 +2874,7 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si) /* Add static route into static route configuration. */ int static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, - u_char flags, u_short tag, u_char distance, u_int32_t vrf_id) + u_char flags, u_short tag, u_char distance, vrf_id_t vrf_id) { u_char type = 0; struct route_node *rn; @@ -2884,10 +2882,9 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, struct static_ipv4 *pp; struct static_ipv4 *cp; struct static_ipv4 *update = NULL; - struct route_table *stable; + struct zebra_vrf *zvrf = vrf_info_get (vrf_id); + struct route_table *stable = zvrf->stable[AFI_IP][SAFI_UNICAST]; - /* Lookup table. */ - stable = zebra_vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! stable) return -1; @@ -2972,7 +2969,7 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, /* Delete static route from static route configuration. */ int static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, - u_short tag, u_char distance, u_int32_t vrf_id) + u_short tag, u_char distance, vrf_id_t vrf_id) { u_char type = 0; struct route_node *rn; @@ -3059,8 +3056,8 @@ rib_bogus_ipv6 (int type, struct prefix_ipv6 *p, int rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, unsigned int ifindex, u_int32_t table_id, - u_int32_t metric, u_char distance, safi_t safi) + struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, + u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi) { struct rib *rib; struct rib *same = NULL; @@ -3071,11 +3068,11 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, safi, vrf_id); } else { - table = zebra_vrf_other_route_table(AFI_IP6, table_id, VRF_DEFAULT); + table = zebra_vrf_other_route_table(AFI_IP6, table_id, vrf_id); } if (! table) return 0; @@ -3131,6 +3128,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, rib->flags = flags; rib->metric = metric; rib->table = table_id; + rib->vrf_id = vrf_id; rib->nexthop_num = 0; rib->uptime = time (NULL); @@ -3294,7 +3292,8 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi, /* XXX factor with rib_delete_ipv6 */ int rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, unsigned int ifindex, u_int32_t table_id, safi_t safi) + struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, + u_int32_t table_id, safi_t safi) { struct route_table *table; struct route_node *rn; @@ -3312,7 +3311,7 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, safi, vrf_id); } else { @@ -3328,15 +3327,13 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, if (IS_ZEBRA_DEBUG_KERNEL) { if (gate) - zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib", - inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN), ifindex); else - zlog_debug ("route %s/%d ifindex %d doesn't exist in rib", - inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, ifindex); } return ZEBRA_ERR_RTNOEXIST; @@ -3422,16 +3419,15 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, if (IS_ZEBRA_DEBUG_KERNEL) { if (gate) - zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib", - inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("route %s vrf %u via %s ifindex %d type %d " + "doesn't exist in rib", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN), ifindex, type); else - zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib", - inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, ifindex, type); } @@ -3509,6 +3505,7 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si) rib->instance = 0; rib->distance = si->distance; rib->metric = 0; + rib->vrf_id = VRF_DEFAULT; rib->table = zebrad.rtm_table_default; rib->nexthop_num = 0; rib->tag = si->tag; @@ -3644,16 +3641,15 @@ static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si) int static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, const char *ifname, u_char flags, u_short tag, - u_char distance, u_int32_t vrf_id) + u_char distance, vrf_id_t vrf_id) { struct route_node *rn; struct static_ipv6 *si; struct static_ipv6 *pp; struct static_ipv6 *cp; - struct route_table *stable; + struct zebra_vrf *zvrf = vrf_info_get (vrf_id); + struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST]; - /* Lookup table. */ - stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! stable) return -1; @@ -3734,7 +3730,7 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, int static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, const char *ifname, u_short tag, u_char distance, - u_int32_t vrf_id) + vrf_id_t vrf_id) { struct route_node *rn; struct static_ipv6 *si; @@ -3788,13 +3784,13 @@ static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, /* RIB update function. */ void -rib_update_static (void) +rib_update_static (vrf_id_t vrf_id) { struct route_node *rn; struct route_table *table; struct rib *rib, *next; - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB_SAFE (rn, rib, next) @@ -3804,7 +3800,7 @@ rib_update_static (void) break; } - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB_SAFE (rn, rib, next) @@ -3817,18 +3813,18 @@ rib_update_static (void) /* RIB update function. */ void -rib_update (void) +rib_update (vrf_id_t vrf_id) { struct route_node *rn; struct route_table *table; - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) if (rnode_to_ribs (rn)) rib_queue_add (&zebrad, rn); - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) if (rnode_to_ribs (rn)) @@ -3861,8 +3857,15 @@ rib_weed_table (struct route_table *table) void rib_weed_tables (void) { - rib_weed_table (zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)); - rib_weed_table (zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT)); + vrf_iter_t iter; + struct zebra_vrf *zvrf; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + if ((zvrf = vrf_iter2info (iter)) != NULL) + { + rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]); + rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); + } } /* Delete self installed routes after zebra is relaunched. */ @@ -3895,8 +3898,15 @@ rib_sweep_table (struct route_table *table) void rib_sweep_route (void) { - rib_sweep_table (zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)); - rib_sweep_table (zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT)); + vrf_iter_t iter; + struct zebra_vrf *zvrf; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + if ((zvrf = vrf_iter2info (iter)) != NULL) + { + rib_sweep_table (zvrf->table[AFI_IP][SAFI_UNICAST]); + rib_sweep_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); + } } /* Remove specific by protocol routes from 'table'. */ @@ -3928,8 +3938,16 @@ rib_score_proto_table (u_char proto, u_short instance, struct route_table *table unsigned long rib_score_proto (u_char proto, u_short instance) { - return rib_score_proto_table (proto, instance, zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)) - +rib_score_proto_table (proto, instance, zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT)); + vrf_iter_t iter; + struct zebra_vrf *zvrf; + unsigned long cnt = 0; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + if ((zvrf = vrf_iter2info (iter)) != NULL) + cnt += rib_score_proto_table (proto, instance, zvrf->table[AFI_IP][SAFI_UNICAST]) + +rib_score_proto_table (proto, instance, zvrf->table[AFI_IP6][SAFI_UNICAST]); + + return cnt; } /* Close RIB and clean up kernel routes. */ @@ -3957,14 +3975,21 @@ rib_close_table (struct route_table *table) void rib_close (void) { - struct listnode *node, *nnode; + vrf_iter_t iter; + struct zebra_vrf *zvrf; + struct listnode *node; struct interface *ifp; - rib_close_table (zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)); - rib_close_table (zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT)); - - for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp)) - if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp); + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) != NULL) + { + rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]); + rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); + } + for (ALL_LIST_ELEMENTS_RO (vrf_iter2iflist (iter), node, ifp)) + if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp); + } } /* Routing information base initialize. */ diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 9728a28c0e..1a50ab6990 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -961,7 +961,8 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn) case NEXTHOP_TYPE_IPV4_IFINDEX: vty_out (vty, " %s", inet_ntoa (nexthop->gate.ipv4)); if (nexthop->ifindex) - vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex)); + vty_out (vty, ", via %s", + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); break; #ifdef HAVE_IPV6 case NEXTHOP_TYPE_IPV6: @@ -972,12 +973,13 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn) if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME) vty_out (vty, ", %s", nexthop->ifname); else if (nexthop->ifindex) - vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex)); + vty_out (vty, ", via %s", + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); break; #endif /* HAVE_IPV6 */ case NEXTHOP_TYPE_IFINDEX: vty_out (vty, " directly connected, %s", - ifindex2ifname (nexthop->ifindex)); + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); break; case NEXTHOP_TYPE_IFNAME: vty_out (vty, " directly connected, %s", nexthop->ifname); @@ -1073,7 +1075,8 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib) case NEXTHOP_TYPE_IPV4_IFINDEX: vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4)); if (nexthop->ifindex) - vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex)); + vty_out (vty, ", %s", + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); break; #ifdef HAVE_IPV6 case NEXTHOP_TYPE_IPV6: @@ -1084,13 +1087,14 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib) if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME) vty_out (vty, ", %s", nexthop->ifname); else if (nexthop->ifindex) - vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex)); + vty_out (vty, ", %s", + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); break; #endif /* HAVE_IPV6 */ case NEXTHOP_TYPE_IFINDEX: vty_out (vty, " is directly connected, %s", - ifindex2ifname (nexthop->ifindex)); + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); break; case NEXTHOP_TYPE_IFNAME: vty_out (vty, " is directly connected, %s", nexthop->ifname); diff --git a/zebra/zserv.c b/zebra/zserv.c index ba3c59aafb..052c797f8b 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -37,6 +37,7 @@ #include "network.h" #include "buffer.h" #include "nexthop.h" +#include "vrf.h" #include "zebra/zserv.h" #include "zebra/router-id.h" @@ -643,7 +644,7 @@ zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr) struct nexthop *nexthop; /* Lookup nexthop. */ - rib = rib_match_ipv6 (addr); + rib = rib_match_ipv6 (addr, VRF_DEFAULT); /* Get output stream. */ s = client->obuf; @@ -710,7 +711,7 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr) struct nexthop *nexthop; /* Lookup nexthop. */ - rib = rib_match_ipv4 (addr); + rib = rib_match_ipv4 (addr, VRF_DEFAULT); /* Get output stream. */ s = client->obuf; @@ -892,7 +893,7 @@ zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p) struct nexthop *nexthop; /* Lookup nexthop. */ - rib = rib_lookup_ipv4 (p); + rib = rib_lookup_ipv4 (p, VRF_DEFAULT); /* Get output stream. */ s = client->obuf; @@ -1076,6 +1077,9 @@ zread_ipv4_add (struct zserv *client, u_short length) p.prefixlen = stream_getc (s); stream_get (&p.prefix, s, PSIZE (p.prefixlen)); + /* VRF ID */ + rib->vrf_id = VRF_DEFAULT; + /* Nexthop parse. */ if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP)) { @@ -1231,7 +1235,7 @@ zread_ipv4_delete (struct zserv *client, u_short length) api.tag = 0; rib_delete_ipv4 (api.type, api.instance, api.flags, &p, nexthop_p, ifindex, - client->rtm_table, api.safi); + VRF_DEFAULT, client->rtm_table, api.safi); client->v4_route_del_cnt++; return 0; } @@ -1505,6 +1509,7 @@ zread_ipv6_add (struct zserv *client, u_short length) /* Table */ rib->table=zebrad.rtm_table_default; + rib->vrf_id = VRF_DEFAULT; ret = rib_add_ipv6_multipath ((struct prefix *)&p, rib, safi, ifindex); /* Stats */ if (ret > 0) @@ -1584,9 +1589,11 @@ zread_ipv6_delete (struct zserv *client, u_short length) api.tag = 0; if (IN6_IS_ADDR_UNSPECIFIED (&nexthop)) - rib_delete_ipv6 (api.type, api.instance, api.flags, &p, NULL, ifindex, client->rtm_table, api.safi); + rib_delete_ipv6 (api.type, api.instance, api.flags, &p, NULL, ifindex, + VRF_DEFAULT, client->rtm_table, api.safi); else - rib_delete_ipv6 (api.type, api.instance, api.flags, &p, &nexthop, ifindex, client->rtm_table, api.safi); + rib_delete_ipv6 (api.type, api.instance, api.flags, &p, &nexthop, ifindex, + VRF_DEFAULT, client->rtm_table, api.safi); client->v6_route_del_cnt++; return 0; -- cgit v1.2.3 From 0032dd59cda8215e7ccf4297cd78ee6100de7499 Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:40:04 +0200 Subject: zebra: let the route-map rule "match interface" work for VRFs Introduce a new "struct nexthop_vrfid" to specify a nexthop together with the VRF ID it belongs to. Thus in route_match_interface(), we can lookup the interface from the correct VRF. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter Conflicts: zebra/zebra_rib.c zebra/zebra_routemap.c --- zebra/zebra_rib.c | 3 ++- zebra/zebra_routemap.c | 22 +++++++++++++--------- zebra/zserv.h | 1 + 3 files changed, 16 insertions(+), 10 deletions(-) (limited to 'zebra/zebra_rib.c') diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 79aa989814..0f25c76858 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1213,7 +1213,8 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr)); /* It'll get set if required inside */ - ret = zebra_route_map_check(family, rib->type, &rn->p, nexthop, rib->tag); + ret = zebra_route_map_check(family, rib->type, &rn->p, nexthop, rib->vrf_id, + rib->tag); if (ret == RMAP_DENYMATCH) { if (IS_ZEBRA_DEBUG_RIB) diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 1c7b63e757..a8e87dd09c 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -29,6 +29,7 @@ #include "filter.h" #include "plist.h" #include "nexthop.h" +#include "vrf.h" #include "zebra/zserv.h" #include "zebra/debug.h" @@ -45,6 +46,7 @@ extern struct zebra_t zebrad; struct nh_rmap_obj { struct nexthop *nexthop; + vrf_id_t vrf_id; u_int32_t source_protocol; int metric; u_short tag; @@ -255,12 +257,12 @@ route_match_interface (void *rule, struct prefix *prefix, { if (strcasecmp(ifname, "any") == 0) return RMAP_MATCH; - ifindex = ifname2ifindex(ifname); - if (ifindex == 0) - return RMAP_NOMATCH; nh_data = object; if (!nh_data || !nh_data->nexthop) return RMAP_NOMATCH; + ifindex = ifname2ifindex_vrf (ifname, nh_data->vrf_id); + if (ifindex == 0) + return RMAP_NOMATCH; if (nh_data->nexthop->ifindex == ifindex) return RMAP_MATCH; } @@ -767,7 +769,7 @@ DEFUN (ip_protocol, if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update", __func__); - rib_update(); + rib_update(VRF_DEFAULT); return CMD_SUCCESS; } @@ -804,7 +806,7 @@ DEFUN (no_ip_protocol, if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update", __func__); - rib_update(); + rib_update(VRF_DEFAULT); } return CMD_SUCCESS; } @@ -879,7 +881,7 @@ DEFUN (ipv6_protocol, if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update", __func__); - rib_update(); + rib_update(VRF_DEFAULT); return CMD_SUCCESS; } @@ -916,7 +918,7 @@ DEFUN (no_ipv6_protocol, if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update", __func__); - rib_update(); + rib_update(VRF_DEFAULT); } return CMD_SUCCESS; } @@ -1590,7 +1592,7 @@ zebra_route_map_update_timer (struct thread *thread) if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update", __func__); - rib_update(); + rib_update(VRF_DEFAULT); zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); @@ -1621,13 +1623,14 @@ zebra_route_map_write_delay_timer (struct vty *vty) route_map_result_t zebra_route_map_check (int family, int rib_type, struct prefix *p, - struct nexthop *nexthop, u_short tag) + struct nexthop *nexthop, vrf_id_t vrf_id, u_short tag) { struct route_map *rmap = NULL; route_map_result_t ret = RMAP_MATCH; struct nh_rmap_obj nh_obj; nh_obj.nexthop = nexthop; + nh_obj.vrf_id = vrf_id; nh_obj.source_protocol = rib_type; nh_obj.metric = 0; nh_obj.tag = tag; @@ -1652,6 +1655,7 @@ zebra_nht_route_map_check (int family, int client_proto, struct prefix *p, struct nh_rmap_obj nh_obj; nh_obj.nexthop = nexthop; + nh_obj.vrf_id = rib->vrf_id; nh_obj.source_protocol = rib->type; nh_obj.metric = rib->metric; nh_obj.tag = rib->tag; diff --git a/zebra/zserv.h b/zebra/zserv.h index 41a4b9ea9f..ace3715247 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -162,6 +162,7 @@ extern void zebra_route_map_write_delay_timer(struct vty *); extern route_map_result_t zebra_route_map_check (int family, int rib_type, struct prefix *p, struct nexthop *nexthop, + vrf_id_t vrf_id, u_short tag); extern route_map_result_t zebra_nht_route_map_check (int family, int client_proto, -- cgit v1.2.3 From 8f527c5e7e6888a7fced25928ea22899259ab49f Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:40:06 +0200 Subject: zebra: configure static routes in any VRF Introduce new commands to configure static routes in any VRF, by appending the old static route commands with a new parameter "vrf N". A new parameter "const char *vrf_id_str" is added to the functions zebra_static_ipv4() and static_ipv6_func() to get the configured VRF ID. A new member "vrf_id" is added to the "struct static_ipv4" and "struct static_ipv6", indicating which VRF this static route is configured in. But till now, no interface can exist in any non-default VRF. So these static routes in non-default VRFs are kept inactive. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter Conflicts: zebra/zebra_rib.c zebra/zebra_vty.c --- zebra/rib.h | 6 + zebra/zebra_rib.c | 14 +- zebra/zebra_vty.c | 4120 ++++++++++++++++++++++++++++++++++++----------------- 3 files changed, 2794 insertions(+), 1346 deletions(-) (limited to 'zebra/zebra_rib.c') diff --git a/zebra/rib.h b/zebra/rib.h index 6908e9d816..b76231f8a9 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -174,6 +174,9 @@ struct static_ipv4 struct static_ipv4 *prev; struct static_ipv4 *next; + /* VRF identifier. */ + vrf_id_t vrf_id; + /* Administrative distance. */ u_char distance; @@ -209,6 +212,9 @@ struct static_ipv6 struct static_ipv6 *prev; struct static_ipv6 *next; + /* VRF identifier. */ + vrf_id_t vrf_id; + /* Administrative distance. */ u_char distance; diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 0f25c76858..2b94c6a7c6 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2689,7 +2689,7 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si) struct prefix nh_p; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, si->vrf_id); if (! table) return; @@ -2740,7 +2740,7 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si) rib->instance = 0; rib->distance = si->distance; rib->metric = 0; - rib->vrf_id = VRF_DEFAULT; + rib->vrf_id = si->vrf_id; rib->table = zebrad.rtm_table_default; rib->nexthop_num = 0; rib->tag = si->tag; @@ -2798,7 +2798,7 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si) struct prefix nh_p; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, si->vrf_id); if (! table) return; @@ -2928,6 +2928,7 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, si->distance = distance; si->flags = flags; si->tag = tag; + si->vrf_id = vrf_id; if (gate) si->gate.ipv4 = *gate; @@ -3454,7 +3455,7 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si) struct prefix nh_p; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, si->vrf_id); if (! table) return; @@ -3506,7 +3507,7 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si) rib->instance = 0; rib->distance = si->distance; rib->metric = 0; - rib->vrf_id = VRF_DEFAULT; + rib->vrf_id = si->vrf_id; rib->table = zebrad.rtm_table_default; rib->nexthop_num = 0; rib->tag = si->tag; @@ -3565,7 +3566,7 @@ static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si) struct prefix nh_p; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, si->vrf_id); if (! table) return; @@ -3686,6 +3687,7 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, si->distance = distance; si->flags = flags; si->tag = tag; + si->vrf_id = vrf_id; switch (type) { diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index a9fb278aab..4341152e09 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -42,7 +42,7 @@ static int zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, const char *mask_str, const char *gate_str, const char *flag_str, const char *tag_str, - const char *distance_str) + const char *distance_str, const char *vrf_id_str) { int ret; u_char distance; @@ -52,6 +52,7 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, const char *ifname; u_char flag = 0; u_short tag = 0; + vrf_id_t vrf_id = VRF_DEFAULT; ret = str2prefix (dest_str, &p); if (ret <= 0) @@ -85,6 +86,10 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, if (tag_str) tag = atoi(tag_str); + /* VRF id */ + if (vrf_id_str) + VTY_GET_INTEGER ("VRF ID", vrf_id, vrf_id_str); + /* Null0 static route. */ if ((gate_str != NULL) && (strncasecmp (gate_str, "Null0", strlen (gate_str)) == 0)) { @@ -94,9 +99,9 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, return CMD_WARNING; } if (add_cmd) - static_add_ipv4 (&p, NULL, NULL, ZEBRA_FLAG_BLACKHOLE, tag, distance, VRF_DEFAULT); + static_add_ipv4 (&p, NULL, NULL, ZEBRA_FLAG_BLACKHOLE, tag, distance, vrf_id); else - static_delete_ipv4 (&p, NULL, NULL, tag, distance, VRF_DEFAULT); + static_delete_ipv4 (&p, NULL, NULL, tag, distance, vrf_id); return CMD_SUCCESS; } @@ -120,9 +125,9 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, if (gate_str == NULL) { if (add_cmd) - static_add_ipv4 (&p, NULL, NULL, flag, tag, distance, VRF_DEFAULT); + static_add_ipv4 (&p, NULL, NULL, flag, tag, distance, vrf_id); else - static_delete_ipv4 (&p, NULL, NULL, tag, distance, VRF_DEFAULT); + static_delete_ipv4 (&p, NULL, NULL, tag, distance, vrf_id); return CMD_SUCCESS; } @@ -136,9 +141,9 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, ifname = gate_str; if (add_cmd) - static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, flag, tag, distance, VRF_DEFAULT); + static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, flag, tag, distance, vrf_id); else - static_delete_ipv4 (&p, ifname ? NULL : &gate, ifname, tag, distance, VRF_DEFAULT); + static_delete_ipv4 (&p, ifname ? NULL : &gate, ifname, tag, distance, vrf_id); return CMD_SUCCESS; } @@ -154,7 +159,8 @@ DEFUN (ip_route, "IP gateway interface name\n" "Null interface\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL, NULL); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL, + NULL, NULL); } DEFUN (ip_route_tag, @@ -169,7 +175,8 @@ DEFUN (ip_route_tag, "Set tag for this route\n" "Tag value\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2], NULL); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2], + NULL, NULL); } DEFUN (ip_route_flags, @@ -183,7 +190,8 @@ DEFUN (ip_route_flags, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL, NULL); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL, + NULL, NULL); } DEFUN (ip_route_flags_tag, @@ -200,7 +208,8 @@ DEFUN (ip_route_flags_tag, "Tag value\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3], NULL); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3], + NULL, NULL); } DEFUN (ip_route_flags2, @@ -212,7 +221,8 @@ DEFUN (ip_route_flags2, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL, NULL); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL, + NULL, NULL); } DEFUN (ip_route_flags2_tag, @@ -227,7 +237,8 @@ DEFUN (ip_route_flags2_tag, "Tag value\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2], NULL); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2], + NULL, NULL); } /* Mask as A.B.C.D format. */ @@ -242,7 +253,8 @@ DEFUN (ip_route_mask, "IP gateway interface name\n" "Null interface\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, NULL); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, + NULL, NULL); } DEFUN (ip_route_mask_tag, @@ -259,7 +271,8 @@ DEFUN (ip_route_mask_tag, "Tag value\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], NULL); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], + NULL, NULL); } DEFUN (ip_route_mask_flags, @@ -274,7 +287,8 @@ DEFUN (ip_route_mask_flags, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, NULL); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, + NULL, NULL); } DEFUN (ip_route_mask_flags_tag, @@ -292,7 +306,8 @@ DEFUN (ip_route_mask_flags_tag, "Tag value\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], NULL); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], + NULL, NULL); } DEFUN (ip_route_mask_flags2, @@ -305,7 +320,8 @@ DEFUN (ip_route_mask_flags2, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, NULL); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, + NULL, NULL); } DEFUN (ip_route_mask_flags2_tag, @@ -320,7 +336,8 @@ DEFUN (ip_route_mask_flags2_tag, "Set tag for this route\n" "Tag value\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], NULL); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], + NULL, NULL); } /* Distance option value. */ @@ -335,7 +352,8 @@ DEFUN (ip_route_distance, "Null interface\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL, argv[2]); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL, + argv[2], NULL); } DEFUN (ip_route_tag_distance, @@ -352,7 +370,8 @@ DEFUN (ip_route_tag_distance, "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2], argv[3]); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2], + argv[3], NULL); } DEFUN (ip_route_flags_distance, @@ -367,7 +386,8 @@ DEFUN (ip_route_flags_distance, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL, argv[3]); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL, + argv[3], NULL); } DEFUN (ip_route_flags_tag_distance, @@ -384,7 +404,8 @@ DEFUN (ip_route_flags_tag_distance, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3], argv[4]); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3], + argv[4], NULL); } DEFUN (ip_route_flags_distance2, @@ -397,7 +418,8 @@ DEFUN (ip_route_flags_distance2, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL, argv[2]); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL, + argv[2], NULL); } DEFUN (ip_route_flags_tag_distance2, @@ -412,7 +434,8 @@ DEFUN (ip_route_flags_tag_distance2, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2], argv[3]); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2], + argv[3], NULL); } DEFUN (ip_route_mask_distance, @@ -427,7 +450,8 @@ DEFUN (ip_route_mask_distance, "Null interface\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, argv[3]); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, + argv[3], NULL); } DEFUN (ip_route_mask_tag_distance, @@ -444,7 +468,8 @@ DEFUN (ip_route_mask_tag_distance, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], argv[4]); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], + argv[4], NULL); } DEFUN (ip_route_mask_flags_tag_distance, @@ -462,7 +487,8 @@ DEFUN (ip_route_mask_flags_tag_distance, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], + argv[5], NULL); } @@ -479,7 +505,8 @@ DEFUN (ip_route_mask_flags_distance, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, argv[4]); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, + argv[4], NULL); } DEFUN (ip_route_mask_flags_distance2, @@ -493,7 +520,8 @@ DEFUN (ip_route_mask_flags_distance2, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, argv[3]); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, + argv[3], NULL); } DEFUN (ip_route_mask_flags_tag_distance2, @@ -509,7 +537,8 @@ DEFUN (ip_route_mask_flags_tag_distance2, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], argv[4]); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], + argv[4], NULL); } DEFUN (no_ip_route, @@ -523,7 +552,8 @@ DEFUN (no_ip_route, "IP gateway interface name\n" "Null interface\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL, NULL); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL, + NULL, NULL); } DEFUN (no_ip_route_tag, @@ -539,7 +569,8 @@ DEFUN (no_ip_route_tag, "Tag of this route\n" "Tag value\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2], NULL); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2], + NULL, NULL); } ALIAS (no_ip_route, @@ -578,7 +609,8 @@ DEFUN (no_ip_route_flags2, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, NULL, NULL); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, NULL, + NULL, NULL); } DEFUN (no_ip_route_flags2_tag, @@ -593,7 +625,8 @@ DEFUN (no_ip_route_flags2_tag, "Tag of this route\n" "Tag value\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, argv[1], NULL); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, argv[1], + NULL, NULL); } DEFUN (no_ip_route_mask, @@ -608,7 +641,8 @@ DEFUN (no_ip_route_mask, "IP gateway interface name\n" "Null interface\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, NULL); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, + NULL, NULL); } DEFUN (no_ip_route_mask_tag, @@ -625,7 +659,8 @@ DEFUN (no_ip_route_mask_tag, "Tag of this route\n" "Tag value\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], NULL); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], + NULL, NULL); } ALIAS (no_ip_route_mask, @@ -667,7 +702,8 @@ DEFUN (no_ip_route_mask_flags2, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, NULL, NULL); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, NULL, + NULL, NULL); } DEFUN (no_ip_route_mask_flags2_tag, @@ -683,10 +719,10 @@ DEFUN (no_ip_route_mask_flags2_tag, "Tag of this route\n" "Tag value\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], NULL); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], + NULL, NULL); } - DEFUN (no_ip_route_distance, no_ip_route_distance_cmd, "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) <1-255>", @@ -699,7 +735,8 @@ DEFUN (no_ip_route_distance, "Null interface\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL, argv[2]); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL, + argv[2], NULL); } DEFUN (no_ip_route_tag_distance, @@ -716,7 +753,8 @@ DEFUN (no_ip_route_tag_distance, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2], argv[3]); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2], + argv[3], NULL); } DEFUN (no_ip_route_flags_distance, @@ -732,7 +770,8 @@ DEFUN (no_ip_route_flags_distance, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], NULL, argv[3]); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], NULL, + argv[3], NULL); } DEFUN (no_ip_route_flags_tag_distance, @@ -750,7 +789,8 @@ DEFUN (no_ip_route_flags_tag_distance, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], argv[3], argv[4]); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], argv[3], + argv[4], NULL); } DEFUN (no_ip_route_flags_distance2, @@ -764,7 +804,8 @@ DEFUN (no_ip_route_flags_distance2, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], NULL, argv[2]); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], NULL, + argv[2], NULL); } DEFUN (no_ip_route_flags_tag_distance2, @@ -780,7 +821,8 @@ DEFUN (no_ip_route_flags_tag_distance2, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], argv[2] , argv[3]); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], argv[2], + argv[3], NULL); } DEFUN (no_ip_route_mask_distance, @@ -796,7 +838,8 @@ DEFUN (no_ip_route_mask_distance, "Null interface\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, argv[3]); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, + argv[3], NULL); } DEFUN (no_ip_route_mask_tag_distance, @@ -814,7 +857,8 @@ DEFUN (no_ip_route_mask_tag_distance, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], argv[4]); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], + argv[4], NULL); } DEFUN (no_ip_route_mask_flags_distance, @@ -831,7 +875,8 @@ DEFUN (no_ip_route_mask_flags_distance, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], NULL, argv[4]); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], NULL, + argv[4], NULL); } DEFUN (no_ip_route_mask_flags_tag_distance, @@ -850,7 +895,8 @@ DEFUN (no_ip_route_mask_flags_tag_distance, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4], + argv[5], NULL); } DEFUN (no_ip_route_mask_flags_distance2, @@ -865,7 +911,8 @@ DEFUN (no_ip_route_mask_flags_distance2, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], NULL, argv[3]); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], NULL, + argv[3], NULL); } DEFUN (no_ip_route_mask_flags_tag_distance2, @@ -882,868 +929,1659 @@ DEFUN (no_ip_route_mask_flags_tag_distance2, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3], argv[4]); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3], + argv[4], NULL); } -/* New RIB. Detailed information for IPv4 route. */ -static void -vty_show_ip_route_detail (struct vty *vty, struct route_node *rn) +/* Static route configuration. */ +DEFUN (ip_route_vrf, + ip_route_vrf_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0)" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + VRF_CMD_HELP_STR) { - struct rib *rib; - struct nexthop *nexthop, *tnexthop; - int recursing; - char buf[BUFSIZ]; + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL, NULL, argv[2]); +} - RNODE_FOREACH_RIB (rn, rib) - { - vty_out (vty, "Routing entry for %s/%d%s", - inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen, - VTY_NEWLINE); - vty_out (vty, " Known via \"%s", zebra_route_string (rib->type)); - if (rib->instance) - vty_out (vty, "[%d]", rib->instance); - vty_out (vty, "\""); - vty_out (vty, ", distance %u, metric %u", rib->distance, rib->metric); - if (rib->tag) - vty_out (vty, ", tag %d", rib->tag); - vty_out (vty, ", vrf %u", rib->vrf_id); - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) - vty_out (vty, ", best"); - if (rib->refcnt) - vty_out (vty, ", refcnt %ld", rib->refcnt); - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, ", blackhole"); - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, ", reject"); - vty_out (vty, "%s", VTY_NEWLINE); +DEFUN (ip_route_tag_vrf, + ip_route_tag_vrf_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) tag <1-65535>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2], NULL, argv[3]); +} -#define ONE_DAY_SECOND 60*60*24 -#define ONE_WEEK_SECOND 60*60*24*7 - if (rib->type == ZEBRA_ROUTE_RIP - || rib->type == ZEBRA_ROUTE_OSPF - || rib->type == ZEBRA_ROUTE_BABEL - || rib->type == ZEBRA_ROUTE_ISIS - || rib->type == ZEBRA_ROUTE_TABLE - || rib->type == ZEBRA_ROUTE_BGP) - { - time_t uptime; - struct tm *tm; +DEFUN (ip_route_flags_vrf, + ip_route_flags_vrf_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole)" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL, NULL, argv[3]); +} - uptime = time (NULL); - uptime -= rib->uptime; - tm = gmtime (&uptime); +DEFUN (ip_route_flags_tag_vrf, + ip_route_flags_tag_vrf_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) - vty_out (vty, " Last update "); +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3], NULL, argv[4]); +} - if (uptime < ONE_DAY_SECOND) - vty_out (vty, "%02d:%02d:%02d", - tm->tm_hour, tm->tm_min, tm->tm_sec); - else if (uptime < ONE_WEEK_SECOND) - vty_out (vty, "%dd%02dh%02dm", - tm->tm_yday, tm->tm_hour, tm->tm_min); - else - vty_out (vty, "%02dw%dd%02dh", - tm->tm_yday/7, - tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); - vty_out (vty, " ago%s", VTY_NEWLINE); - } +DEFUN (ip_route_flags2_vrf, + ip_route_flags2_vrf_cmd, + "ip route A.B.C.D/M (reject|blackhole)" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL, NULL, argv[2]); +} - for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) - { - char addrstr[32]; +DEFUN (ip_route_flags2_tag_vrf, + ip_route_flags2_tag_vrf_cmd, + "ip route A.B.C.D/M (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) - vty_out (vty, " %c%s", - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ', - recursing ? " " : ""); +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2], NULL, argv[3]); +} - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out (vty, " %s", inet_ntoa (nexthop->gate.ipv4)); - if (nexthop->ifindex) - vty_out (vty, ", via %s", - ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); - break; -#ifdef HAVE_IPV6 - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - case NEXTHOP_TYPE_IPV6_IFNAME: - vty_out (vty, " %s", - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); - if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME) - vty_out (vty, ", %s", nexthop->ifname); - else if (nexthop->ifindex) - vty_out (vty, ", via %s", - ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); - break; -#endif /* HAVE_IPV6 */ - case NEXTHOP_TYPE_IFINDEX: - vty_out (vty, " directly connected, %s", - ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); - break; - case NEXTHOP_TYPE_IFNAME: - vty_out (vty, " directly connected, %s", nexthop->ifname); - break; - case NEXTHOP_TYPE_BLACKHOLE: - vty_out (vty, " directly connected, Null0"); - break; - default: - break; - } - if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - vty_out (vty, " inactive"); +/* Mask as A.B.C.D format. */ +DEFUN (ip_route_mask_vrf, + ip_route_mask_vrf_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0)" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, NULL, argv[3]); +} - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) - vty_out (vty, " onlink"); +DEFUN (ip_route_mask_tag_vrf, + ip_route_mask_tag_vrf_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) tag <1-65535>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - vty_out (vty, " (recursive)"); +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], NULL, argv[4]); +} - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - case NEXTHOP_TYPE_IPV4_IFNAME: - if (nexthop->src.ipv4.s_addr) - { - if (inet_ntop(AF_INET, &nexthop->src.ipv4, addrstr, - sizeof addrstr)) - vty_out (vty, ", src %s", addrstr); - } - break; -#ifdef HAVE_IPV6 - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - case NEXTHOP_TYPE_IPV6_IFNAME: - if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) - { - if (inet_ntop(AF_INET6, &nexthop->src.ipv6, addrstr, - sizeof addrstr)) - vty_out (vty, ", src %s", addrstr); - } - break; -#endif /* HAVE_IPV6 */ - default: - break; - } - vty_out (vty, "%s", VTY_NEWLINE); - } - vty_out (vty, "%s", VTY_NEWLINE); - } +DEFUN (ip_route_mask_flags_vrf, + ip_route_mask_flags_vrf_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole)" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, NULL, argv[4]); } -static void -vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib) +DEFUN (ip_route_mask_flags_tag_vrf, + ip_route_mask_flags_tag_vrf_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) + { - struct nexthop *nexthop, *tnexthop; - int recursing; - int len = 0; - char buf[BUFSIZ]; + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], NULL, argv[5]); +} - /* Nexthop information. */ - for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) - { - if (nexthop == rib->nexthop) - { - /* Prefix information. */ - len = vty_out (vty, "%c", zebra_route_char (rib->type)); - if (rib->instance) - len += vty_out (vty, "[%d]", rib->instance); - len += vty_out (vty, "%c%c %s/%d", - CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) - ? '>' : ' ', - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) - ? '*' : ' ', - inet_ntop (AF_INET, &rn->p.u.prefix, buf, BUFSIZ), - rn->p.prefixlen); - - /* Distance and metric display. */ - if (rib->type != ZEBRA_ROUTE_CONNECT - && rib->type != ZEBRA_ROUTE_KERNEL) - len += vty_out (vty, " [%d/%d]", rib->distance, - rib->metric); - - if (rib->vrf_id != VRF_DEFAULT) - len += vty_out (vty, " [vrf %u]", rib->vrf_id); - } - else - vty_out (vty, " %c%*c", - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) - ? '*' : ' ', - len - 3 + (2 * recursing), ' '); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4)); - if (nexthop->ifindex) - vty_out (vty, ", %s", - ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); - break; -#ifdef HAVE_IPV6 - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - case NEXTHOP_TYPE_IPV6_IFNAME: - vty_out (vty, " via %s", - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); - if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME) - vty_out (vty, ", %s", nexthop->ifname); - else if (nexthop->ifindex) - vty_out (vty, ", %s", - ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); - break; -#endif /* HAVE_IPV6 */ - - case NEXTHOP_TYPE_IFINDEX: - vty_out (vty, " is directly connected, %s", - ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); - break; - case NEXTHOP_TYPE_IFNAME: - vty_out (vty, " is directly connected, %s", nexthop->ifname); - break; - case NEXTHOP_TYPE_BLACKHOLE: - vty_out (vty, " is directly connected, Null0"); - break; - default: - break; - } - if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - vty_out (vty, " inactive"); - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) - vty_out (vty, " onlink"); - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - vty_out (vty, " (recursive)"); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - case NEXTHOP_TYPE_IPV4_IFNAME: - if (nexthop->src.ipv4.s_addr) - { - if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, sizeof buf)) - vty_out (vty, ", src %s", buf); - } - break; -#ifdef HAVE_IPV6 - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - case NEXTHOP_TYPE_IPV6_IFNAME: - if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) - { - if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf, sizeof buf)) - vty_out (vty, ", src %s", buf); - } - break; -#endif /* HAVE_IPV6 */ - default: - break; - } - - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, ", bh"); - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, ", rej"); - - if (rib->type == ZEBRA_ROUTE_RIP - || rib->type == ZEBRA_ROUTE_OSPF - || rib->type == ZEBRA_ROUTE_BABEL - || rib->type == ZEBRA_ROUTE_ISIS - || rib->type == ZEBRA_ROUTE_TABLE - || rib->type == ZEBRA_ROUTE_BGP) - { - time_t uptime; - struct tm *tm; - - uptime = time (NULL); - uptime -= rib->uptime; - tm = gmtime (&uptime); - -#define ONE_DAY_SECOND 60*60*24 -#define ONE_WEEK_SECOND 60*60*24*7 - - if (uptime < ONE_DAY_SECOND) - vty_out (vty, ", %02d:%02d:%02d", - tm->tm_hour, tm->tm_min, tm->tm_sec); - else if (uptime < ONE_WEEK_SECOND) - vty_out (vty, ", %dd%02dh%02dm", - tm->tm_yday, tm->tm_hour, tm->tm_min); - else - vty_out (vty, ", %02dw%dd%02dh", - tm->tm_yday/7, - tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); - } - vty_out (vty, "%s", VTY_NEWLINE); - } +DEFUN (ip_route_mask_flags2_vrf, + ip_route_mask_flags2_vrf_cmd, + "ip route A.B.C.D A.B.C.D (reject|blackhole)" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, NULL, argv[3]); } -DEFUN (show_ip_route, - show_ip_route_cmd, - "show ip route", - SHOW_STR +DEFUN (ip_route_mask_flags2_tag_vrf, + ip_route_mask_flags2_tag_vrf_cmd, + "ip route A.B.C.D A.B.C.D (reject|blackhole) tag <1-65535>" VRF_CMD_STR, IP_STR - "IP routing table\n") + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) { - struct route_table *table; - struct route_node *rn; - struct rib *rib; - int first = 1; - - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); - if (! table) - return CMD_SUCCESS; - - /* Show all IPv4 routes. */ - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RIB (rn, rib) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V4_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, rib); - } - return CMD_SUCCESS; + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], NULL, argv[4]); } -DEFUN (show_ip_nht, - show_ip_nht_cmd, - "show ip nht", - SHOW_STR +/* Distance option value. */ +DEFUN (ip_route_distance_vrf, + ip_route_distance_vrf_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) <1-255>" VRF_CMD_STR, IP_STR - "IP nexthop tracking table\n") + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) { - zebra_print_rnh_table(0, AF_INET, vty, RNH_NEXTHOP_TYPE); - return CMD_SUCCESS; + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL, argv[2], argv[3]); } -DEFUN (show_ipv6_nht, - show_ipv6_nht_cmd, - "show ipv6 nht", - SHOW_STR +DEFUN (ip_route_tag_distance_vrf, + ip_route_tag_distance_vrf_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) tag <1-65535> <1-255>" VRF_CMD_STR, IP_STR - "IPv6 nexthop tracking table\n") + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) + { - zebra_print_rnh_table(0, AF_INET6, vty, RNH_NEXTHOP_TYPE); - return CMD_SUCCESS; + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2], argv[3], argv[4]); } -DEFUN (ip_nht_default_route, - ip_nht_default_route_cmd, - "ip nht resolve-via-default", +DEFUN (ip_route_flags_distance_vrf, + ip_route_flags_distance_vrf_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>" VRF_CMD_STR, IP_STR - "Filter Next Hop tracking route resolution\n" - "Resolve via default route\n") + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) { - if (zebra_rnh_ip_default_route) - return CMD_SUCCESS; - - zebra_rnh_ip_default_route = 1; - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL, argv[3], argv[4]); } -DEFUN (no_ip_nht_default_route, - no_ip_nht_default_route_cmd, - "no ip nht resolve-via-default", - NO_STR +DEFUN (ip_route_flags_tag_distance_vrf, + ip_route_flags_tag_distance_vrf_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, IP_STR - "Filter Next Hop tracking route resolution\n" - "Resolve via default route\n") + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) { - if (!zebra_rnh_ip_default_route) - return CMD_SUCCESS; + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3], argv[4],argv[5]); +} - zebra_rnh_ip_default_route = 0; - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; +DEFUN (ip_route_flags_distance2_vrf, + ip_route_flags_distance2_vrf_cmd, + "ip route A.B.C.D/M (reject|blackhole) <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL, argv[2], argv[3]); } -DEFUN (ipv6_nht_default_route, - ipv6_nht_default_route_cmd, - "ipv6 nht resolve-via-default", - IP6_STR - "Filter Next Hop tracking route resolution\n" - "Resolve via default route\n") +DEFUN (ip_route_flags_tag_distance2_vrf, + ip_route_flags_tag_distance2_vrf_cmd, + "ip route A.B.C.D/M (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) { - if (zebra_rnh_ipv6_default_route) - return CMD_SUCCESS; - - zebra_rnh_ipv6_default_route = 1; - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2], argv[3], argv[4]); } -DEFUN (no_ipv6_nht_default_route, - no_ipv6_nht_default_route_cmd, - "no ipv6 nht resolve-via-default", - NO_STR - IP6_STR - "Filter Next Hop tracking route resolution\n" - "Resolve via default route\n") +DEFUN (ip_route_mask_distance_vrf, + ip_route_mask_distance_vrf_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) { - if (!zebra_rnh_ipv6_default_route) - return CMD_SUCCESS; - - zebra_rnh_ipv6_default_route = 0; - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, argv[3], argv[4]); } - -DEFUN (show_ip_route_tag, - show_ip_route_tag_cmd, - "show ip route tag <1-65535>", - SHOW_STR +DEFUN (ip_route_mask_tag_distance_vrf, + ip_route_mask_tag_distance_vrf_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) tag <1-65535> <1-255>" VRF_CMD_STR, IP_STR - "IP routing table\n" - "Show only routes with tag\n" - "Tag value\n") + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) { - struct route_table *table; - struct route_node *rn; - struct rib *rib; - int first = 1; - u_short tag = 0; - - if (argv[0]) - tag = atoi(argv[0]); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], argv[4], argv[5]); +} - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); - if (! table) - return CMD_SUCCESS; +DEFUN (ip_route_mask_flags_tag_distance_vrf, + ip_route_mask_flags_tag_distance_vrf_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); +} - /* Show all IPv4 routes with matching tag value. */ - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RIB (rn, rib) - { - if (rib->tag != tag) - continue; - if (first) - { - vty_out (vty, SHOW_ROUTE_V4_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, rib); - } - return CMD_SUCCESS; +DEFUN (ip_route_mask_flags_distance_vrf, + ip_route_mask_flags_distance_vrf_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, argv[4], argv[5]); } -ALIAS (show_ip_route, - show_ip_route_vrf_cmd, - "show ip route " VRF_CMD_STR, - SHOW_STR +DEFUN (ip_route_mask_flags_distance2_vrf, + ip_route_mask_flags_distance2_vrf_cmd, + "ip route A.B.C.D A.B.C.D (reject|blackhole) <1-255>" VRF_CMD_STR, IP_STR - "IP routing table\n" + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this route\n" VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, argv[3], argv[4]); +} -DEFUN (show_ip_route_prefix_longer, - show_ip_route_prefix_longer_cmd, - "show ip route A.B.C.D/M longer-prefixes", - SHOW_STR +DEFUN (ip_route_mask_flags_tag_distance2_vrf, + ip_route_mask_flags_tag_distance2_vrf_cmd, + "ip route A.B.C.D A.B.C.D (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, IP_STR - "IP routing table\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Show route matching the specified Network/Mask pair only\n") + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) { - struct route_table *table; - struct route_node *rn; - struct rib *rib; - struct prefix p; - int ret; - int first = 1; - vrf_id_t vrf_id = VRF_DEFAULT; - - ret = str2prefix (argv[0], &p); - if (! ret) - { - vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE); - return CMD_WARNING; - } - - if (argc > 1) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); - - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; - - /* Show matched type IPv4 routes. */ - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RIB (rn, rib) - if (prefix_match (&p, &rn->p)) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V4_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, rib); - } - return CMD_SUCCESS; + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], argv[4], argv[5]); } -ALIAS (show_ip_route_prefix_longer, - show_ip_route_prefix_longer_vrf_cmd, - "show ip route A.B.C.D/M longer-prefixes " VRF_CMD_STR, - SHOW_STR +DEFUN (no_ip_route_vrf, + no_ip_route_vrf_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0)" VRF_CMD_STR, + NO_STR IP_STR - "IP routing table\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Show route matching the specified Network/Mask pair only\n" + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL, NULL, argv[2]); +} -DEFUN (show_ip_route_supernets, - show_ip_route_supernets_cmd, - "show ip route supernets-only", - SHOW_STR +DEFUN (no_ip_route_tag_vrf, + no_ip_route_tag_vrf_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) tag <1-65535>" VRF_CMD_STR, + NO_STR IP_STR - "IP routing table\n" - "Show supernet entries only\n") + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Tag of this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) { - struct route_table *table; - struct route_node *rn; - struct rib *rib; - u_int32_t addr; - int first = 1; - vrf_id_t vrf_id = VRF_DEFAULT; - - if (argc > 0) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); - - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; - - /* Show matched type IPv4 routes. */ - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RIB (rn, rib) - { - addr = ntohl (rn->p.u.prefix4.s_addr); - - if ((IN_CLASSC (addr) && rn->p.prefixlen < 24) - || (IN_CLASSB (addr) && rn->p.prefixlen < 16) - || (IN_CLASSA (addr) && rn->p.prefixlen < 8)) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V4_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, rib); - } - } - return CMD_SUCCESS; + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2], NULL, argv[3]); } -ALIAS (show_ip_route_supernets, - show_ip_route_supernets_vrf_cmd, - "show ip route supernets-only " VRF_CMD_STR, - SHOW_STR +ALIAS (no_ip_route_vrf, + no_ip_route_flags_vrf_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole)" VRF_CMD_STR, + NO_STR IP_STR - "IP routing table\n" - "Show supernet entries only\n" + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" VRF_CMD_HELP_STR) -DEFUN (show_ip_route_protocol, - show_ip_route_protocol_cmd, - "show ip route " QUAGGA_IP_REDIST_STR_ZEBRA, - SHOW_STR +ALIAS (no_ip_route_tag_vrf, + no_ip_route_flags_tag_vrf_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + NO_STR IP_STR - "IP routing table\n" - QUAGGA_IP_REDIST_HELP_STR_ZEBRA) -{ - int type; - struct route_table *table; - struct route_node *rn; - struct rib *rib; - int first = 1; - vrf_id_t vrf_id = VRF_DEFAULT; - - type = proto_redistnum (AFI_IP, argv[0]); - if (type < 0) - { - vty_out (vty, "Unknown route type%s", VTY_NEWLINE); - return CMD_WARNING; - } - - if (argc > 1) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); - - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) - /* Show matched type IPv4 routes. */ - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RIB (rn, rib) - if (rib->type == type) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V4_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, rib); - } - return CMD_SUCCESS; +DEFUN (no_ip_route_flags2_vrf, + no_ip_route_flags2_vrf_cmd, + "no ip route A.B.C.D/M (reject|blackhole)" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, NULL, NULL, argv[1]); } -ALIAS (show_ip_route_protocol, - show_ip_route_protocol_vrf_cmd, - "show ip route " QUAGGA_IP_REDIST_STR_ZEBRA " " VRF_CMD_STR, - SHOW_STR +DEFUN (no_ip_route_flags2_tag_vrf, + no_ip_route_flags2_tag_vrf_cmd, + "no ip route A.B.C.D/M (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + NO_STR IP_STR - "IP routing table\n" - QUAGGA_IP_REDIST_HELP_STR_ZEBRA + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, argv[1], NULL, argv[1]); +} -DEFUN (show_ip_route_ospf_instance, - show_ip_route_ospf_instance_cmd, - "show ip route ospf <1-65535>", - SHOW_STR +DEFUN (no_ip_route_mask_vrf, + no_ip_route_mask_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0)" VRF_CMD_STR, + NO_STR IP_STR - "IP routing table\n" - "Open Shortest Path First (OSPFv2)\n" - "Instance ID\n") + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + VRF_CMD_HELP_STR) { - struct route_table *table; - struct route_node *rn; - struct rib *rib; - int first = 1; - u_short instance = 0; - - VTY_GET_INTEGER ("Instance", instance, argv[0]); - - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); - if (! table) - return CMD_SUCCESS; - - /* Show matched type IPv4 routes. */ - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RIB (rn, rib) - if (rib->type == ZEBRA_ROUTE_OSPF && rib->instance == instance) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V4_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, rib); - } - return CMD_SUCCESS; + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, NULL, argv[3]); } -DEFUN (show_ip_route_addr, - show_ip_route_addr_cmd, - "show ip route A.B.C.D", - SHOW_STR +DEFUN (no_ip_route_mask_tag_vrf, + no_ip_route_mask_tag_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) tag <1-65535>" VRF_CMD_STR, + NO_STR IP_STR - "IP routing table\n" - "Network in the IP routing table to display\n") + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Tag of this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) { - int ret; - struct prefix_ipv4 p; - struct route_table *table; - struct route_node *rn; - vrf_id_t vrf_id = VRF_DEFAULT; + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], NULL, argv[4]); +} - ret = str2prefix_ipv4 (argv[0], &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed IPv4 address%s", VTY_NEWLINE); - return CMD_WARNING; - } +ALIAS (no_ip_route_mask_vrf, + no_ip_route_mask_flags_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole)" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) - if (argc > 1) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); +ALIAS (no_ip_route_mask_tag_vrf, + no_ip_route_mask_flags_tag_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; +DEFUN (no_ip_route_mask_flags2_vrf, + no_ip_route_mask_flags2_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (reject|blackhole)" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, NULL, NULL, argv[2]); +} - rn = route_node_match (table, (struct prefix *) &p); - if (! rn) - { - vty_out (vty, "%% Network not in table%s", VTY_NEWLINE); - return CMD_WARNING; - } +DEFUN (no_ip_route_mask_flags2_tag_vrf, + no_ip_route_mask_flags2_tag_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], NULL, argv[3]); +} - vty_show_ip_route_detail (vty, rn); - route_unlock_node (rn); +DEFUN (no_ip_route_distance_vrf, + no_ip_route_distance_vrf_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL, argv[2], argv[3]); +} - return CMD_SUCCESS; +DEFUN (no_ip_route_tag_distance_vrf, + no_ip_route_tag_distance_vrf_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) tag <1-65535> <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2], argv[3], argv[4]); } -ALIAS (show_ip_route_addr, - show_ip_route_addr_vrf_cmd, - "show ip route A.B.C.D " VRF_CMD_STR, - SHOW_STR +DEFUN (no_ip_route_flags_distance_vrf, + no_ip_route_flags_distance_vrf_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>" VRF_CMD_STR, + NO_STR IP_STR - "IP routing table\n" - "Network in the IP routing table to display\n" + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this route\n" VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], NULL, argv[3], argv[4]); +} -DEFUN (show_ip_route_prefix, - show_ip_route_prefix_cmd, - "show ip route A.B.C.D/M", - SHOW_STR +DEFUN (no_ip_route_flags_tag_distance_vrf, + no_ip_route_flags_tag_distance_vrf_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + NO_STR IP_STR - "IP routing table\n" - "IP prefix /, e.g., 35.0.0.0/8\n") + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) { - int ret; - struct prefix_ipv4 p; - struct route_table *table; - struct route_node *rn; - vrf_id_t vrf_id = VRF_DEFAULT; + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], argv[3], argv[4],argv[5]); +} - ret = str2prefix_ipv4 (argv[0], &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed IPv4 address%s", VTY_NEWLINE); - return CMD_WARNING; - } +DEFUN (no_ip_route_flags_distance2_vrf, + no_ip_route_flags_distance2_vrf_cmd, + "no ip route A.B.C.D/M (reject|blackhole) <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], NULL, argv[2], argv[3]); +} - if (argc > 1) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); +DEFUN (no_ip_route_flags_tag_distance2_vrf, + no_ip_route_flags_tag_distance2_vrf_cmd, + "no ip route A.B.C.D/M (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], argv[2] , argv[3], argv[4]); +} - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; +DEFUN (no_ip_route_mask_distance_vrf, + no_ip_route_mask_distance_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, argv[3], argv[4]); +} - rn = route_node_match (table, (struct prefix *) &p); - if (! rn || rn->p.prefixlen != p.prefixlen) - { - vty_out (vty, "%% Network not in table%s", VTY_NEWLINE); - return CMD_WARNING; - } +DEFUN (no_ip_route_mask_tag_distance_vrf, + no_ip_route_mask_tag_distance_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) tag <1-65535> <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], argv[4], argv[5]); +} - vty_show_ip_route_detail (vty, rn); +DEFUN (no_ip_route_mask_flags_distance_vrf, + no_ip_route_mask_flags_distance_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], NULL, argv[4], argv[5]); +} - route_unlock_node (rn); +DEFUN (no_ip_route_mask_flags_tag_distance_vrf, + no_ip_route_mask_flags_tag_distance_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); +} - return CMD_SUCCESS; +DEFUN (no_ip_route_mask_flags_distance2_vrf, + no_ip_route_mask_flags_distance2_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (reject|blackhole) <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], NULL, argv[3], argv[4]); } -ALIAS (show_ip_route_prefix, - show_ip_route_prefix_vrf_cmd, - "show ip route A.B.C.D/M " VRF_CMD_STR, - SHOW_STR +DEFUN (no_ip_route_mask_flags_tag_distance2_vrf, + no_ip_route_mask_flags_tag_distance2_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + NO_STR IP_STR - "IP routing table\n" - "IP prefix /, e.g., 35.0.0.0/8\n" + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n" VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3], argv[4], argv[5]); +} +/* New RIB. Detailed information for IPv4 route. */ static void -vty_show_ip_route_summary (struct vty *vty, struct route_table *table) +vty_show_ip_route_detail (struct vty *vty, struct route_node *rn) { - struct route_node *rn; struct rib *rib; - struct nexthop *nexthop; -#define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX -#define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1) - u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1]; - u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1]; - u_int32_t i; - - memset (&rib_cnt, 0, sizeof(rib_cnt)); - memset (&fib_cnt, 0, sizeof(fib_cnt)); - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RIB (rn, rib) - for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) - { - rib_cnt[ZEBRA_ROUTE_TOTAL]++; - rib_cnt[rib->type]++; - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) - || nexthop_has_fib_child(nexthop)) - { - fib_cnt[ZEBRA_ROUTE_TOTAL]++; - fib_cnt[rib->type]++; - } - if (rib->type == ZEBRA_ROUTE_BGP && - CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP)) - { - rib_cnt[ZEBRA_ROUTE_IBGP]++; - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) - || nexthop_has_fib_child(nexthop)) - fib_cnt[ZEBRA_ROUTE_IBGP]++; - } - } - - vty_out (vty, "%-20s %-20s %s (vrf %u)%s", - "Route Source", "Routes", "FIB", - ((rib_table_info_t *)table->info)->zvrf->vrf_id, - VTY_NEWLINE); + struct nexthop *nexthop, *tnexthop; + int recursing; + char buf[BUFSIZ]; - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + RNODE_FOREACH_RIB (rn, rib) { - if (rib_cnt[i] > 0) - { - if (i == ZEBRA_ROUTE_BGP) - { - vty_out (vty, "%-20s %-20d %-20d %s", "ebgp", - rib_cnt[ZEBRA_ROUTE_BGP] - rib_cnt[ZEBRA_ROUTE_IBGP], - fib_cnt[ZEBRA_ROUTE_BGP] - fib_cnt[ZEBRA_ROUTE_IBGP], - VTY_NEWLINE); - vty_out (vty, "%-20s %-20d %-20d %s", "ibgp", - rib_cnt[ZEBRA_ROUTE_IBGP], fib_cnt[ZEBRA_ROUTE_IBGP], - VTY_NEWLINE); - } - else - vty_out (vty, "%-20s %-20d %-20d %s", zebra_route_string(i), - rib_cnt[i], fib_cnt[i], VTY_NEWLINE); - } - } + vty_out (vty, "Routing entry for %s/%d%s", + inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen, + VTY_NEWLINE); + vty_out (vty, " Known via \"%s", zebra_route_string (rib->type)); + if (rib->instance) + vty_out (vty, "[%d]", rib->instance); + vty_out (vty, "\""); + vty_out (vty, ", distance %u, metric %u", rib->distance, rib->metric); + if (rib->tag) + vty_out (vty, ", tag %d", rib->tag); + vty_out (vty, ", vrf %u", rib->vrf_id); + if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) + vty_out (vty, ", best"); + if (rib->refcnt) + vty_out (vty, ", refcnt %ld", rib->refcnt); + if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE)) + vty_out (vty, ", blackhole"); + if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT)) + vty_out (vty, ", reject"); + vty_out (vty, "%s", VTY_NEWLINE); - vty_out (vty, "------%s", VTY_NEWLINE); - vty_out (vty, "%-20s %-20d %-20d %s", "Totals", rib_cnt[ZEBRA_ROUTE_TOTAL], - fib_cnt[ZEBRA_ROUTE_TOTAL], VTY_NEWLINE); - vty_out (vty, "%s", VTY_NEWLINE); -} +#define ONE_DAY_SECOND 60*60*24 +#define ONE_WEEK_SECOND 60*60*24*7 + if (rib->type == ZEBRA_ROUTE_RIP + || rib->type == ZEBRA_ROUTE_OSPF + || rib->type == ZEBRA_ROUTE_BABEL + || rib->type == ZEBRA_ROUTE_ISIS + || rib->type == ZEBRA_ROUTE_TABLE + || rib->type == ZEBRA_ROUTE_BGP) + { + time_t uptime; + struct tm *tm; -/* - * Implementation of the ip route summary prefix command. - * - * This command prints the primary prefixes that have been installed by various - * protocols on the box. - * - */ -static void -vty_show_ip_route_summary_prefix (struct vty *vty, struct route_table *table) -{ - struct route_node *rn; - struct rib *rib; - struct nexthop *nexthop; -#define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX -#define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1) - u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1]; - u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1]; - u_int32_t i; - int cnt; + uptime = time (NULL); + uptime -= rib->uptime; + tm = gmtime (&uptime); - memset (&rib_cnt, 0, sizeof(rib_cnt)); - memset (&fib_cnt, 0, sizeof(fib_cnt)); - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RIB (rn, rib) - { + vty_out (vty, " Last update "); - /* - * In case of ECMP, count only once. - */ - cnt = 0; - for (nexthop = rib->nexthop; (!cnt && nexthop); nexthop = nexthop->next) - { - cnt++; - rib_cnt[ZEBRA_ROUTE_TOTAL]++; - rib_cnt[rib->type]++; + if (uptime < ONE_DAY_SECOND) + vty_out (vty, "%02d:%02d:%02d", + tm->tm_hour, tm->tm_min, tm->tm_sec); + else if (uptime < ONE_WEEK_SECOND) + vty_out (vty, "%dd%02dh%02dm", + tm->tm_yday, tm->tm_hour, tm->tm_min); + else + vty_out (vty, "%02dw%dd%02dh", + tm->tm_yday/7, + tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); + vty_out (vty, " ago%s", VTY_NEWLINE); + } + + for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) + { + char addrstr[32]; + + vty_out (vty, " %c%s", + CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ', + recursing ? " " : ""); + + switch (nexthop->type) + { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out (vty, " %s", inet_ntoa (nexthop->gate.ipv4)); + if (nexthop->ifindex) + vty_out (vty, ", via %s", + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + break; +#ifdef HAVE_IPV6 + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + case NEXTHOP_TYPE_IPV6_IFNAME: + vty_out (vty, " %s", + inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); + if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME) + vty_out (vty, ", %s", nexthop->ifname); + else if (nexthop->ifindex) + vty_out (vty, ", via %s", + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + break; +#endif /* HAVE_IPV6 */ + case NEXTHOP_TYPE_IFINDEX: + vty_out (vty, " directly connected, %s", + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + break; + case NEXTHOP_TYPE_IFNAME: + vty_out (vty, " directly connected, %s", nexthop->ifname); + break; + case NEXTHOP_TYPE_BLACKHOLE: + vty_out (vty, " directly connected, Null0"); + break; + default: + break; + } + if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + vty_out (vty, " inactive"); + + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) + vty_out (vty, " onlink"); + + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + vty_out (vty, " (recursive)"); + + switch (nexthop->type) + { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFNAME: + if (nexthop->src.ipv4.s_addr) + { + if (inet_ntop(AF_INET, &nexthop->src.ipv4, addrstr, + sizeof addrstr)) + vty_out (vty, ", src %s", addrstr); + } + break; +#ifdef HAVE_IPV6 + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + case NEXTHOP_TYPE_IPV6_IFNAME: + if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) + { + if (inet_ntop(AF_INET6, &nexthop->src.ipv6, addrstr, + sizeof addrstr)) + vty_out (vty, ", src %s", addrstr); + } + break; +#endif /* HAVE_IPV6 */ + default: + break; + } + vty_out (vty, "%s", VTY_NEWLINE); + } + vty_out (vty, "%s", VTY_NEWLINE); + } +} + +static void +vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib) +{ + struct nexthop *nexthop, *tnexthop; + int recursing; + int len = 0; + char buf[BUFSIZ]; + + /* Nexthop information. */ + for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) + { + if (nexthop == rib->nexthop) + { + /* Prefix information. */ + len = vty_out (vty, "%c", zebra_route_char (rib->type)); + if (rib->instance) + len += vty_out (vty, "[%d]", rib->instance); + len += vty_out (vty, "%c%c %s/%d", + CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) + ? '>' : ' ', + CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) + ? '*' : ' ', + inet_ntop (AF_INET, &rn->p.u.prefix, buf, BUFSIZ), + rn->p.prefixlen); + + /* Distance and metric display. */ + if (rib->type != ZEBRA_ROUTE_CONNECT + && rib->type != ZEBRA_ROUTE_KERNEL) + len += vty_out (vty, " [%d/%d]", rib->distance, + rib->metric); + + if (rib->vrf_id != VRF_DEFAULT) + len += vty_out (vty, " [vrf %u]", rib->vrf_id); + } + else + vty_out (vty, " %c%*c", + CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) + ? '*' : ' ', + len - 3 + (2 * recursing), ' '); + + switch (nexthop->type) + { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4)); + if (nexthop->ifindex) + vty_out (vty, ", %s", + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + break; +#ifdef HAVE_IPV6 + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + case NEXTHOP_TYPE_IPV6_IFNAME: + vty_out (vty, " via %s", + inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); + if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME) + vty_out (vty, ", %s", nexthop->ifname); + else if (nexthop->ifindex) + vty_out (vty, ", %s", + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + break; +#endif /* HAVE_IPV6 */ + + case NEXTHOP_TYPE_IFINDEX: + vty_out (vty, " is directly connected, %s", + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + break; + case NEXTHOP_TYPE_IFNAME: + vty_out (vty, " is directly connected, %s", nexthop->ifname); + break; + case NEXTHOP_TYPE_BLACKHOLE: + vty_out (vty, " is directly connected, Null0"); + break; + default: + break; + } + if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + vty_out (vty, " inactive"); + + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) + vty_out (vty, " onlink"); + + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + vty_out (vty, " (recursive)"); + + switch (nexthop->type) + { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFNAME: + if (nexthop->src.ipv4.s_addr) + { + if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, sizeof buf)) + vty_out (vty, ", src %s", buf); + } + break; +#ifdef HAVE_IPV6 + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + case NEXTHOP_TYPE_IPV6_IFNAME: + if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) + { + if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf, sizeof buf)) + vty_out (vty, ", src %s", buf); + } + break; +#endif /* HAVE_IPV6 */ + default: + break; + } + + if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE)) + vty_out (vty, ", bh"); + if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT)) + vty_out (vty, ", rej"); + + if (rib->type == ZEBRA_ROUTE_RIP + || rib->type == ZEBRA_ROUTE_OSPF + || rib->type == ZEBRA_ROUTE_BABEL + || rib->type == ZEBRA_ROUTE_ISIS + || rib->type == ZEBRA_ROUTE_TABLE + || rib->type == ZEBRA_ROUTE_BGP) + { + time_t uptime; + struct tm *tm; + + uptime = time (NULL); + uptime -= rib->uptime; + tm = gmtime (&uptime); + +#define ONE_DAY_SECOND 60*60*24 +#define ONE_WEEK_SECOND 60*60*24*7 + + if (uptime < ONE_DAY_SECOND) + vty_out (vty, ", %02d:%02d:%02d", + tm->tm_hour, tm->tm_min, tm->tm_sec); + else if (uptime < ONE_WEEK_SECOND) + vty_out (vty, ", %dd%02dh%02dm", + tm->tm_yday, tm->tm_hour, tm->tm_min); + else + vty_out (vty, ", %02dw%dd%02dh", + tm->tm_yday/7, + tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); + } + vty_out (vty, "%s", VTY_NEWLINE); + } +} + +DEFUN (show_ip_route, + show_ip_route_cmd, + "show ip route", + SHOW_STR + IP_STR + "IP routing table\n") +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + int first = 1; + + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (! table) + return CMD_SUCCESS; + + /* Show all IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + return CMD_SUCCESS; +} + +DEFUN (show_ip_nht, + show_ip_nht_cmd, + "show ip nht", + SHOW_STR + IP_STR + "IP nexthop tracking table\n") +{ + zebra_print_rnh_table(0, AF_INET, vty, RNH_NEXTHOP_TYPE); + return CMD_SUCCESS; +} + +DEFUN (show_ipv6_nht, + show_ipv6_nht_cmd, + "show ipv6 nht", + SHOW_STR + IP_STR + "IPv6 nexthop tracking table\n") +{ + zebra_print_rnh_table(0, AF_INET6, vty, RNH_NEXTHOP_TYPE); + return CMD_SUCCESS; +} + +DEFUN (ip_nht_default_route, + ip_nht_default_route_cmd, + "ip nht resolve-via-default", + IP_STR + "Filter Next Hop tracking route resolution\n" + "Resolve via default route\n") +{ + if (zebra_rnh_ip_default_route) + return CMD_SUCCESS; + + zebra_rnh_ip_default_route = 1; + zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + return CMD_SUCCESS; +} + +DEFUN (no_ip_nht_default_route, + no_ip_nht_default_route_cmd, + "no ip nht resolve-via-default", + NO_STR + IP_STR + "Filter Next Hop tracking route resolution\n" + "Resolve via default route\n") +{ + if (!zebra_rnh_ip_default_route) + return CMD_SUCCESS; + + zebra_rnh_ip_default_route = 0; + zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + return CMD_SUCCESS; +} + +DEFUN (ipv6_nht_default_route, + ipv6_nht_default_route_cmd, + "ipv6 nht resolve-via-default", + IP6_STR + "Filter Next Hop tracking route resolution\n" + "Resolve via default route\n") +{ + if (zebra_rnh_ipv6_default_route) + return CMD_SUCCESS; + + zebra_rnh_ipv6_default_route = 1; + zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + return CMD_SUCCESS; +} + +DEFUN (no_ipv6_nht_default_route, + no_ipv6_nht_default_route_cmd, + "no ipv6 nht resolve-via-default", + NO_STR + IP6_STR + "Filter Next Hop tracking route resolution\n" + "Resolve via default route\n") +{ + if (!zebra_rnh_ipv6_default_route) + return CMD_SUCCESS; + + zebra_rnh_ipv6_default_route = 0; + zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + return CMD_SUCCESS; +} + + +DEFUN (show_ip_route_tag, + show_ip_route_tag_cmd, + "show ip route tag <1-65535>", + SHOW_STR + IP_STR + "IP routing table\n" + "Show only routes with tag\n" + "Tag value\n") +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + int first = 1; + u_short tag = 0; + + if (argv[0]) + tag = atoi(argv[0]); + + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (! table) + return CMD_SUCCESS; + + /* Show all IPv4 routes with matching tag value. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + { + if (rib->tag != tag) + continue; + + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + return CMD_SUCCESS; +} + +ALIAS (show_ip_route, + show_ip_route_vrf_cmd, + "show ip route " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + VRF_CMD_HELP_STR) + +DEFUN (show_ip_route_prefix_longer, + show_ip_route_prefix_longer_cmd, + "show ip route A.B.C.D/M longer-prefixes", + SHOW_STR + IP_STR + "IP routing table\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + "Show route matching the specified Network/Mask pair only\n") +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + struct prefix p; + int ret; + int first = 1; + vrf_id_t vrf_id = VRF_DEFAULT; + + ret = str2prefix (argv[0], &p); + if (! ret) + { + vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); + if (! table) + return CMD_SUCCESS; + + /* Show matched type IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + if (prefix_match (&p, &rn->p)) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + return CMD_SUCCESS; +} + +ALIAS (show_ip_route_prefix_longer, + show_ip_route_prefix_longer_vrf_cmd, + "show ip route A.B.C.D/M longer-prefixes " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + "Show route matching the specified Network/Mask pair only\n" + VRF_CMD_HELP_STR) + +DEFUN (show_ip_route_supernets, + show_ip_route_supernets_cmd, + "show ip route supernets-only", + SHOW_STR + IP_STR + "IP routing table\n" + "Show supernet entries only\n") +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + u_int32_t addr; + int first = 1; + vrf_id_t vrf_id = VRF_DEFAULT; + + if (argc > 0) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); + if (! table) + return CMD_SUCCESS; + + /* Show matched type IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + { + addr = ntohl (rn->p.u.prefix4.s_addr); + + if ((IN_CLASSC (addr) && rn->p.prefixlen < 24) + || (IN_CLASSB (addr) && rn->p.prefixlen < 16) + || (IN_CLASSA (addr) && rn->p.prefixlen < 8)) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + } + return CMD_SUCCESS; +} + +ALIAS (show_ip_route_supernets, + show_ip_route_supernets_vrf_cmd, + "show ip route supernets-only " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "Show supernet entries only\n" + VRF_CMD_HELP_STR) + +DEFUN (show_ip_route_protocol, + show_ip_route_protocol_cmd, + "show ip route " QUAGGA_IP_REDIST_STR_ZEBRA, + SHOW_STR + IP_STR + "IP routing table\n" + QUAGGA_IP_REDIST_HELP_STR_ZEBRA) +{ + int type; + struct route_table *table; + struct route_node *rn; + struct rib *rib; + int first = 1; + vrf_id_t vrf_id = VRF_DEFAULT; + + type = proto_redistnum (AFI_IP, argv[0]); + if (type < 0) + { + vty_out (vty, "Unknown route type%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); + if (! table) + return CMD_SUCCESS; + + /* Show matched type IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + if (rib->type == type) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + return CMD_SUCCESS; +} + +ALIAS (show_ip_route_protocol, + show_ip_route_protocol_vrf_cmd, + "show ip route " QUAGGA_IP_REDIST_STR_ZEBRA " " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + QUAGGA_IP_REDIST_HELP_STR_ZEBRA + VRF_CMD_HELP_STR) + +DEFUN (show_ip_route_ospf_instance, + show_ip_route_ospf_instance_cmd, + "show ip route ospf <1-65535>", + SHOW_STR + IP_STR + "IP routing table\n" + "Open Shortest Path First (OSPFv2)\n" + "Instance ID\n") +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + int first = 1; + u_short instance = 0; + + VTY_GET_INTEGER ("Instance", instance, argv[0]); + + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (! table) + return CMD_SUCCESS; + + /* Show matched type IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + if (rib->type == ZEBRA_ROUTE_OSPF && rib->instance == instance) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + return CMD_SUCCESS; +} + +DEFUN (show_ip_route_addr, + show_ip_route_addr_cmd, + "show ip route A.B.C.D", + SHOW_STR + IP_STR + "IP routing table\n" + "Network in the IP routing table to display\n") +{ + int ret; + struct prefix_ipv4 p; + struct route_table *table; + struct route_node *rn; + vrf_id_t vrf_id = VRF_DEFAULT; + + ret = str2prefix_ipv4 (argv[0], &p); + if (ret <= 0) + { + vty_out (vty, "%% Malformed IPv4 address%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); + if (! table) + return CMD_SUCCESS; + + rn = route_node_match (table, (struct prefix *) &p); + if (! rn) + { + vty_out (vty, "%% Network not in table%s", VTY_NEWLINE); + return CMD_WARNING; + } + + vty_show_ip_route_detail (vty, rn); + + route_unlock_node (rn); + + return CMD_SUCCESS; +} + +ALIAS (show_ip_route_addr, + show_ip_route_addr_vrf_cmd, + "show ip route A.B.C.D " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "Network in the IP routing table to display\n" + VRF_CMD_HELP_STR) + +DEFUN (show_ip_route_prefix, + show_ip_route_prefix_cmd, + "show ip route A.B.C.D/M", + SHOW_STR + IP_STR + "IP routing table\n" + "IP prefix /, e.g., 35.0.0.0/8\n") +{ + int ret; + struct prefix_ipv4 p; + struct route_table *table; + struct route_node *rn; + vrf_id_t vrf_id = VRF_DEFAULT; + + ret = str2prefix_ipv4 (argv[0], &p); + if (ret <= 0) + { + vty_out (vty, "%% Malformed IPv4 address%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); + if (! table) + return CMD_SUCCESS; + + rn = route_node_match (table, (struct prefix *) &p); + if (! rn || rn->p.prefixlen != p.prefixlen) + { + vty_out (vty, "%% Network not in table%s", VTY_NEWLINE); + return CMD_WARNING; + } + + vty_show_ip_route_detail (vty, rn); + + route_unlock_node (rn); + + return CMD_SUCCESS; +} + +ALIAS (show_ip_route_prefix, + show_ip_route_prefix_vrf_cmd, + "show ip route A.B.C.D/M " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + VRF_CMD_HELP_STR) + +static void +vty_show_ip_route_summary (struct vty *vty, struct route_table *table) +{ + struct route_node *rn; + struct rib *rib; + struct nexthop *nexthop; +#define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX +#define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1) + u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1]; + u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1]; + u_int32_t i; + + memset (&rib_cnt, 0, sizeof(rib_cnt)); + memset (&fib_cnt, 0, sizeof(fib_cnt)); + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) + { + rib_cnt[ZEBRA_ROUTE_TOTAL]++; + rib_cnt[rib->type]++; + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) + || nexthop_has_fib_child(nexthop)) + { + fib_cnt[ZEBRA_ROUTE_TOTAL]++; + fib_cnt[rib->type]++; + } + if (rib->type == ZEBRA_ROUTE_BGP && + CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP)) + { + rib_cnt[ZEBRA_ROUTE_IBGP]++; + if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) + || nexthop_has_fib_child(nexthop)) + fib_cnt[ZEBRA_ROUTE_IBGP]++; + } + } + + vty_out (vty, "%-20s %-20s %s (vrf %u)%s", + "Route Source", "Routes", "FIB", + ((rib_table_info_t *)table->info)->zvrf->vrf_id, + VTY_NEWLINE); + + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + { + if (rib_cnt[i] > 0) + { + if (i == ZEBRA_ROUTE_BGP) + { + vty_out (vty, "%-20s %-20d %-20d %s", "ebgp", + rib_cnt[ZEBRA_ROUTE_BGP] - rib_cnt[ZEBRA_ROUTE_IBGP], + fib_cnt[ZEBRA_ROUTE_BGP] - fib_cnt[ZEBRA_ROUTE_IBGP], + VTY_NEWLINE); + vty_out (vty, "%-20s %-20d %-20d %s", "ibgp", + rib_cnt[ZEBRA_ROUTE_IBGP], fib_cnt[ZEBRA_ROUTE_IBGP], + VTY_NEWLINE); + } + else + vty_out (vty, "%-20s %-20d %-20d %s", zebra_route_string(i), + rib_cnt[i], fib_cnt[i], VTY_NEWLINE); + } + } + + vty_out (vty, "------%s", VTY_NEWLINE); + vty_out (vty, "%-20s %-20d %-20d %s", "Totals", rib_cnt[ZEBRA_ROUTE_TOTAL], + fib_cnt[ZEBRA_ROUTE_TOTAL], VTY_NEWLINE); + vty_out (vty, "%s", VTY_NEWLINE); +} + +/* + * Implementation of the ip route summary prefix command. + * + * This command prints the primary prefixes that have been installed by various + * protocols on the box. + * + */ +static void +vty_show_ip_route_summary_prefix (struct vty *vty, struct route_table *table) +{ + struct route_node *rn; + struct rib *rib; + struct nexthop *nexthop; +#define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX +#define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1) + u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1]; + u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1]; + u_int32_t i; + int cnt; + + memset (&rib_cnt, 0, sizeof(rib_cnt)); + memset (&fib_cnt, 0, sizeof(fib_cnt)); + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + { + + /* + * In case of ECMP, count only once. + */ + cnt = 0; + for (nexthop = rib->nexthop; (!cnt && nexthop); nexthop = nexthop->next) + { + cnt++; + rib_cnt[ZEBRA_ROUTE_TOTAL]++; + rib_cnt[rib->type]++; if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) { fib_cnt[ZEBRA_ROUTE_TOTAL]++; @@ -1879,45 +2717,138 @@ DEFUN (show_ip_route_vrf_all, (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) continue; - /* Show all IPv4 routes. */ + /* Show all IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + } + + return CMD_SUCCESS; +} + +DEFUN (show_ip_route_prefix_longer_vrf_all, + show_ip_route_prefix_longer_vrf_all_cmd, + "show ip route A.B.C.D/M longer-prefixes " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + "Show route matching the specified Network/Mask pair only\n" + VRF_ALL_CMD_HELP_STR) +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + struct prefix p; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + int ret; + int first = 1; + + ret = str2prefix (argv[0], &p); + if (! ret) + { + vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) + continue; + + /* Show matched type IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + if (prefix_match (&p, &rn->p)) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + } + + return CMD_SUCCESS; +} + +DEFUN (show_ip_route_supernets_vrf_all, + show_ip_route_supernets_vrf_all_cmd, + "show ip route supernets-only " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "Show supernet entries only\n" + VRF_ALL_CMD_HELP_STR) +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + u_int32_t addr; + int first = 1; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) + continue; + + /* Show matched type IPv4 routes. */ for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB (rn, rib) { - if (first) + addr = ntohl (rn->p.u.prefix4.s_addr); + + if ((IN_CLASSC (addr) && rn->p.prefixlen < 24) + || (IN_CLASSB (addr) && rn->p.prefixlen < 16) + || (IN_CLASSA (addr) && rn->p.prefixlen < 8)) { - vty_out (vty, SHOW_ROUTE_V4_HEADER); - first = 0; + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); } - vty_show_ip_route (vty, rn, rib); } } return CMD_SUCCESS; } -DEFUN (show_ip_route_prefix_longer_vrf_all, - show_ip_route_prefix_longer_vrf_all_cmd, - "show ip route A.B.C.D/M longer-prefixes " VRF_ALL_CMD_STR, +DEFUN (show_ip_route_protocol_vrf_all, + show_ip_route_protocol_vrf_all_cmd, + "show ip route " QUAGGA_IP_REDIST_STR_ZEBRA " " VRF_ALL_CMD_STR, SHOW_STR IP_STR "IP routing table\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Show route matching the specified Network/Mask pair only\n" + QUAGGA_IP_REDIST_HELP_STR_ZEBRA VRF_ALL_CMD_HELP_STR) { + int type; struct route_table *table; struct route_node *rn; struct rib *rib; - struct prefix p; struct zebra_vrf *zvrf; vrf_iter_t iter; - int ret; int first = 1; - ret = str2prefix (argv[0], &p); - if (! ret) + type = proto_redistnum (AFI_IP, argv[0]); + if (type < 0) { - vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE); + vty_out (vty, "Unknown route type%s", VTY_NEWLINE); return CMD_WARNING; } @@ -1930,7 +2861,7 @@ DEFUN (show_ip_route_prefix_longer_vrf_all, /* Show matched type IPv4 routes. */ for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB (rn, rib) - if (prefix_match (&p, &rn->p)) + if (rib->type == type) { if (first) { @@ -1944,22 +2875,28 @@ DEFUN (show_ip_route_prefix_longer_vrf_all, return CMD_SUCCESS; } -DEFUN (show_ip_route_supernets_vrf_all, - show_ip_route_supernets_vrf_all_cmd, - "show ip route supernets-only " VRF_ALL_CMD_STR, +DEFUN (show_ip_route_addr_vrf_all, + show_ip_route_addr_vrf_all_cmd, + "show ip route A.B.C.D " VRF_ALL_CMD_STR, SHOW_STR IP_STR "IP routing table\n" - "Show supernet entries only\n" + "Network in the IP routing table to display\n" VRF_ALL_CMD_HELP_STR) { + int ret; + struct prefix_ipv4 p; struct route_table *table; struct route_node *rn; - struct rib *rib; struct zebra_vrf *zvrf; vrf_iter_t iter; - u_int32_t addr; - int first = 1; + + ret = str2prefix_ipv4 (argv[0], &p); + if (ret <= 0) + { + vty_out (vty, "%% Malformed IPv4 address%s", VTY_NEWLINE); + return CMD_WARNING; + } for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) { @@ -1967,39 +2904,222 @@ DEFUN (show_ip_route_supernets_vrf_all, (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) continue; - /* Show matched type IPv4 routes. */ - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RIB (rn, rib) + rn = route_node_match (table, (struct prefix *) &p); + if (! rn) + continue; + + vty_show_ip_route_detail (vty, rn); + + route_unlock_node (rn); + } + + return CMD_SUCCESS; +} + +DEFUN (show_ip_route_prefix_vrf_all, + show_ip_route_prefix_vrf_all_cmd, + "show ip route A.B.C.D/M " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + VRF_ALL_CMD_HELP_STR) +{ + int ret; + struct prefix_ipv4 p; + struct route_table *table; + struct route_node *rn; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + + ret = str2prefix_ipv4 (argv[0], &p); + if (ret <= 0) + { + vty_out (vty, "%% Malformed IPv4 address%s", VTY_NEWLINE); + return CMD_WARNING; + } + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) + continue; + + rn = route_node_match (table, (struct prefix *) &p); + if (! rn) + continue; + if (rn->p.prefixlen != p.prefixlen) + { + route_unlock_node (rn); + continue; + } + + vty_show_ip_route_detail (vty, rn); + + route_unlock_node (rn); + } + + return CMD_SUCCESS; +} + +DEFUN (show_ip_route_summary_vrf_all, + show_ip_route_summary_vrf_all_cmd, + "show ip route summary " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "Summary of all routes\n" + VRF_ALL_CMD_HELP_STR) +{ + struct zebra_vrf *zvrf; + vrf_iter_t iter; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + if ((zvrf = vrf_iter2info (iter)) != NULL) + vty_show_ip_route_summary (vty, zvrf->table[AFI_IP][SAFI_UNICAST]); + + return CMD_SUCCESS; +} + +DEFUN (show_ip_route_summary_prefix_vrf_all, + show_ip_route_summary_prefix_vrf_all_cmd, + "show ip route summary prefix " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "Summary of all routes\n" + "Prefix routes\n" + VRF_ALL_CMD_HELP_STR) +{ + struct zebra_vrf *zvrf; + vrf_iter_t iter; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + if ((zvrf = vrf_iter2info (iter)) != NULL) + vty_show_ip_route_summary_prefix (vty, zvrf->table[AFI_IP][SAFI_UNICAST]); + + return CMD_SUCCESS; +} + +/* Write IPv4 static route configuration. */ +static int +static_config_ipv4 (struct vty *vty, safi_t safi, const char *cmd) +{ + struct route_node *rn; + struct static_ipv4 *si; + struct route_table *stable; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + int write; + + write = 0; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (stable = zvrf->stable[AFI_IP][safi]) == NULL) + continue; + + for (rn = route_top (stable); rn; rn = route_next (rn)) + for (si = rn->info; si; si = si->next) { - addr = ntohl (rn->p.u.prefix4.s_addr); + vty_out (vty, "%s %s/%d", cmd, inet_ntoa (rn->p.u.prefix4), + rn->p.prefixlen); - if ((IN_CLASSC (addr) && rn->p.prefixlen < 24) - || (IN_CLASSB (addr) && rn->p.prefixlen < 16) - || (IN_CLASSA (addr) && rn->p.prefixlen < 8)) + switch (si->type) { - if (first) - { - vty_out (vty, SHOW_ROUTE_V4_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, rib); + case STATIC_IPV4_GATEWAY: + vty_out (vty, " %s", inet_ntoa (si->gate.ipv4)); + break; + case STATIC_IPV4_IFNAME: + vty_out (vty, " %s", si->gate.ifname); + break; + case STATIC_IPV4_BLACKHOLE: + vty_out (vty, " Null0"); + break; + } + + /* flags are incompatible with STATIC_IPV4_BLACKHOLE */ + if (si->type != STATIC_IPV4_BLACKHOLE) + { + if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT)) + vty_out (vty, " %s", "reject"); + + if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE)) + vty_out (vty, " %s", "blackhole"); } + + if (si->tag) + vty_out (vty, " tag %d", si->tag); + + if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) + vty_out (vty, " %d", si->distance); + + if (si->vrf_id != VRF_DEFAULT) + vty_out (vty, " vrf %u", si->vrf_id); + + vty_out (vty, "%s", VTY_NEWLINE); + + write = 1; } } + return write; +} + +/* + * Show IP mroute command to dump the BGP Multicast + * routing table + */ +DEFUN (show_ip_mroute, + show_ip_mroute_cmd, + "show ip mroute", + SHOW_STR + IP_STR + "IP Multicast routing table\n") +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + int first = 1; + vrf_id_t vrf_id = VRF_DEFAULT; + + if (argc > 0) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + table = zebra_vrf_table (AFI_IP, SAFI_MULTICAST, vrf_id); + if (! table) + return CMD_SUCCESS; + + /* Show all IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } return CMD_SUCCESS; } -DEFUN (show_ip_route_protocol_vrf_all, - show_ip_route_protocol_vrf_all_cmd, - "show ip route " QUAGGA_IP_REDIST_STR_ZEBRA " " VRF_ALL_CMD_STR, +ALIAS (show_ip_mroute, + show_ip_mroute_vrf_cmd, + "show ip mroute " VRF_CMD_STR, SHOW_STR IP_STR - "IP routing table\n" - QUAGGA_IP_REDIST_HELP_STR_ZEBRA + "IP Multicast routing table\n" + VRF_CMD_HELP_STR) + +DEFUN (show_ip_mroute_vrf_all, + show_ip_mroute_vrf_all_cmd, + "show ip mroute " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IP Multicast routing table\n" VRF_ALL_CMD_HELP_STR) { - int type; struct route_table *table; struct route_node *rn; struct rib *rib; @@ -2007,442 +3127,640 @@ DEFUN (show_ip_route_protocol_vrf_all, vrf_iter_t iter; int first = 1; - type = proto_redistnum (AFI_IP, argv[0]); - if (type < 0) - { - vty_out (vty, "Unknown route type%s", VTY_NEWLINE); - return CMD_WARNING; - } - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) { if ((zvrf = vrf_iter2info (iter)) == NULL || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) continue; - /* Show matched type IPv4 routes. */ + /* Show all IPv4 routes. */ for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB (rn, rib) - if (rib->type == type) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V4_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, rib); - } + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } } return CMD_SUCCESS; } -DEFUN (show_ip_route_addr_vrf_all, - show_ip_route_addr_vrf_all_cmd, - "show ip route A.B.C.D " VRF_ALL_CMD_STR, - SHOW_STR - IP_STR - "IP routing table\n" - "Network in the IP routing table to display\n" - VRF_ALL_CMD_HELP_STR) +#ifdef HAVE_IPV6 +/* General fucntion for IPv6 static route. */ +static int +static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, + const char *gate_str, const char *ifname, + const char *flag_str, const char *tag_str, + const char *distance_str, const char *vrf_id_str) { int ret; - struct prefix_ipv4 p; - struct route_table *table; - struct route_node *rn; - struct zebra_vrf *zvrf; - vrf_iter_t iter; - - ret = str2prefix_ipv4 (argv[0], &p); + u_char distance; + struct prefix p; + struct in6_addr *gate = NULL; + struct in6_addr gate_addr; + u_char type = 0; + vrf_id_t vrf_id = VRF_DEFAULT; + u_char flag = 0; + u_short tag = 0; + + ret = str2prefix (dest_str, &p); if (ret <= 0) { - vty_out (vty, "%% Malformed IPv4 address%s", VTY_NEWLINE); + vty_out (vty, "%% Malformed address%s", VTY_NEWLINE); return CMD_WARNING; } - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - { - if ((zvrf = vrf_iter2info (iter)) == NULL || - (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) - continue; + /* Apply mask for given prefix. */ + apply_mask (&p); - rn = route_node_match (table, (struct prefix *) &p); - if (! rn) - continue; + /* Route flags */ + if (flag_str) { + switch(flag_str[0]) { + case 'r': + case 'R': /* XXX */ + SET_FLAG (flag, ZEBRA_FLAG_REJECT); + break; + case 'b': + case 'B': /* XXX */ + SET_FLAG (flag, ZEBRA_FLAG_BLACKHOLE); + break; + default: + vty_out (vty, "%% Malformed flag %s %s", flag_str, VTY_NEWLINE); + return CMD_WARNING; + } + } - vty_show_ip_route_detail (vty, rn); + /* Administrative distance. */ + if (distance_str) + distance = atoi (distance_str); + else + distance = ZEBRA_STATIC_DISTANCE_DEFAULT; - route_unlock_node (rn); + /* tag */ + if (tag_str) + tag = atoi(tag_str); + + /* When gateway is valid IPv6 addrees, then gate is treated as + nexthop address other case gate is treated as interface name. */ + ret = inet_pton (AF_INET6, gate_str, &gate_addr); + + if (ifname) + { + /* When ifname is specified. It must be come with gateway + address. */ + if (ret != 1) + { + vty_out (vty, "%% Malformed address%s", VTY_NEWLINE); + return CMD_WARNING; + } + type = STATIC_IPV6_GATEWAY_IFNAME; + gate = &gate_addr; + } + else + { + if (ret == 1) + { + type = STATIC_IPV6_GATEWAY; + gate = &gate_addr; + } + else + { + type = STATIC_IPV6_IFNAME; + ifname = gate_str; + } } + /* VRF id */ + if (vrf_id_str) + VTY_GET_INTEGER ("VRF ID", vrf_id, vrf_id_str); + + if (add_cmd) + static_add_ipv6 (&p, type, gate, ifname, flag, tag, distance, vrf_id); + else + static_delete_ipv6 (&p, type, gate, ifname, tag, distance, vrf_id); + return CMD_SUCCESS; } -DEFUN (show_ip_route_prefix_vrf_all, - show_ip_route_prefix_vrf_all_cmd, - "show ip route A.B.C.D/M " VRF_ALL_CMD_STR, - SHOW_STR +DEFUN (ipv6_route, + ipv6_route_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)", IP_STR - "IP routing table\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - VRF_ALL_CMD_HELP_STR) + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n") { - int ret; - struct prefix_ipv4 p; - struct route_table *table; - struct route_node *rn; - struct zebra_vrf *zvrf; - vrf_iter_t iter; - - ret = str2prefix_ipv4 (argv[0], &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed IPv4 address%s", VTY_NEWLINE); - return CMD_WARNING; - } - - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - { - if ((zvrf = vrf_iter2info (iter)) == NULL || - (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) - continue; + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL, NULL, NULL); +} - rn = route_node_match (table, (struct prefix *) &p); - if (! rn) - continue; - if (rn->p.prefixlen != p.prefixlen) - { - route_unlock_node (rn); - continue; - } +DEFUN (ipv6_route_tag, + ipv6_route_tag_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2], NULL, NULL); +} - vty_show_ip_route_detail (vty, rn); +DEFUN (ipv6_route_flags, + ipv6_route_flags_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole)", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, NULL, NULL); +} - route_unlock_node (rn); - } +DEFUN (ipv6_route_flags_tag, + ipv6_route_flags_tag_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], NULL, NULL); +} - return CMD_SUCCESS; +DEFUN (ipv6_route_ifname, + ipv6_route_ifname_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, NULL, NULL); +} +DEFUN (ipv6_route_ifname_tag, + ipv6_route_ifname_tag_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], NULL, NULL); } -DEFUN (show_ip_route_summary_vrf_all, - show_ip_route_summary_vrf_all_cmd, - "show ip route summary " VRF_ALL_CMD_STR, - SHOW_STR +DEFUN (ipv6_route_ifname_flags, + ipv6_route_ifname_flags_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole)", IP_STR - "IP routing table\n" - "Summary of all routes\n" - VRF_ALL_CMD_HELP_STR) + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n") { - struct zebra_vrf *zvrf; - vrf_iter_t iter; - - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - if ((zvrf = vrf_iter2info (iter)) != NULL) - vty_show_ip_route_summary (vty, zvrf->table[AFI_IP][SAFI_UNICAST]); - - return CMD_SUCCESS; + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, NULL, NULL); } -DEFUN (show_ip_route_summary_prefix_vrf_all, - show_ip_route_summary_prefix_vrf_all_cmd, - "show ip route summary prefix " VRF_ALL_CMD_STR, - SHOW_STR +DEFUN (ipv6_route_ifname_flags_tag, + ipv6_route_ifname_flags_tag_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535>", IP_STR - "IP routing table\n" - "Summary of all routes\n" - "Prefix routes\n" - VRF_ALL_CMD_HELP_STR) + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n") { - struct zebra_vrf *zvrf; - vrf_iter_t iter; + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], NULL, NULL); +} - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - if ((zvrf = vrf_iter2info (iter)) != NULL) - vty_show_ip_route_summary_prefix (vty, zvrf->table[AFI_IP][SAFI_UNICAST]); +DEFUN (ipv6_route_pref, + ipv6_route_pref_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Distance value for this prefix\n") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL, argv[2], NULL); +} - return CMD_SUCCESS; +DEFUN (ipv6_route_pref_tag, + ipv6_route_pref_tag_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535> <1-255>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2], argv[3], NULL); } -/* Write IPv4 static route configuration. */ -static int -static_config_ipv4 (struct vty *vty, safi_t safi, const char *cmd) +DEFUN (ipv6_route_flags_pref, + ipv6_route_flags_pref_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) <1-255>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this prefix\n") { - struct route_node *rn; - struct static_ipv4 *si; - struct route_table *stable; - struct zebra_vrf *zvrf; - vrf_iter_t iter; - int write; + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, argv[3], NULL); +} - write = 0; +DEFUN (ipv6_route_flags_pref_tag, + ipv6_route_flags_pref_tag_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], argv[4], NULL); +} - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - { - if ((zvrf = vrf_iter2info (iter)) == NULL || - (stable = zvrf->stable[AFI_IP][safi]) == NULL) - continue; +DEFUN (ipv6_route_ifname_pref, + ipv6_route_ifname_pref_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Distance value for this prefix\n") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, argv[3], NULL); +} - for (rn = route_top (stable); rn; rn = route_next (rn)) - for (si = rn->info; si; si = si->next) - { - vty_out (vty, "%s %s/%d", cmd, inet_ntoa (rn->p.u.prefix4), - rn->p.prefixlen); +DEFUN (ipv6_route_ifname_pref_tag, + ipv6_route_ifname_pref_tag_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535> <1-255>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], argv[4], NULL); +} - switch (si->type) - { - case STATIC_IPV4_GATEWAY: - vty_out (vty, " %s", inet_ntoa (si->gate.ipv4)); - break; - case STATIC_IPV4_IFNAME: - vty_out (vty, " %s", si->gate.ifname); - break; - case STATIC_IPV4_BLACKHOLE: - vty_out (vty, " Null0"); - break; - } +DEFUN (ipv6_route_ifname_flags_pref, + ipv6_route_ifname_flags_pref_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) <1-255>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this prefix\n") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, argv[4], NULL); +} - /* flags are incompatible with STATIC_IPV4_BLACKHOLE */ - if (si->type != STATIC_IPV4_BLACKHOLE) - { - if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, " %s", "reject"); +DEFUN (ipv6_route_ifname_flags_pref_tag, + ipv6_route_ifname_flags_pref_tag_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535> <1-255>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], NULL); +} - if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, " %s", "blackhole"); - } +DEFUN (no_ipv6_route, + no_ipv6_route_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n") +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL, NULL, NULL); +} - if (si->tag) - vty_out (vty, " tag %d", si->tag); +DEFUN (no_ipv6_route_tag, + no_ipv6_route_tag_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n") +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], NULL, NULL); +} - if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) - vty_out (vty, " %d", si->distance); +ALIAS (no_ipv6_route, + no_ipv6_route_flags_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole)", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n") - vty_out (vty, "%s", VTY_NEWLINE); +ALIAS (no_ipv6_route_tag, + no_ipv6_route_flags_tag_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n") - write = 1; - } - } - return write; +DEFUN (no_ipv6_route_ifname, + no_ipv6_route_ifname_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n") +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, NULL, NULL); } -/* - * Show IP mroute command to dump the BGP Multicast - * routing table - */ -DEFUN (show_ip_mroute, - show_ip_mroute_cmd, - "show ip mroute", - SHOW_STR +DEFUN (no_ipv6_route_ifname_tag, + no_ipv6_route_ifname_tag_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535>", + NO_STR IP_STR - "IP Multicast routing table\n") + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n") { - struct route_table *table; - struct route_node *rn; - struct rib *rib; - int first = 1; - vrf_id_t vrf_id = VRF_DEFAULT; + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], NULL, NULL); +} - if (argc > 0) - VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); +ALIAS (no_ipv6_route_ifname, + no_ipv6_route_ifname_flags_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole)", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n") - table = zebra_vrf_table (AFI_IP, SAFI_MULTICAST, vrf_id); - if (! table) - return CMD_SUCCESS; +ALIAS (no_ipv6_route_ifname_tag, + no_ipv6_route_ifname_flags_tag_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n") - /* Show all IPv4 routes. */ - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RIB (rn, rib) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V4_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, rib); - } - return CMD_SUCCESS; +DEFUN (no_ipv6_route_pref, + no_ipv6_route_pref_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Distance value for this prefix\n") +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL, argv[2], NULL); } -ALIAS (show_ip_mroute, - show_ip_mroute_vrf_cmd, - "show ip mroute " VRF_CMD_STR, - SHOW_STR +DEFUN (no_ipv6_route_pref_tag, + no_ipv6_route_pref_tag_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535> <1-255>", + NO_STR IP_STR - "IP Multicast routing table\n" - VRF_CMD_HELP_STR) + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n") +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], argv[3], NULL); +} -DEFUN (show_ip_mroute_vrf_all, - show_ip_mroute_vrf_all_cmd, - "show ip mroute " VRF_ALL_CMD_STR, - SHOW_STR +DEFUN (no_ipv6_route_flags_pref, + no_ipv6_route_flags_pref_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) <1-255>", + NO_STR IP_STR - "IP Multicast routing table\n" - VRF_ALL_CMD_HELP_STR) + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this prefix\n") { - struct route_table *table; - struct route_node *rn; - struct rib *rib; - struct zebra_vrf *zvrf; - vrf_iter_t iter; - int first = 1; - - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - { - if ((zvrf = vrf_iter2info (iter)) == NULL || - (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) - continue; - - /* Show all IPv4 routes. */ - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RIB (rn, rib) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V4_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, rib); - } - } - - return CMD_SUCCESS; + /* We do not care about argv[2] */ + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], NULL, argv[3], NULL); } -#ifdef HAVE_IPV6 -/* General fucntion for IPv6 static route. */ -static int -static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, - const char *gate_str, const char *ifname, - const char *flag_str, const char *tag_str, - const char *distance_str) +DEFUN (no_ipv6_route_flags_pref_tag, + no_ipv6_route_flags_pref_tag_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n") { - int ret; - u_char distance; - struct prefix p; - struct in6_addr *gate = NULL; - struct in6_addr gate_addr; - u_char type = 0; - u_char flag = 0; - u_short tag = 0; - - ret = str2prefix (dest_str, &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address%s", VTY_NEWLINE); - return CMD_WARNING; - } - - /* Apply mask for given prefix. */ - apply_mask (&p); - - /* Route flags */ - if (flag_str) { - switch(flag_str[0]) { - case 'r': - case 'R': /* XXX */ - SET_FLAG (flag, ZEBRA_FLAG_REJECT); - break; - case 'b': - case 'B': /* XXX */ - SET_FLAG (flag, ZEBRA_FLAG_BLACKHOLE); - break; - default: - vty_out (vty, "%% Malformed flag %s %s", flag_str, VTY_NEWLINE); - return CMD_WARNING; - } - } - - /* Administrative distance. */ - if (distance_str) - distance = atoi (distance_str); - else - distance = ZEBRA_STATIC_DISTANCE_DEFAULT; - - /* tag */ - if (tag_str) - tag = atoi(tag_str); + /* We do not care about argv[2] */ + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3], argv[4], NULL); +} - /* When gateway is valid IPv6 addrees, then gate is treated as - nexthop address other case gate is treated as interface name. */ - ret = inet_pton (AF_INET6, gate_str, &gate_addr); +DEFUN (no_ipv6_route_ifname_pref, + no_ipv6_route_ifname_pref_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Distance value for this prefix\n") +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, argv[3], NULL); +} - if (ifname) - { - /* When ifname is specified. It must be come with gateway - address. */ - if (ret != 1) - { - vty_out (vty, "%% Malformed address%s", VTY_NEWLINE); - return CMD_WARNING; - } - type = STATIC_IPV6_GATEWAY_IFNAME; - gate = &gate_addr; - } - else - { - if (ret == 1) - { - type = STATIC_IPV6_GATEWAY; - gate = &gate_addr; - } - else - { - type = STATIC_IPV6_IFNAME; - ifname = gate_str; - } - } +DEFUN (no_ipv6_route_ifname_pref_tag, + no_ipv6_route_ifname_pref_tag_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535> <1-255>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n") +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], argv[4], NULL); +} - if (add_cmd) - static_add_ipv6 (&p, type, gate, ifname, flag, tag, distance, VRF_DEFAULT); - else - static_delete_ipv6 (&p, type, gate, ifname, tag, distance, VRF_DEFAULT); +DEFUN (no_ipv6_route_ifname_flags_pref, + no_ipv6_route_ifname_flags_pref_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) <1-255>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this prefix\n") +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], NULL, argv[4], NULL); +} - return CMD_SUCCESS; +DEFUN (no_ipv6_route_ifname_flags_pref_tag, + no_ipv6_route_ifname_flags_pref_tag_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535> <1-255>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n") +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], NULL); } -DEFUN (ipv6_route, - ipv6_route_cmd, - "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)", +DEFUN (ipv6_route_vrf, + ipv6_route_vrf_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)" VRF_CMD_STR, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 gateway address\n" - "IPv6 gateway interface name\n") + "IPv6 gateway interface name\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL, NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL, NULL, argv[2]); } -DEFUN (ipv6_route_tag, - ipv6_route_tag_cmd, - "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535>", +DEFUN (ipv6_route_tag_vrf, + ipv6_route_tag_vrf_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535>" VRF_CMD_STR, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 gateway address\n" "IPv6 gateway interface name\n" "Set tag for this route\n" - "Tag value\n") + "Tag value\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2], NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2], NULL, argv[3]); } -DEFUN (ipv6_route_flags, - ipv6_route_flags_cmd, - "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole)", +DEFUN (ipv6_route_flags_vrf, + ipv6_route_flags_vrf_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole)" VRF_CMD_STR, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 gateway address\n" "IPv6 gateway interface name\n" "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, NULL, argv[3]); } -DEFUN (ipv6_route_flags_tag, - ipv6_route_flags_tag_cmd, - "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535>", +DEFUN (ipv6_route_flags_tag_vrf, + ipv6_route_flags_tag_vrf_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535>" VRF_CMD_STR, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" @@ -2451,53 +3769,57 @@ DEFUN (ipv6_route_flags_tag, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n" "Set tag for this route\n" - "Tag value\n") + "Tag value\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], NULL, argv[4]); } -DEFUN (ipv6_route_ifname, - ipv6_route_ifname_cmd, - "ipv6 route X:X::X:X/M X:X::X:X INTERFACE", +DEFUN (ipv6_route_ifname_vrf, + ipv6_route_ifname_vrf_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE" VRF_CMD_STR, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 gateway address\n" - "IPv6 gateway interface name\n") + "IPv6 gateway interface name\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, NULL, argv[3]); } -DEFUN (ipv6_route_ifname_tag, - ipv6_route_ifname_tag_cmd, - "ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535>", +DEFUN (ipv6_route_ifname_tag_vrf, + ipv6_route_ifname_tag_vrf_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535>" VRF_CMD_STR, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 gateway address\n" "IPv6 gateway interface name\n" "Set tag for this route\n" - "Tag value\n") + "Tag value\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], NULL, argv[4]); } -DEFUN (ipv6_route_ifname_flags, - ipv6_route_ifname_flags_cmd, - "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole)", +DEFUN (ipv6_route_ifname_flags_vrf, + ipv6_route_ifname_flags_vrf_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole)" VRF_CMD_STR, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 gateway address\n" "IPv6 gateway interface name\n" "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, NULL, argv[4]); } -DEFUN (ipv6_route_ifname_flags_tag, - ipv6_route_ifname_flags_tag_cmd, - "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535>", +DEFUN (ipv6_route_ifname_flags_tag_vrf, + ipv6_route_ifname_flags_tag_vrf_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535>" VRF_CMD_STR, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" @@ -2506,27 +3828,29 @@ DEFUN (ipv6_route_ifname_flags_tag, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n" "Set tag for this route\n" - "Tag value\n") + "Tag value\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], NULL, argv[5]); } -DEFUN (ipv6_route_pref, - ipv6_route_pref_cmd, - "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>", +DEFUN (ipv6_route_pref_vrf, + ipv6_route_pref_vrf_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>" VRF_CMD_STR, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 gateway address\n" "IPv6 gateway interface name\n" - "Distance value for this prefix\n") + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL, argv[2]); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL, argv[2], argv[3]); } -DEFUN (ipv6_route_pref_tag, - ipv6_route_pref_tag_cmd, - "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535> <1-255>", +DEFUN (ipv6_route_pref_tag_vrf, + ipv6_route_pref_tag_vrf_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535> <1-255>" VRF_CMD_STR, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" @@ -2534,14 +3858,15 @@ DEFUN (ipv6_route_pref_tag, "IPv6 gateway interface name\n" "Set tag for this route\n" "Tag value\n" - "Distance value for this prefix\n") + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2], argv[3]); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2], argv[3], argv[4]); } -DEFUN (ipv6_route_flags_pref, - ipv6_route_flags_pref_cmd, - "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) <1-255>", +DEFUN (ipv6_route_flags_pref_vrf, + ipv6_route_flags_pref_vrf_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) <1-255>" VRF_CMD_STR, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" @@ -2549,14 +3874,15 @@ DEFUN (ipv6_route_flags_pref, "IPv6 gateway interface name\n" "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n" - "Distance value for this prefix\n") + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, argv[3]); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, argv[3], argv[4]); } -DEFUN (ipv6_route_flags_pref_tag, - ipv6_route_flags_pref_tag_cmd, - "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>", +DEFUN (ipv6_route_flags_pref_tag_vrf, + ipv6_route_flags_pref_tag_vrf_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" @@ -2566,27 +3892,29 @@ DEFUN (ipv6_route_flags_pref_tag, "Silently discard pkts when matched\n" "Set tag for this route\n" "Tag value\n" - "Distance value for this prefix\n") + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], argv[4]); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], argv[4], argv[5]); } -DEFUN (ipv6_route_ifname_pref, - ipv6_route_ifname_pref_cmd, - "ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>", +DEFUN (ipv6_route_ifname_pref_vrf, + ipv6_route_ifname_pref_vrf_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>" VRF_CMD_STR, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 gateway address\n" "IPv6 gateway interface name\n" - "Distance value for this prefix\n") + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, argv[3]); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, argv[3], argv[4]); } -DEFUN (ipv6_route_ifname_pref_tag, - ipv6_route_ifname_pref_tag_cmd, - "ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535> <1-255>", +DEFUN (ipv6_route_ifname_pref_tag_vrf, + ipv6_route_ifname_pref_tag_vrf_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535> <1-255>" VRF_CMD_STR, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" @@ -2594,14 +3922,15 @@ DEFUN (ipv6_route_ifname_pref_tag, "IPv6 gateway interface name\n" "Set tag for this route\n" "Tag value\n" - "Distance value for this prefix\n") + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], argv[4]); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], argv[4], argv[5]); } -DEFUN (ipv6_route_ifname_flags_pref, - ipv6_route_ifname_flags_pref_cmd, - "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) <1-255>", +DEFUN (ipv6_route_ifname_flags_pref_vrf, + ipv6_route_ifname_flags_pref_vrf_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) <1-255>" VRF_CMD_STR, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" @@ -2609,14 +3938,15 @@ DEFUN (ipv6_route_ifname_flags_pref, "IPv6 gateway interface name\n" "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n" - "Distance value for this prefix\n") + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, argv[4]); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, argv[4], argv[5]); } -DEFUN (ipv6_route_ifname_flags_pref_tag, - ipv6_route_ifname_flags_pref_tag_cmd, - "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535> <1-255>", +DEFUN (ipv6_route_ifname_flags_pref_tag_vrf, + ipv6_route_ifname_flags_pref_tag_vrf_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" @@ -2626,27 +3956,29 @@ DEFUN (ipv6_route_ifname_flags_pref_tag, "Silently discard pkts when matched\n" "Set tag for this route\n" "Tag value\n" - "Distance value for this prefix\n") + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); } -DEFUN (no_ipv6_route, - no_ipv6_route_cmd, - "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)", +DEFUN (no_ipv6_route_vrf, + no_ipv6_route_vrf_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)" VRF_CMD_STR, NO_STR IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 gateway address\n" - "IPv6 gateway interface name\n") + "IPv6 gateway interface name\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL, NULL); + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL, NULL, argv[2]); } -DEFUN (no_ipv6_route_tag, - no_ipv6_route_tag_cmd, - "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535>", +DEFUN (no_ipv6_route_tag_vrf, + no_ipv6_route_tag_vrf_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535>" VRF_CMD_STR, NO_STR IP_STR "Establish static routes\n" @@ -2654,14 +3986,15 @@ DEFUN (no_ipv6_route_tag, "IPv6 gateway address\n" "IPv6 gateway interface name\n" "Set tag for this route\n" - "Tag value\n") + "Tag value\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], NULL); + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], NULL, argv[3]); } -ALIAS (no_ipv6_route, - no_ipv6_route_flags_cmd, - "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole)", +ALIAS (no_ipv6_route_vrf, + no_ipv6_route_flags_vrf_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole)" VRF_CMD_STR, NO_STR IP_STR "Establish static routes\n" @@ -2669,11 +4002,12 @@ ALIAS (no_ipv6_route, "IPv6 gateway address\n" "IPv6 gateway interface name\n" "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) -ALIAS (no_ipv6_route_tag, - no_ipv6_route_flags_tag_cmd, - "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535>", +ALIAS (no_ipv6_route_tag_vrf, + no_ipv6_route_flags_tag_vrf_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535>" VRF_CMD_STR, NO_STR IP_STR "Establish static routes\n" @@ -2683,24 +4017,26 @@ ALIAS (no_ipv6_route_tag, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n" "Set tag for this route\n" - "Tag value\n") + "Tag value\n" + VRF_CMD_HELP_STR) -DEFUN (no_ipv6_route_ifname, - no_ipv6_route_ifname_cmd, - "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE", +DEFUN (no_ipv6_route_ifname_vrf, + no_ipv6_route_ifname_vrf_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE" VRF_CMD_STR, NO_STR IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 gateway address\n" - "IPv6 gateway interface name\n") + "IPv6 gateway interface name\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, NULL); + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, NULL, argv[3]); } -DEFUN (no_ipv6_route_ifname_tag, - no_ipv6_route_ifname_tag_cmd, - "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535>", +DEFUN (no_ipv6_route_ifname_tag_vrf, + no_ipv6_route_ifname_tag_vrf_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535>" VRF_CMD_STR, NO_STR IP_STR "Establish static routes\n" @@ -2708,14 +4044,15 @@ DEFUN (no_ipv6_route_ifname_tag, "IPv6 gateway address\n" "IPv6 gateway interface name\n" "Set tag for this route\n" - "Tag value\n") + "Tag value\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], NULL); + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], NULL, argv[4]); } -ALIAS (no_ipv6_route_ifname, - no_ipv6_route_ifname_flags_cmd, - "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole)", +ALIAS (no_ipv6_route_ifname_vrf, + no_ipv6_route_ifname_flags_vrf_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole)" VRF_CMD_STR, NO_STR IP_STR "Establish static routes\n" @@ -2723,11 +4060,12 @@ ALIAS (no_ipv6_route_ifname, "IPv6 gateway address\n" "IPv6 gateway interface name\n" "Emit an ICMP unreachable when matched\n" - "Silently discard pkts when matched\n") + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) -ALIAS (no_ipv6_route_ifname_tag, - no_ipv6_route_ifname_flags_tag_cmd, - "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535>", +ALIAS (no_ipv6_route_ifname_tag_vrf, + no_ipv6_route_ifname_flags_tag_vrf_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535>" VRF_CMD_STR, NO_STR IP_STR "Establish static routes\n" @@ -2737,25 +4075,27 @@ ALIAS (no_ipv6_route_ifname_tag, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n" "Set tag for this route\n" - "Tag value\n") + "Tag value\n" + VRF_CMD_HELP_STR) -DEFUN (no_ipv6_route_pref, - no_ipv6_route_pref_cmd, - "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>", +DEFUN (no_ipv6_route_pref_vrf, + no_ipv6_route_pref_vrf_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>" VRF_CMD_STR, NO_STR IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 gateway address\n" "IPv6 gateway interface name\n" - "Distance value for this prefix\n") + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL, argv[2]); + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL, argv[2], argv[3]); } -DEFUN (no_ipv6_route_pref_tag, - no_ipv6_route_pref_tag_cmd, - "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535> <1-255>", +DEFUN (no_ipv6_route_pref_tag_vrf, + no_ipv6_route_pref_tag_vrf_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535> <1-255>" VRF_CMD_STR, NO_STR IP_STR "Establish static routes\n" @@ -2764,14 +4104,15 @@ DEFUN (no_ipv6_route_pref_tag, "IPv6 gateway interface name\n" "Set tag for this route\n" "Tag value\n" - "Distance value for this prefix\n") + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], argv[3]); + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], argv[3], argv[4]); } -DEFUN (no_ipv6_route_flags_pref, - no_ipv6_route_flags_pref_cmd, - "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) <1-255>", +DEFUN (no_ipv6_route_flags_pref_vrf, + no_ipv6_route_flags_pref_vrf_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) <1-255>" VRF_CMD_STR, NO_STR IP_STR "Establish static routes\n" @@ -2780,15 +4121,16 @@ DEFUN (no_ipv6_route_flags_pref, "IPv6 gateway interface name\n" "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n" - "Distance value for this prefix\n") + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) { /* We do not care about argv[2] */ - return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], NULL, argv[3]); + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], NULL, argv[3], argv[4]); } -DEFUN (no_ipv6_route_flags_pref_tag, - no_ipv6_route_flags_pref_tag_cmd, - "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>", +DEFUN (no_ipv6_route_flags_pref_tag_vrf, + no_ipv6_route_flags_pref_tag_vrf_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, NO_STR IP_STR "Establish static routes\n" @@ -2799,29 +4141,31 @@ DEFUN (no_ipv6_route_flags_pref_tag, "Silently discard pkts when matched\n" "Set tag for this route\n" "Tag value\n" - "Distance value for this prefix\n") + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) { /* We do not care about argv[2] */ - return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3], argv[4]); + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3], argv[4], argv[5]); } -DEFUN (no_ipv6_route_ifname_pref, - no_ipv6_route_ifname_pref_cmd, - "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>", +DEFUN (no_ipv6_route_ifname_pref_vrf, + no_ipv6_route_ifname_pref_vrf_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>" VRF_CMD_STR, NO_STR IP_STR "Establish static routes\n" "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" "IPv6 gateway address\n" "IPv6 gateway interface name\n" - "Distance value for this prefix\n") + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, argv[3]); + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, argv[3], argv[4]); } -DEFUN (no_ipv6_route_ifname_pref_tag, - no_ipv6_route_ifname_pref_tag_cmd, - "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535> <1-255>", +DEFUN (no_ipv6_route_ifname_pref_tag_vrf, + no_ipv6_route_ifname_pref_tag_vrf_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535> <1-255>" VRF_CMD_STR, NO_STR IP_STR "Establish static routes\n" @@ -2830,14 +4174,15 @@ DEFUN (no_ipv6_route_ifname_pref_tag, "IPv6 gateway interface name\n" "Set tag for this route\n" "Tag value\n" - "Distance value for this prefix\n") + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], argv[4]); + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], argv[4], argv[5]); } -DEFUN (no_ipv6_route_ifname_flags_pref, - no_ipv6_route_ifname_flags_pref_cmd, - "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) <1-255>", +DEFUN (no_ipv6_route_ifname_flags_pref_vrf, + no_ipv6_route_ifname_flags_pref_vrf_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) <1-255>" VRF_CMD_STR, NO_STR IP_STR "Establish static routes\n" @@ -2846,14 +4191,15 @@ DEFUN (no_ipv6_route_ifname_flags_pref, "IPv6 gateway interface name\n" "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n" - "Distance value for this prefix\n") + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], NULL, argv[4]); + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], NULL, argv[4], argv[5]); } -DEFUN (no_ipv6_route_ifname_flags_pref_tag, - no_ipv6_route_ifname_flags_pref_tag_cmd, - "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535> <1-255>", +DEFUN (no_ipv6_route_ifname_flags_pref_tag_vrf, + no_ipv6_route_ifname_flags_pref_tag_vrf_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, NO_STR IP_STR "Establish static routes\n" @@ -2864,9 +4210,10 @@ DEFUN (no_ipv6_route_ifname_flags_pref_tag, "Silently discard pkts when matched\n" "Set tag for this route\n" "Tag value\n" - "Distance value for this prefix\n") + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); } /* New RIB. Detailed information for IPv6 route. */ @@ -3785,50 +5132,58 @@ static_config_ipv6 (struct vty *vty) int write; char buf[BUFSIZ]; struct route_table *stable; + struct zebra_vrf *zvrf; + vrf_iter_t iter; write = 0; - /* Lookup table. */ - stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); - if (! stable) - return -1; + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (stable = zvrf->stable[AFI_IP6][SAFI_UNICAST]) == NULL) + continue; + + for (rn = route_top (stable); rn; rn = route_next (rn)) + for (si = rn->info; si; si = si->next) + { + vty_out (vty, "ipv6 route %s", prefix2str (&rn->p, buf, sizeof buf)); - for (rn = route_top (stable); rn; rn = route_next (rn)) - for (si = rn->info; si; si = si->next) - { - vty_out (vty, "ipv6 route %s/%d", - inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ), - rn->p.prefixlen); + switch (si->type) + { + case STATIC_IPV6_GATEWAY: + vty_out (vty, " %s", + inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ)); + break; + case STATIC_IPV6_IFNAME: + vty_out (vty, " %s", si->ifname); + break; + case STATIC_IPV6_GATEWAY_IFNAME: + vty_out (vty, " %s %s", + inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ), + si->ifname); + break; + } - switch (si->type) - { - case STATIC_IPV6_GATEWAY: - vty_out (vty, " %s", inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ)); - break; - case STATIC_IPV6_IFNAME: - vty_out (vty, " %s", si->ifname); - break; - case STATIC_IPV6_GATEWAY_IFNAME: - vty_out (vty, " %s %s", - inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ), si->ifname); - break; - } + if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT)) + vty_out (vty, " %s", "reject"); + + if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE)) + vty_out (vty, " %s", "blackhole"); - if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, " %s", "reject"); + if (si->tag) + vty_out (vty, " tag %d", si->tag); - if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, " %s", "blackhole"); + if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) + vty_out (vty, " %d", si->distance); - if (si->tag) - vty_out (vty, " tag %d", si->tag); + if (si->vrf_id != VRF_DEFAULT) + vty_out (vty, " vrf %u", si->vrf_id); - if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) - vty_out (vty, " %d", si->distance); - vty_out (vty, "%s", VTY_NEWLINE); + vty_out (vty, "%s", VTY_NEWLINE); - write = 1; - } + write = 1; + } + } return write; } #endif /* HAVE_IPV6 */ @@ -3976,6 +5331,8 @@ config_write_protocol (struct vty *vty) static struct cmd_node ip_node = { IP_NODE, "", 1 }; static struct cmd_node protocol_node = { PROTOCOL_NODE, "", 1 }; + + /* Route VTY. */ void zebra_vty_init (void) @@ -4069,6 +5426,55 @@ zebra_vty_init (void) /* Commands for VRF */ + install_element (CONFIG_NODE, &ip_route_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_tag_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_flags_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_flags_tag_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_flags2_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_flags2_tag_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_tag_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags_tag_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags2_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags2_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags2_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags2_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags2_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags2_tag_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_distance_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_tag_distance_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_flags_distance_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_flags_tag_distance_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_flags_distance2_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_flags_tag_distance2_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_distance_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_tag_distance_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags_distance_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags_tag_distance_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags_distance2_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags_tag_distance2_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_distance_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_tag_distance_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags_distance_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags_tag_distance_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags_distance2_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags_tag_distance2_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_distance_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_tag_distance_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags_distance_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags_tag_distance_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags_distance2_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags_tag_distance2_vrf_cmd); + install_element (VIEW_NODE, &show_ip_route_vrf_cmd); install_element (VIEW_NODE, &show_ip_route_addr_vrf_cmd); install_element (VIEW_NODE, &show_ip_route_prefix_vrf_cmd); @@ -4168,6 +5574,40 @@ zebra_vty_init (void) /* Commands for VRF */ + install_element (CONFIG_NODE, &ipv6_route_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_flags_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_flags_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_flags_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_pref_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_flags_pref_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_pref_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_flags_pref_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_pref_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_flags_pref_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_pref_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_tag_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_flags_tag_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_tag_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_flags_tag_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_pref_tag_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_flags_pref_tag_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_pref_tag_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_flags_pref_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_flags_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_pref_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_flags_pref_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_pref_tag_vrf_cmd); + + install_element (VIEW_NODE, &show_ipv6_route_vrf_cmd); install_element (VIEW_NODE, &show_ipv6_route_summary_vrf_cmd); install_element (VIEW_NODE, &show_ipv6_route_summary_prefix_vrf_cmd); -- cgit v1.2.3 From a31c5886dda74cab102671d3712fa2070e50d8ed Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:40:09 +0200 Subject: zebra: add hooks upon enabling / disabling a VRF zebra_vrf_enable() is the callback for VRF_ENABLE_HOOK. It presently needs do nothing. zebra_vrf_disable() is the callback for VRF_DISABLE_HOOK. It presently withdraws routes, shuts down interfaces, and clears the router-id candidates in that VRF. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter --- zebra/main.c | 40 ++++++++++++++++++++++++++++++++++++++++ zebra/rib.h | 1 + zebra/test_main.c | 37 +++++++++++++++++++++++++++++++++++++ zebra/zebra_rib.c | 2 +- 4 files changed, 79 insertions(+), 1 deletion(-) (limited to 'zebra/zebra_rib.c') diff --git a/zebra/main.c b/zebra/main.c index 95a0e438e8..22471d3d01 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -230,11 +230,51 @@ zebra_vrf_new (vrf_id_t vrf_id, void **info) return 0; } +/* Callback upon enabling a VRF. */ +static int +zebra_vrf_enable (vrf_id_t vrf_id, void **info) +{ + struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info); + + assert (zvrf); + + return 0; +} + +/* Callback upon disabling a VRF. */ +static int +zebra_vrf_disable (vrf_id_t vrf_id, void **info) +{ + struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info); + struct listnode *list_node; + struct interface *ifp; + + assert (zvrf); + + rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]); + rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), list_node, ifp)) + { + int operative = if_is_operative (ifp); + UNSET_FLAG (ifp->flags, IFF_UP); + if (operative) + if_down (ifp); + } + + list_delete_all_node (zvrf->rid_all_sorted_list); + list_delete_all_node (zvrf->rid_lo_sorted_list); + + return 0; +} + /* Zebra VRF initialization. */ static 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_init (); } diff --git a/zebra/rib.h b/zebra/rib.h index ddc6a49dcd..60a39d4727 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -438,6 +438,7 @@ extern void rib_update (vrf_id_t); extern void rib_update_static (vrf_id_t); extern void rib_weed_tables (void); extern void rib_sweep_route (void); +extern void rib_close_table (struct route_table *); extern void rib_close (void); extern void rib_init (void); extern unsigned long rib_score_proto (u_char proto, u_short instance); diff --git a/zebra/test_main.c b/zebra/test_main.c index 0013506b9b..9b83b642d4 100644 --- a/zebra/test_main.c +++ b/zebra/test_main.c @@ -217,11 +217,48 @@ zebra_vrf_new (vrf_id_t vrf_id, void **info) return 0; } +/* Callback upon enabling a VRF. */ +static int +zebra_vrf_enable (vrf_id_t vrf_id, void **info) +{ + struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info); + + assert (zvrf); + + return 0; +} + +/* Callback upon disabling a VRF. */ +static int +zebra_vrf_disable (vrf_id_t vrf_id, void **info) +{ + struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info); + struct listnode *list_node; + struct interface *ifp; + + assert (zvrf); + + rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]); + rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), list_node, ifp)) + { + int operative = if_is_operative (ifp); + UNSET_FLAG (ifp->flags, IFF_UP); + if (operative) + if_down (ifp); + } + + return 0; +} + /* Zebra VRF initialization. */ static 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_init (); } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 2b94c6a7c6..ee7abc432c 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -3954,7 +3954,7 @@ rib_score_proto (u_char proto, u_short instance) } /* Close RIB and clean up kernel routes. */ -static void +void rib_close_table (struct route_table *table) { struct route_node *rn; -- cgit v1.2.3 From 8f7d9fc0883869bb32f67b4f70f017141d412ccb Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Thu, 3 Jul 2014 18:23:09 +0800 Subject: zebra, lib/memtypes.c: the netlink sockets work per VRF This patch lets the netlink sockets work per VRF. * The definition of "struct nlsock" is moved into zebra/rib.h. * The previous global variables "netlink" and "netlink_cmd" now become the members of "struct zebra_vrf", and are initialized in zebra_vrf_alloc(). * All relative functions now work for a specific VRF, by adding a new parameter which specifies the working VRF, except those functions in which the VRF ID can be obtained from the interface. * kernel_init(), interface_list() and route_read() are now also working per VRF, and moved from main() to zebra_vrf_enable(). * A new function kernel_terminate() is added to release the netlink sockets. It is called from zebra_vrf_disable(). * Correct VRF ID, instead of the previous VRF_DEFAULT, are now passed to the functions of processing interfaces or route entries. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Donald Sharp Conflicts: lib/memtypes.c zebra/rib.h zebra/rt_netlink.c Conflicts: zebra/if_netlink.c zebra/if_sysctl.c zebra/kernel_null.c zebra/rib.h zebra/rt_netlink.c zebra/rt_netlink.h --- lib/memtypes.c | 1 + zebra/if_ioctl.c | 9 +- zebra/if_ioctl_solaris.c | 9 +- zebra/if_netlink.c | 4 +- zebra/if_sysctl.c | 14 ++- zebra/kernel_null.c | 6 +- zebra/kernel_socket.c | 16 +++- zebra/main.c | 8 +- zebra/rib.h | 17 ++++ zebra/rt_netlink.c | 244 ++++++++++++++++++++++++++--------------------- zebra/rt_netlink.h | 4 +- zebra/rtread_getmsg.c | 6 +- zebra/rtread_netlink.c | 4 +- zebra/rtread_sysctl.c | 8 +- zebra/test_main.c | 7 +- zebra/zebra_rib.c | 14 +++ zebra/zserv.h | 7 +- 17 files changed, 244 insertions(+), 134 deletions(-) (limited to 'zebra/zebra_rib.c') diff --git a/lib/memtypes.c b/lib/memtypes.c index dafd471dd2..fc50443600 100644 --- a/lib/memtypes.c +++ b/lib/memtypes.c @@ -90,6 +90,7 @@ struct memory_list memory_list_zebra[] = { MTYPE_RIB_DEST, "RIB destination" }, { MTYPE_RIB_TABLE_INFO, "RIB table info" }, { MTYPE_RNH, "Nexthop tracking object" }, + { MTYPE_NETLINK_NAME, "Netlink name" }, { -1, NULL }, }; diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index f357e15447..8df877dbaa 100644 --- a/zebra/if_ioctl.c +++ b/zebra/if_ioctl.c @@ -29,8 +29,10 @@ #include "connected.h" #include "memory.h" #include "log.h" +#include "vrf.h" #include "zebra/interface.h" +#include "zebra/rib.h" /* Interface looking up using infamous SIOCGIFCONF. */ static int @@ -442,8 +444,13 @@ interface_info_ioctl () /* Lookup all interface information. */ void -interface_list () +interface_list (struct zebra_vrf *zvrf) { + if (zvrf->vrf_id != VRF_DEFAULT) + { + zlog_warn ("interface_list: ignore VRF %u", zvrf->vrf_id); + return; + } /* Linux can do both proc & ioctl, ioctl is the only way to get interface aliases in 2.2 series kernels. */ #ifdef HAVE_PROC_NET_DEV diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c index fc384ea29a..3f33f749af 100644 --- a/zebra/if_ioctl_solaris.c +++ b/zebra/if_ioctl_solaris.c @@ -30,8 +30,10 @@ #include "memory.h" #include "log.h" #include "privs.h" +#include "vrf.h" #include "zebra/interface.h" +#include "zebra/rib.h" void lifreq_set_name (struct lifreq *, const char *); int if_get_flags_direct (const char *, uint64_t *, unsigned int af); @@ -349,8 +351,13 @@ interface_info_ioctl (struct interface *ifp) /* Lookup all interface information. */ void -interface_list () +interface_list (struct zebra_vrf *zvrf) { + if (zvrf->vrf_id != VRF_DEFAULT) + { + zlog_warn ("interface_list: ignore VRF %u", zvrf->vrf_id); + return; + } interface_list_ioctl (AF_INET); interface_list_ioctl (AF_INET6); interface_list_ioctl (AF_UNSPEC); diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 2016986cb5..9562f2f586 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -27,7 +27,7 @@ /* Interface information read by netlink. */ void -interface_list (void) +interface_list (struct zebra_vrf *zvrf) { - interface_lookup_netlink (); + interface_lookup_netlink (zvrf); } diff --git a/zebra/if_sysctl.c b/zebra/if_sysctl.c index 1150ec1b06..e7b25d1f8f 100644 --- a/zebra/if_sysctl.c +++ b/zebra/if_sysctl.c @@ -29,9 +29,15 @@ #include "memory.h" #include "ioctl.h" #include "log.h" +<<<<<<< HEAD +======= +#include "interface.h" +#include "vrf.h" +>>>>>>> 3c27b5f... zebra, lib/memtypes.c: the netlink sockets work per VRF #include "zebra/rt.h" #include "zebra/kernel_socket.h" +#include "zebra/rib.h" void ifstat_update_sysctl (void) @@ -90,7 +96,7 @@ ifstat_update_sysctl (void) /* Interface listing up function using sysctl(). */ void -interface_list () +interface_list (struct zebra_vrf *zvrf) { caddr_t ref, buf, end; size_t bufsiz; @@ -107,6 +113,12 @@ interface_list () 0 }; + if (zvrf->vrf_id != VRF_DEFAULT) + { + zlog_warn ("interface_list: ignore VRF %u", zvrf->vrf_id); + return; + } + /* Query buffer size. */ if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) { diff --git a/zebra/kernel_null.c b/zebra/kernel_null.c index 5f37e0cc7c..08fef9b309 100644 --- a/zebra/kernel_null.c +++ b/zebra/kernel_null.c @@ -8,6 +8,7 @@ #include "zebra/redistribute.h" #include "zebra/connected.h" #include "zebra/rt_netlink.h" +#include "zebra/rib.h" int kernel_add_ipv4 (struct prefix *a, struct rib *b) { return 0; } int kernel_update_ipv4 (struct prefix *a, struct rib *b) { return 0; } @@ -54,9 +55,10 @@ int netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llale return 0; } -void kernel_init (void) { return; } +void kernel_init (struct zebra_vrf *zvrf) { return; } +void kernel_terminate (struct zebra_vrf *zvrf) { return; } #ifdef HAVE_SYS_WEAK_ALIAS_PRAGMA #pragma weak route_read = kernel_init #else -void route_read (void) { return; } +void route_read (struct zebra_vrf *zvrf) { return; } #endif diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index a1002a4d86..7b4f70fa83 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -38,6 +38,7 @@ #include "zebra/zserv.h" #include "zebra/debug.h" #include "zebra/kernel_socket.h" +#include "zebra/rib.h" extern struct zebra_privs_t zserv_privs; extern struct zebra_t zebrad; @@ -1262,8 +1263,11 @@ kernel_read (struct thread *thread) /* Make routing socket. */ static void -routing_socket (void) +routing_socket (struct zebra_vrf *zvrf) { + if (zvrf->vrf_id != VRF_DEFAULT) + return; + if ( zserv_privs.change (ZPRIVS_RAISE) ) zlog_err ("routing_socket: Can't raise privileges"); @@ -1294,7 +1298,13 @@ routing_socket (void) /* Exported interface function. This function simply calls routing_socket (). */ void -kernel_init (void) +kernel_init (struct zebra_vrf *zvrf) +{ + routing_socket (zvrf); +} + +void +kernel_terminate (struct zebra_vrf *zvrf) { - routing_socket (); + return; } diff --git a/zebra/main.c b/zebra/main.c index 16a11edea3..4b2a89856e 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -241,6 +241,10 @@ zebra_vrf_enable (vrf_id_t vrf_id, void **info) #ifdef RTADV rtadv_init (zvrf); #endif + kernel_init (zvrf); + interface_list (zvrf); + route_read (zvrf); + return 0; } @@ -268,6 +272,7 @@ zebra_vrf_disable (vrf_id_t vrf_id, void **info) #ifdef RTADV rtadv_terminate (zvrf); #endif + kernel_terminate (zvrf); list_delete_all_node (zvrf->rid_all_sorted_list); list_delete_all_node (zvrf->rid_lo_sorted_list); @@ -428,9 +433,6 @@ main (int argc, char **argv) /* Initialize VRF module, and make kernel routing socket. */ zebra_vrf_init (); - kernel_init (); - interface_list (); - route_read (); #ifdef HAVE_SNMP zebra_snmp_init (); diff --git a/zebra/rib.h b/zebra/rib.h index f18b311d47..25ab68df13 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -310,6 +310,17 @@ struct rtadv }; #endif /* RTADV && HAVE_IPV6 */ +#ifdef HAVE_NETLINK +/* Socket interface to kernel */ +struct nlsock +{ + int sock; + int seq; + struct sockaddr_nl snl; + const char *name; +}; +#endif + /* Routing table instance. */ struct zebra_vrf { @@ -340,6 +351,12 @@ struct zebra_vrf /* Routing tables off of main table for redistribute table */ struct route_table *other_table[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; +#ifdef HAVE_NETLINK + struct nlsock netlink; /* kernel messages */ + struct nlsock netlink_cmd; /* command channel */ + struct thread *t_netlink; +#endif + /* 2nd pointer type used primarily to quell a warning on * ALL_LIST_ELEMENTS_RO */ diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index e312801e55..cad367808d 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -47,16 +47,6 @@ #include "rt_netlink.h" -/* Socket interface to kernel */ -struct nlsock -{ - int sock; - int seq; - struct sockaddr_nl snl; - const char *name; -} netlink = { -1, 0, {0}, "netlink-listen"}, /* kernel messages */ - netlink_cmd = { -1, 0, {0}, "netlink-cmd"}; /* command channel */ - static const struct message nlmsg_str[] = { {RTM_NEWROUTE, "RTM_NEWROUTE"}, {RTM_DELROUTE, "RTM_DELROUTE"}, @@ -156,7 +146,7 @@ netlink_recvbuf (struct nlsock *nl, uint32_t newsize) /* Make socket for Linux netlink interface. */ static int -netlink_socket (struct nlsock *nl, unsigned long groups) +netlink_socket (struct nlsock *nl, unsigned long groups, vrf_id_t vrf_id) { int ret; struct sockaddr_nl snl; @@ -170,7 +160,7 @@ netlink_socket (struct nlsock *nl, unsigned long groups) return -1; } - sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + sock = vrf_socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, vrf_id); if (sock < 0) { zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name, @@ -273,8 +263,9 @@ netlink_request (int family, int type, struct nlsock *nl) /* Receive message from netlink interface and pass those information to the given function. */ static int -netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), - struct nlsock *nl) +netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, + vrf_id_t), + struct nlsock *nl, struct zebra_vrf *zvrf) { int status; int ret = 0; @@ -363,7 +354,7 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), } /* Deal with errors that occur because of races in link handling */ - if (nl == &netlink_cmd + if (nl == &zvrf->netlink_cmd && ((msg_type == RTM_DELROUTE && (-errnum == ENODEV || -errnum == ESRCH)) || (msg_type == RTM_NEWROUTE && -errnum == EEXIST))) @@ -376,7 +367,7 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), return 0; } - if (nl == &netlink_cmd + if (nl == &zvrf->netlink_cmd && msg_type == RTM_NEWROUTE && -errnum == ESRCH) { /* This is known to happen in some situations, don't log @@ -407,16 +398,17 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), /* skip unsolicited messages originating from command socket * linux sets the originators port-id for {NEW|DEL}ADDR messages, * so this has to be checked here. */ - if (nl != &netlink_cmd && h->nlmsg_pid == netlink_cmd.snl.nl_pid + if (nl != &zvrf->netlink_cmd + && h->nlmsg_pid == zvrf->netlink_cmd.snl.nl_pid && (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)) { if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug ("netlink_parse_info: %s packet comes from %s", - netlink_cmd.name, nl->name); + zvrf->netlink_cmd.name, nl->name); continue; } - error = (*filter) (&snl, h); + error = (*filter) (&snl, h, zvrf->vrf_id); if (error < 0) { zlog (NULL, LOG_ERR, "%s filter function error", nl->name); @@ -487,7 +479,8 @@ netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp) /* Called from interface_lookup_netlink(). This function is only used during bootstrap. */ static int -netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) +netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, + vrf_id_t vrf_id) { int len; struct ifinfomsg *ifi; @@ -523,7 +516,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) name = (char *) RTA_DATA (tb[IFLA_IFNAME]); /* Add interface. */ - ifp = if_get_by_name (name); + ifp = if_get_by_name_vrf (name, vrf_id); set_ifindex(ifp, ifi->ifi_index); ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); @@ -540,7 +533,8 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) /* Lookup interface IPv4/IPv6 address. */ static int -netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) +netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h, + vrf_id_t vrf_id) { int len; struct ifaddrmsg *ifa; @@ -570,19 +564,19 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) memset (tb, 0, sizeof tb); netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len); - ifp = if_lookup_by_index (ifa->ifa_index); + ifp = if_lookup_by_index_vrf (ifa->ifa_index, vrf_id); if (ifp == NULL) { - zlog_err ("netlink_interface_addr can't find interface by index %d", - ifa->ifa_index); + zlog_err ("netlink_interface_addr can't find interface by index %d vrf %u", + ifa->ifa_index, vrf_id); return -1; } if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */ { char buf[BUFSIZ]; - zlog_debug ("netlink_interface_addr %s %s:", - lookup (nlmsg_str, h->nlmsg_type), ifp->name); + zlog_debug ("netlink_interface_addr %s %s vrf %u:", + lookup (nlmsg_str, h->nlmsg_type), ifp->name, vrf_id); if (tb[IFA_LOCAL]) zlog_debug (" IFA_LOCAL %s/%d", inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]), @@ -675,7 +669,8 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) /* Looking up routing table by netlink interface. */ static int -netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) +netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, + vrf_id_t vrf_id) { int len; struct rtmsg *rtm; @@ -756,7 +751,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) if (!tb[RTA_MULTIPATH]) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, src, index, - VRF_DEFAULT, table, metric, 0, SAFI_UNICAST); + vrf_id, table, metric, 0, SAFI_UNICAST); else { /* This is a multipath route */ @@ -772,7 +767,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) rib->distance = 0; rib->flags = flags; rib->metric = metric; - rib->vrf_id = VRF_DEFAULT; + rib->vrf_id = vrf_id; rib->table = table; rib->nexthop_num = 0; rib->uptime = time (NULL); @@ -823,7 +818,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) memcpy (&p.prefix, dest, 16); p.prefixlen = rtm->rtm_dst_len; - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, index, VRF_DEFAULT, + rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, index, vrf_id, table, metric, 0, SAFI_UNICAST); } #endif /* HAVE_IPV6 */ @@ -848,7 +843,8 @@ static const struct message rtproto_str[] = { /* Routing information change from the kernel. */ static int -netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) +netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, + vrf_id_t vrf_id) { int len; struct rtmsg *rtm; @@ -870,18 +866,19 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) { /* If this is not route add/delete message print warning. */ - zlog_warn ("Kernel message: %d\n", h->nlmsg_type); + zlog_warn ("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id); return 0; } /* Connected route. */ if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s %s %s proto %s", + zlog_debug ("%s %s %s proto %s vrf %u", h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", rtm->rtm_family == AF_INET ? "ipv4" : "ipv6", rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast", - lookup (rtproto_str, rtm->rtm_protocol)); + lookup (rtproto_str, rtm->rtm_protocol), + vrf_id); if (rtm->rtm_type != RTN_UNICAST) { @@ -913,7 +910,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (rtm->rtm_src_len != 0) { - zlog_warn ("netlink_route_change(): no src len"); + zlog_warn ("netlink_route_change(): no src len, vrf %u", vrf_id); return 0; } @@ -949,18 +946,16 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (IS_ZEBRA_DEBUG_KERNEL) { - if (h->nlmsg_type == RTM_NEWROUTE) - zlog_debug ("RTM_NEWROUTE %s/%d", - inet_ntoa (p.prefix), p.prefixlen); - else - zlog_debug ("RTM_DELROUTE %s/%d", - inet_ntoa (p.prefix), p.prefixlen); + char buf[BUFSIZ]; + zlog_debug ("%s %s vrf %u", + h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", + prefix2str (&p, buf, sizeof(buf)), vrf_id); } if (h->nlmsg_type == RTM_NEWROUTE) { if (!tb[RTA_MULTIPATH]) - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, src, index, VRF_DEFAULT, + rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, src, index, vrf_id, table, metric, 0, SAFI_UNICAST); else { @@ -977,7 +972,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) rib->distance = 0; rib->flags = 0; rib->metric = metric; - rib->vrf_id = VRF_DEFAULT; + rib->vrf_id = vrf_id; rib->table = table; rib->nexthop_num = 0; rib->uptime = time (NULL); @@ -1023,7 +1018,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) } else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, - VRF_DEFAULT, table, SAFI_UNICAST); + vrf_id, table, SAFI_UNICAST); } #ifdef HAVE_IPV6 @@ -1038,22 +1033,17 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (IS_ZEBRA_DEBUG_KERNEL) { - if (h->nlmsg_type == RTM_NEWROUTE) - zlog_debug ("RTM_NEWROUTE %s/%d", - inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ), - p.prefixlen); - else - zlog_debug ("RTM_DELROUTE %s/%d", - inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ), - p.prefixlen); + zlog_debug ("%s %s vrf %u", + h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", + prefix2str (&p, buf, sizeof(buf)), vrf_id); } if (h->nlmsg_type == RTM_NEWROUTE) - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, index, VRF_DEFAULT, + rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, index, vrf_id, table, metric, 0, SAFI_UNICAST); else rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, - VRF_DEFAULT, table, SAFI_UNICAST); + vrf_id, table, SAFI_UNICAST); } #endif /* HAVE_IPV6 */ @@ -1061,7 +1051,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) } static int -netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) +netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, + vrf_id_t vrf_id) { int len; struct ifinfomsg *ifi; @@ -1074,8 +1065,8 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) { /* If this is not link add/delete message so print warning. */ - zlog_warn ("netlink_link_change: wrong kernel message %d\n", - h->nlmsg_type); + zlog_warn ("netlink_link_change: wrong kernel message %d vrf %u\n", + h->nlmsg_type, vrf_id); return 0; } @@ -1092,7 +1083,8 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) { if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__); + zlog_debug ("%s: ignoring IFLA_WIRELESS message, vrf %u", __func__, + vrf_id); return 0; } #endif /* IFLA_WIRELESS */ @@ -1104,12 +1096,12 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) /* Add interface. */ if (h->nlmsg_type == RTM_NEWLINK) { - ifp = if_lookup_by_name (name); + ifp = if_lookup_by_name_vrf (name, vrf_id); if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) { if (ifp == NULL) - ifp = if_get_by_name (name); + ifp = if_get_by_name_vrf (name, vrf_id); set_ifindex(ifp, ifi->ifi_index); ifp->flags = ifi->ifi_flags & 0x0000fffff; @@ -1150,12 +1142,12 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) else { /* RTM_DELLINK. */ - ifp = if_lookup_by_name (name); + ifp = if_lookup_by_name_vrf (name, vrf_id); if (ifp == NULL) { - zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find", - name); + zlog_warn ("interface %s vrf %u is deleted but can't find", + name, vrf_id); return 0; } @@ -1166,7 +1158,8 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) } static int -netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h) +netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h, + vrf_id_t vrf_id) { /* JF: Ignore messages that aren't from the kernel */ if ( snl->nl_pid != 0 ) @@ -1178,25 +1171,26 @@ netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h) switch (h->nlmsg_type) { case RTM_NEWROUTE: - return netlink_route_change (snl, h); + return netlink_route_change (snl, h, vrf_id); break; case RTM_DELROUTE: - return netlink_route_change (snl, h); + return netlink_route_change (snl, h, vrf_id); break; case RTM_NEWLINK: - return netlink_link_change (snl, h); + return netlink_link_change (snl, h, vrf_id); break; case RTM_DELLINK: - return netlink_link_change (snl, h); + return netlink_link_change (snl, h, vrf_id); break; case RTM_NEWADDR: - return netlink_interface_addr (snl, h); + return netlink_interface_addr (snl, h, vrf_id); break; case RTM_DELADDR: - return netlink_interface_addr (snl, h); + return netlink_interface_addr (snl, h, vrf_id); break; default: - zlog_warn ("Unknown netlink nlmsg_type %d\n", h->nlmsg_type); + zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type, + vrf_id); break; } return 0; @@ -1204,32 +1198,32 @@ netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h) /* Interface lookup by netlink socket. */ int -interface_lookup_netlink (void) +interface_lookup_netlink (struct zebra_vrf *zvrf) { int ret; /* Get interface information. */ - ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd); + ret = netlink_request (AF_PACKET, RTM_GETLINK, &zvrf->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_interface, &netlink_cmd); + ret = netlink_parse_info (netlink_interface, &zvrf->netlink_cmd, zvrf); if (ret < 0) return ret; /* Get IPv4 address of the interfaces. */ - ret = netlink_request (AF_INET, RTM_GETADDR, &netlink_cmd); + ret = netlink_request (AF_INET, RTM_GETADDR, &zvrf->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd); + ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, zvrf); if (ret < 0) return ret; #ifdef HAVE_IPV6 /* Get IPv6 address of the interfaces. */ - ret = netlink_request (AF_INET6, RTM_GETADDR, &netlink_cmd); + ret = netlink_request (AF_INET6, RTM_GETADDR, &zvrf->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd); + ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, zvrf); if (ret < 0) return ret; #endif /* HAVE_IPV6 */ @@ -1240,24 +1234,24 @@ interface_lookup_netlink (void) /* Routing table read function using netlink interface. Only called bootstrap time. */ int -netlink_route_read (void) +netlink_route_read (struct zebra_vrf *zvrf) { int ret; /* Get IPv4 routing table. */ - ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd); + ret = netlink_request (AF_INET, RTM_GETROUTE, &zvrf->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_routing_table, &netlink_cmd); + ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, zvrf); if (ret < 0) return ret; #ifdef HAVE_IPV6 /* Get IPv6 routing table. */ - ret = netlink_request (AF_INET6, RTM_GETROUTE, &netlink_cmd); + ret = netlink_request (AF_INET6, RTM_GETROUTE, &zvrf->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_routing_table, &netlink_cmd); + ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, zvrf); if (ret < 0) return ret; #endif /* HAVE_IPV6 */ @@ -1330,15 +1324,17 @@ addattr32 (struct nlmsghdr *n, unsigned int maxlen, int type, int data) } static int -netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h) +netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h, + vrf_id_t vrf_id) { - zlog_warn ("netlink_talk: ignoring message type 0x%04x", h->nlmsg_type); + zlog_warn ("netlink_talk: ignoring message type 0x%04x vrf %u", h->nlmsg_type, + vrf_id); return 0; } /* sendmsg() to netlink socket then recvmsg(). */ static int -netlink_talk (struct nlmsghdr *n, struct nlsock *nl) +netlink_talk (struct nlmsghdr *n, struct nlsock *nl, struct zebra_vrf *zvrf) { int status; struct sockaddr_nl snl; @@ -1388,7 +1384,7 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl) * Get reply from netlink socket. * The reply should either be an acknowlegement or an error. */ - return netlink_parse_info (netlink_talk_filter, nl); + return netlink_parse_info (netlink_talk_filter, nl, zvrf); } /* Routing table change via netlink interface. */ @@ -1401,6 +1397,8 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate, struct sockaddr_nl snl; int discard; + struct zebra_vrf *zvrf = vrf_info_lookup (VRF_DEFAULT); //Pending + struct { struct nlmsghdr n; @@ -1462,7 +1460,7 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate, snl.nl_family = AF_NETLINK; /* Talk to netlink socket. */ - ret = netlink_talk (&req.n, &netlink_cmd); + ret = netlink_talk (&req.n, &zvrf->netlink_cmd, VRF_DEFAULT); if (ret < 0) return -1; @@ -1763,11 +1761,12 @@ _netlink_route_debug( struct prefix *p, struct nexthop *nexthop, const char *routedesc, - int family) + int family, + struct zebra_vrf *zvrf) { if (IS_ZEBRA_DEBUG_KERNEL) { - zlog_debug ("netlink_route_multipath() (%s): %s %s/%d type %s", + zlog_debug ("netlink_route_multipath() (%s): %s %s/%d vrf %u type %s", routedesc, lookup (nlmsg_str, cmd), #ifdef HAVE_IPV6 @@ -1776,7 +1775,7 @@ _netlink_route_debug( #else inet_ntoa (p->u.prefix4), #endif /* HAVE_IPV6 */ - p->prefixlen, nexthop_type_to_str (nexthop->type)); + p->prefixlen, zvrf->vrf_id, nexthop_type_to_str (nexthop->type)); } } @@ -1789,6 +1788,8 @@ netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen) char buf[256]; } req; + struct zebra_vrf *zvrf = vrf_info_lookup (VRF_DEFAULT); //Pending + memset(&req.n, 0, sizeof(req.n)); memset(&req.ndm, 0, sizeof(req.ndm)); @@ -1803,7 +1804,7 @@ netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen) addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4); addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); - return netlink_talk (&req.n, &netlink_cmd); + return netlink_talk (&req.n, &zvrf->netlink_cmd, VRF_DEFAULT); } /* Routing table change via netlink interface. */ @@ -1829,6 +1830,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, char buf[NL_PKT_BUF_SIZE]; } req; + struct zebra_vrf *zvrf = vrf_info_lookup (rib->vrf_id); + memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); bytelen = (family == AF_INET ? 4 : 16); @@ -1950,7 +1953,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, { routedesc = recursing ? "recursive, 1 hop" : "single hop"; - _netlink_route_debug(cmd, p, nexthop, routedesc, family); + _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf); _netlink_route_build_singlepath(routedesc, bytelen, nexthop, &req.n, &req.r, sizeof req, cmd); @@ -2031,7 +2034,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, nexthop_num++; _netlink_route_debug(cmd, p, nexthop, - routedesc, family); + routedesc, family, zvrf); _netlink_route_build_multipath(routedesc, bytelen, nexthop, rta, rtnh, &req.r, &src1); rtnh = RTNH_NEXT (rtnh); @@ -2079,7 +2082,7 @@ skip: snl.nl_family = AF_NETLINK; /* Talk to netlink socket. */ - return netlink_talk (&req.n, &netlink_cmd); + return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf); } int @@ -2142,6 +2145,8 @@ netlink_address (int cmd, int family, struct interface *ifp, char buf[NL_PKT_BUF_SIZE]; } req; + struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id); + p = ifc->address; memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); @@ -2174,7 +2179,7 @@ netlink_address (int cmd, int family, struct interface *ifp, addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label, strlen (ifc->label) + 1); - return netlink_talk (&req.n, &netlink_cmd); + return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf); } int @@ -2196,8 +2201,10 @@ extern struct thread_master *master; static int kernel_read (struct thread *thread) { - netlink_parse_info (netlink_information_fetch, &netlink); - thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); + struct zebra_vrf *zvrf = (struct zebra_vrf *)THREAD_ARG (thread); + netlink_parse_info (netlink_information_fetch, &zvrf->netlink, zvrf); + zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf, + zvrf->netlink.sock); return 0; } @@ -2236,7 +2243,7 @@ static void netlink_install_filter (int sock, __u32 pid) /* Exported interface function. This function simply calls netlink_socket (). */ void -kernel_init (void) +kernel_init (struct zebra_vrf *zvrf) { unsigned long groups; @@ -2244,23 +2251,42 @@ kernel_init (void) #ifdef HAVE_IPV6 groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR; #endif /* HAVE_IPV6 */ - netlink_socket (&netlink, groups); - netlink_socket (&netlink_cmd, 0); + netlink_socket (&zvrf->netlink, groups, zvrf->vrf_id); + netlink_socket (&zvrf->netlink_cmd, 0, zvrf->vrf_id); /* Register kernel socket. */ - if (netlink.sock > 0) + if (zvrf->netlink.sock > 0) { /* Only want non-blocking on the netlink event socket */ - if (fcntl (netlink.sock, F_SETFL, O_NONBLOCK) < 0) - zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", netlink.name, - safe_strerror (errno)); + if (fcntl (zvrf->netlink.sock, F_SETFL, O_NONBLOCK) < 0) + zlog_err ("Can't set %s socket flags: %s", zvrf->netlink.name, + safe_strerror (errno)); /* Set receive buffer size if it's set from command line */ if (nl_rcvbufsize) - netlink_recvbuf (&netlink, nl_rcvbufsize); + netlink_recvbuf (&zvrf->netlink, nl_rcvbufsize); - netlink_install_filter (netlink.sock, netlink_cmd.snl.nl_pid); - thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); + netlink_install_filter (zvrf->netlink.sock, zvrf->netlink_cmd.snl.nl_pid); + zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf, + zvrf->netlink.sock); + } +} + +void +kernel_terminate (struct zebra_vrf *zvrf) +{ + THREAD_READ_OFF (zvrf->t_netlink); + + if (zvrf->netlink.sock >= 0) + { + close (zvrf->netlink.sock); + zvrf->netlink.sock = -1; + } + + if (zvrf->netlink_cmd.sock >= 0) + { + close (zvrf->netlink_cmd.sock); + zvrf->netlink_cmd.sock = -1; } } diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index 5b1b48cb0a..d45d22f936 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -44,8 +44,8 @@ nl_rtproto_to_str (u_char rtproto); int netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen); -extern int netlink_route_read(void); -extern int interface_lookup_netlink(void); +extern int interface_lookup_netlink (struct zebra_vrf *zvrf); +extern int netlink_route_read (struct zebra_vrf *zvrf); #endif /* HAVE_NETLINK */ diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index f9bfb338a0..6975390415 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -95,7 +95,7 @@ handle_route_entry (mib2_ipRouteEntry_t *routeEntry) } void -route_read (void) +route_read (struct zebra_vrf *zvrf) { char storage[RT_BUFSIZ]; @@ -110,6 +110,10 @@ route_read (void) struct strbuf msgdata; int flags, dev, retval, process; + if (zvrf->vrf_id != VRF_DEFAULT) { + return; + } + if ((dev = open (_PATH_GETMSG_ROUTE, O_RDWR)) == -1) { zlog_warn ("can't open %s: %s", _PATH_GETMSG_ROUTE, safe_strerror (errno)); diff --git a/zebra/rtread_netlink.c b/zebra/rtread_netlink.c index 09191d517b..5b26449798 100644 --- a/zebra/rtread_netlink.c +++ b/zebra/rtread_netlink.c @@ -25,7 +25,7 @@ #include "zebra/zserv.h" #include "zebra/rt_netlink.h" -void route_read (void) +void route_read (struct zebra_vrf *zvrf) { - netlink_route_read (); + netlink_route_read (zvrf); } diff --git a/zebra/rtread_sysctl.c b/zebra/rtread_sysctl.c index 69d45950ae..2a9601a304 100644 --- a/zebra/rtread_sysctl.c +++ b/zebra/rtread_sysctl.c @@ -24,6 +24,7 @@ #include "memory.h" #include "log.h" +#include "vrf.h" #include "zebra/zserv.h" #include "zebra/rt.h" @@ -31,7 +32,7 @@ /* Kernel routing table read up by sysctl function. */ void -route_read (void) +route_read (struct zebra_vrf *zvrf) { caddr_t buf, end, ref; size_t bufsiz; @@ -47,7 +48,10 @@ route_read (void) NET_RT_DUMP, 0 }; - + + if (zvrf->vrf_id != VRF_DEFAULT) + return; + /* Get buffer size. */ if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) { diff --git a/zebra/test_main.c b/zebra/test_main.c index 9b83b642d4..027d2a1580 100644 --- a/zebra/test_main.c +++ b/zebra/test_main.c @@ -225,6 +225,9 @@ zebra_vrf_enable (vrf_id_t vrf_id, void **info) assert (zvrf); + kernel_init (zvrf); + route_read (zvrf); + return 0; } @@ -249,6 +252,8 @@ zebra_vrf_disable (vrf_id_t vrf_id, void **info) if_down (ifp); } + kernel_terminate (zvrf); + return 0; } @@ -363,8 +368,6 @@ main (int argc, char **argv) /* Make kernel routing socket. */ zebra_vrf_init (); - kernel_init (); - route_read (); zebra_vty_init(); /* Configuration file read*/ diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index ee7abc432c..5fd6545ffe 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -4135,6 +4135,9 @@ struct zebra_vrf * zebra_vrf_alloc (vrf_id_t vrf_id) { struct zebra_vrf *zvrf; +#ifdef HAVE_NETLINK + char nl_name[64]; +#endif zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf)); @@ -4157,6 +4160,17 @@ zebra_vrf_alloc (vrf_id_t vrf_id) /* Set VRF ID */ zvrf->vrf_id = vrf_id; +#ifdef HAVE_NETLINK + /* Initialize netlink sockets */ + snprintf (nl_name, 64, "netlink-listen (vrf %u)", vrf_id); + zvrf->netlink.sock = -1; + zvrf->netlink.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name); + + snprintf (nl_name, 64, "netlink-cmd (vrf %u)", vrf_id); + zvrf->netlink_cmd.sock = -1; + zvrf->netlink_cmd.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name); +#endif + return zvrf; } diff --git a/zebra/zserv.h b/zebra/zserv.h index 29b3145672..f4da43d0b0 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -134,9 +134,10 @@ extern void zebra_if_init (void); extern void zebra_zserv_socket_init (char *path); extern void hostinfo_get (void); extern void rib_init (void); -extern void interface_list (void); -extern void kernel_init (void); -extern void route_read (void); +extern void interface_list (struct zebra_vrf *); +extern void route_read (struct zebra_vrf *); +extern void kernel_init (struct zebra_vrf *); +extern void kernel_terminate (struct zebra_vrf *); extern void zebra_route_map_init (void); extern void zebra_snmp_init (void); extern void zebra_vty_init (void); -- cgit v1.2.3 From 92955671de04097089fc3fd62dda351ab00b0ce6 Mon Sep 17 00:00:00 2001 From: Vipin Kumar Date: Fri, 30 Oct 2015 02:12:14 -0700 Subject: zebra_vrf lookup fix in upstream VRF patches Ticket: Reviewed By: Testing Done: --- zebra/zebra_rib.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'zebra/zebra_rib.c') diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 5fd6545ffe..ffa3161f2b 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -79,9 +79,6 @@ static const struct /* no entry/default: 150 */ }; -/* Vector for routing table. */ -static vector zebra_vrf_vector; - /* * nexthop_type_to_str */ @@ -4178,7 +4175,7 @@ zebra_vrf_alloc (vrf_id_t vrf_id) struct zebra_vrf * zebra_vrf_lookup (vrf_id_t vrf_id) { - return vector_lookup (zebra_vrf_vector, vrf_id); + return vrf_info_lookup (vrf_id); } /* Lookup the routing table in an enabled VRF. */ -- cgit v1.2.3