Merge branch 'cmaster' of ssh://stash.cumulusnetworks.com:7999/quag/quagga into cmaster

Conflicts:
	zebra/rib.h
	zebra/zebra_rib.c
	zebra/zebra_vty.c
This commit is contained in:
Donald Sharp 2015-10-30 05:52:29 -07:00
commit be5e48abec
74 changed files with 5289 additions and 1377 deletions

View File

@ -55,6 +55,7 @@ THE SOFTWARE.
#include "neighbour.h" #include "neighbour.h"
#include "route.h" #include "route.h"
#include "xroute.h" #include "xroute.h"
#include "vrf.h"
#define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0) #define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0)
@ -878,7 +879,7 @@ void
babel_if_init () babel_if_init ()
{ {
/* initialize interface list */ /* initialize interface list */
if_init(); vrf_init();
if_add_hook (IF_NEW_HOOK, babel_if_new_hook); if_add_hook (IF_NEW_HOOK, babel_if_new_hook);
if_add_hook (IF_DELETE_HOOK, babel_if_delete_hook); if_add_hook (IF_DELETE_HOOK, babel_if_delete_hook);

View File

@ -37,6 +37,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "plist.h" #include "plist.h"
#include "stream.h" #include "stream.h"
#include "queue.h" #include "queue.h"
#include "vrf.h"
#include "bgpd/bgpd.h" #include "bgpd/bgpd.h"
#include "bgpd/bgp_attr.h" #include "bgpd/bgp_attr.h"
@ -238,17 +239,14 @@ bgp_exit (int status)
/* reverse bgp_zebra_init/if_init */ /* reverse bgp_zebra_init/if_init */
if (retain_mode) if (retain_mode)
if_add_hook (IF_DELETE_HOOK, NULL); if_add_hook (IF_DELETE_HOOK, NULL);
for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp)) for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
{ {
struct listnode *c_node, *c_nnode; struct listnode *c_node, *c_nnode;
struct connected *c; struct connected *c;
for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c)) for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c))
bgp_connected_delete (c); bgp_connected_delete (c);
if_delete (ifp);
} }
list_free (iflist);
/* reverse bgp_attr_init */ /* reverse bgp_attr_init */
bgp_attr_finish (); bgp_attr_finish ();
@ -280,6 +278,7 @@ bgp_exit (int status)
/* reverse community_list_init */ /* reverse community_list_init */
community_list_terminate (bgp_clist); community_list_terminate (bgp_clist);
vrf_terminate ();
cmd_terminate (); cmd_terminate ();
vty_terminate (); vty_terminate ();
if (zclient) if (zclient)
@ -412,6 +411,7 @@ main (int argc, char **argv)
cmd_init (1); cmd_init (1);
vty_init (bm->master); vty_init (bm->master);
memory_init (); memory_init ();
vrf_init ();
/* BGP related initialization. */ /* BGP related initialization. */
bgp_init (); bgp_init ();

View File

@ -477,7 +477,8 @@ show_ip_bgp_nexthop_table (struct vty *vty, int detail)
VTY_NEWLINE); VTY_NEWLINE);
break; break;
case NEXTHOP_TYPE_IFINDEX: case NEXTHOP_TYPE_IFINDEX:
vty_out (vty, " ifidx %u%s", nexthop->ifindex, vty_out (vty, " if %s%s",
ifindex2ifname(nexthop->ifindex),
VTY_NEWLINE); VTY_NEWLINE);
break; break;
default: default:

View File

@ -1136,12 +1136,16 @@ bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
struct peer *peer, struct attr *attr) struct peer *peer, struct attr *attr)
{ {
if (peer->sort == BGP_PEER_EBGP && if (peer->sort == BGP_PEER_EBGP &&
peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)) (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE) ||
peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE) ||
peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL) ||
peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)))
{ {
// Take action on the entire aspath // Take action on the entire aspath
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE) ||
peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL))
{ {
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
attr->aspath = aspath_replace_private_asns (attr->aspath, bgp->as); attr->aspath = aspath_replace_private_asns (attr->aspath, bgp->as);
// The entire aspath consists of private ASNs so create an empty aspath // The entire aspath consists of private ASNs so create an empty aspath
@ -1500,7 +1504,8 @@ subgroup_announce_check (struct bgp_info *ri, struct update_subgroup *subgrp,
!CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) !CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED))
{ {
/* We can reset the nexthop, if setting (or forcing) it to 'self' */ /* We can reset the nexthop, if setting (or forcing) it to 'self' */
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF)) if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF) ||
CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_FORCE_NEXTHOP_SELF))
{ {
if (!reflect || if (!reflect ||
CHECK_FLAG (peer->af_flags[afi][safi], CHECK_FLAG (peer->af_flags[afi][safi],

View File

@ -2666,8 +2666,9 @@ bgp_route_set_delete (struct vty *vty, struct route_map_index *index,
* modifications. * modifications.
*/ */
static void static void
bgp_route_map_process_peer (const char *rmap_name, struct peer *peer, bgp_route_map_process_peer (const char *rmap_name, struct route_map *map,
int afi, int safi, int route_update) struct peer *peer, int afi, int safi,
int route_update)
{ {
int update; int update;
@ -2687,8 +2688,7 @@ bgp_route_map_process_peer (const char *rmap_name, struct peer *peer,
if (filter->map[RMAP_IN].name && if (filter->map[RMAP_IN].name &&
(strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0))
{ {
filter->map[RMAP_IN].map = filter->map[RMAP_IN].map = map;
route_map_lookup_by_name (filter->map[RMAP_IN].name);
if (route_update && peer->status == Established) if (route_update && peer->status == Established)
{ {
@ -2723,17 +2723,14 @@ bgp_route_map_process_peer (const char *rmap_name, struct peer *peer,
if (filter->map[RMAP_IMPORT].name && if (filter->map[RMAP_IMPORT].name &&
(strcmp(rmap_name, filter->map[RMAP_IMPORT].name) == 0)) (strcmp(rmap_name, filter->map[RMAP_IMPORT].name) == 0))
{ {
filter->map[RMAP_IMPORT].map = filter->map[RMAP_IMPORT].map = map;
route_map_lookup_by_name (filter->map[RMAP_IMPORT].name);
update = 1; update = 1;
} }
if (filter->map[RMAP_EXPORT].name && if (filter->map[RMAP_EXPORT].name &&
(strcmp(rmap_name, filter->map[RMAP_EXPORT].name) == 0)) (strcmp(rmap_name, filter->map[RMAP_EXPORT].name) == 0))
{ {
filter->map[RMAP_EXPORT].map = filter->map[RMAP_EXPORT].map = map;
route_map_lookup_by_name (filter->map[RMAP_EXPORT].name);
update = 1; update = 1;
} }
@ -2769,21 +2766,20 @@ bgp_route_map_process_peer (const char *rmap_name, struct peer *peer,
*/ */
if (filter->map[RMAP_OUT].name && if (filter->map[RMAP_OUT].name &&
(strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0)) (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
filter->map[RMAP_OUT].map = filter->map[RMAP_OUT].map = map;
route_map_lookup_by_name (filter->map[RMAP_OUT].name);
if (filter->usmap.name && if (filter->usmap.name &&
(strcmp(rmap_name, filter->usmap.name) == 0)) (strcmp(rmap_name, filter->usmap.name) == 0))
filter->usmap.map = route_map_lookup_by_name (filter->usmap.name); filter->usmap.map = map;
if (peer->default_rmap[afi][safi].name && if (peer->default_rmap[afi][safi].name &&
(strcmp (rmap_name, peer->default_rmap[afi][safi].name) == 0)) (strcmp (rmap_name, peer->default_rmap[afi][safi].name) == 0))
peer->default_rmap[afi][safi].map = peer->default_rmap[afi][safi].map = map;
route_map_lookup_by_name (peer->default_rmap[afi][safi].name);
} }
static void static void
bgp_route_map_update_peer_group(const char *rmap_name, struct bgp *bgp) bgp_route_map_update_peer_group(const char *rmap_name, struct route_map *map,
struct bgp *bgp)
{ {
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
@ -2807,16 +2803,22 @@ bgp_route_map_update_peer_group(const char *rmap_name, struct bgp *bgp)
{ {
if ((filter->map[direct].name) && if ((filter->map[direct].name) &&
(strcmp(rmap_name, filter->map[direct].name) == 0)) (strcmp(rmap_name, filter->map[direct].name) == 0))
filter->map[direct].map = filter->map[direct].map = map;
route_map_lookup_by_name (filter->map[direct].name);
} }
if (filter->usmap.name && if (filter->usmap.name &&
(strcmp(rmap_name, filter->usmap.name) == 0)) (strcmp(rmap_name, filter->usmap.name) == 0))
filter->usmap.map = route_map_lookup_by_name (filter->usmap.name); filter->usmap.map = map;
} }
} }
/*
* Note that if an extreme number (tens of thousands) of route-maps are in use
* and if bgp has an extreme number of peers, network statements, etc then this
* function can consume a lot of cycles. This is due to this function being
* called for each route-map and within this function we walk the list of peers,
* network statements, etc looking to see if they use this route-map.
*/
static int static int
bgp_route_map_process_update (void *arg, const char *rmap_name, int route_update) bgp_route_map_process_update (void *arg, const char *rmap_name, int route_update)
{ {
@ -2828,11 +2830,14 @@ bgp_route_map_process_update (void *arg, const char *rmap_name, int route_update
struct bgp_static *bgp_static; struct bgp_static *bgp_static;
struct bgp *bgp = (struct bgp *)arg; struct bgp *bgp = (struct bgp *)arg;
struct listnode *node, *nnode; struct listnode *node, *nnode;
struct route_map *map;
char buf[INET6_ADDRSTRLEN]; char buf[INET6_ADDRSTRLEN];
if (!bgp) if (!bgp)
return (-1); return (-1);
map = route_map_lookup_by_name (rmap_name);
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
{ {
@ -2848,7 +2853,7 @@ bgp_route_map_process_update (void *arg, const char *rmap_name, int route_update
continue; continue;
/* process in/out/import/export/default-orig route-maps */ /* process in/out/import/export/default-orig route-maps */
bgp_route_map_process_peer(rmap_name, peer, afi, safi, route_update); bgp_route_map_process_peer(rmap_name, map, peer, afi, safi, route_update);
} }
} }
@ -2857,49 +2862,46 @@ bgp_route_map_process_update (void *arg, const char *rmap_name, int route_update
route_update, 0); route_update, 0);
/* update peer-group config (template) */ /* update peer-group config (template) */
bgp_route_map_update_peer_group(rmap_name, bgp); bgp_route_map_update_peer_group(rmap_name, map, bgp);
/* For table route-map updates. */
for (afi = AFI_IP; afi < AFI_MAX; afi++) for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
{ {
/* For table route-map updates. */
if (bgp->table_map[afi][safi].name && if (bgp->table_map[afi][safi].name &&
(strcmp(rmap_name, bgp->table_map[afi][safi].name) == 0)) (strcmp(rmap_name, bgp->table_map[afi][safi].name) == 0))
{ {
bgp->table_map[afi][safi].map = bgp->table_map[afi][safi].map = map;
route_map_lookup_by_name (bgp->table_map[afi][safi].name);
if (BGP_DEBUG (zebra, ZEBRA)) if (BGP_DEBUG (zebra, ZEBRA))
zlog_debug("Processing route_map %s update on " zlog_debug("Processing route_map %s update on "
"table map", rmap_name); "table map", rmap_name);
if (route_update) if (route_update)
bgp_zebra_announce_table(bgp, afi, safi); bgp_zebra_announce_table(bgp, afi, safi);
} }
}
/* For network route-map updates. */ /* For network route-map updates. */
for (afi = AFI_IP; afi < AFI_MAX; afi++) for (bn = bgp_table_top (bgp->route[afi][safi]); bn; bn = bgp_route_next (bn))
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) if ((bgp_static = bn->info) != NULL)
for (bn = bgp_table_top (bgp->route[afi][safi]); bn; {
bn = bgp_route_next (bn)) if (bgp_static->rmap.name &&
if ((bgp_static = bn->info) != NULL) (strcmp(rmap_name, bgp_static->rmap.name) == 0))
{ {
if (bgp_static->rmap.name && bgp_static->rmap.map = map;
(strcmp(rmap_name, bgp_static->rmap.name) == 0))
{ if (route_update)
bgp_static->rmap.map = if (!bgp_static->backdoor)
route_map_lookup_by_name (bgp_static->rmap.name); {
if (route_update) if (bgp_debug_zebra(&bn->p))
if (!bgp_static->backdoor) zlog_debug("Processing route_map %s update on "
{ "static route %s", rmap_name,
if (bgp_debug_zebra(&bn->p)) inet_ntop (bn->p.family, &bn->p.u.prefix,
zlog_debug("Processing route_map %s update on " buf, INET6_ADDRSTRLEN));
"static route %s", rmap_name, bgp_static_update (bgp, &bn->p, bgp_static, afi, safi);
inet_ntop (bn->p.family, &bn->p.u.prefix, }
buf, INET6_ADDRSTRLEN)); }
bgp_static_update (bgp, &bn->p, bgp_static, afi, safi); }
} }
}
}
/* For redistribute route-map updates. */ /* For redistribute route-map updates. */
for (afi = AFI_IP; afi < AFI_MAX; afi++) for (afi = AFI_IP; afi < AFI_MAX; afi++)
@ -2918,8 +2920,7 @@ bgp_route_map_process_update (void *arg, const char *rmap_name, int route_update
if (red->rmap.name && if (red->rmap.name &&
(strcmp(rmap_name, red->rmap.name) == 0)) (strcmp(rmap_name, red->rmap.name) == 0))
{ {
red->rmap.map = red->rmap.map = map;
route_map_lookup_by_name (red->rmap.name);
if (route_update) if (route_update)
{ {

View File

@ -1719,9 +1719,6 @@ update_group_adjust_soloness (struct peer *peer, int set)
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (peer_group_active (peer))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
{ {
peer_lonesoul_or_not (peer, set); peer_lonesoul_or_not (peer, set);

View File

@ -48,6 +48,7 @@
PEER_FLAG_REMOVE_PRIVATE_AS | \ PEER_FLAG_REMOVE_PRIVATE_AS | \
PEER_FLAG_REMOVE_PRIVATE_AS_ALL | \ PEER_FLAG_REMOVE_PRIVATE_AS_ALL | \
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE | \ PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE | \
PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE | \
PEER_FLAG_AS_OVERRIDE) PEER_FLAG_AS_OVERRIDE)
#define PEER_UPDGRP_CAP_FLAGS (PEER_CAP_AS4_RCV) #define PEER_UPDGRP_CAP_FLAGS (PEER_CAP_AS4_RCV)

View File

@ -57,6 +57,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
extern struct in_addr router_id_zebra; extern struct in_addr router_id_zebra;
static struct peer_group *
listen_range_exists (struct bgp *bgp, struct prefix *range, int exact);
/* Utility function to get address family from current node. */ /* Utility function to get address family from current node. */
afi_t afi_t
bgp_node_afi (struct vty *vty) bgp_node_afi (struct vty *vty)
@ -207,18 +210,9 @@ bgp_vty_return (struct vty *vty, int ret)
case BGP_ERR_INVALID_FLAG: case BGP_ERR_INVALID_FLAG:
str = "Invalid flag"; str = "Invalid flag";
break; break;
case BGP_ERR_PEER_INACTIVE:
str = "Activate the neighbor for the address family first";
break;
case BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER:
str = "Invalid command for a peer-group member";
break;
case BGP_ERR_PEER_GROUP_SHUTDOWN: case BGP_ERR_PEER_GROUP_SHUTDOWN:
str = "Peer-group has been shutdown. Activate the peer-group first"; str = "Peer-group has been shutdown. Activate the peer-group first";
break; break;
case BGP_ERR_PEER_GROUP_HAS_THE_FLAG:
str = "This peer is a peer-group member. Please change peer-group configuration";
break;
case BGP_ERR_PEER_FLAG_CONFLICT: case BGP_ERR_PEER_FLAG_CONFLICT:
str = "Can't set override-capability and strict-capability-match at the same time"; str = "Can't set override-capability and strict-capability-match at the same time";
break; break;
@ -2353,6 +2347,38 @@ DEFUN (no_bgp_listen_limit,
} }
/*
* Check if this listen range is already configured. Check for exact
* match or overlap based on input.
*/
static struct peer_group *
listen_range_exists (struct bgp *bgp, struct prefix *range, int exact)
{
struct listnode *node, *nnode;
struct listnode *node1, *nnode1;
struct peer_group *group;
struct prefix *lr;
afi_t afi;
int match;
afi = family2afi(range->family);
for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
{
for (ALL_LIST_ELEMENTS (group->listen_range[afi], node1,
nnode1, lr))
{
if (exact)
match = prefix_same (range, lr);
else
match = (prefix_match (range, lr) || prefix_match (lr, range));
if (match)
return group;
}
}
return NULL;
}
DEFUN (bgp_listen_range, DEFUN (bgp_listen_range,
bgp_listen_range_cmd, bgp_listen_range_cmd,
LISTEN_RANGE_CMD "peer-group WORD" , LISTEN_RANGE_CMD "peer-group WORD" ,
@ -2363,7 +2389,7 @@ DEFUN (bgp_listen_range,
{ {
struct bgp *bgp; struct bgp *bgp;
struct prefix range; struct prefix range;
struct peer_group *group; struct peer_group *group, *existing_group;
afi_t afi; afi_t afi;
int ret; int ret;
@ -2392,6 +2418,27 @@ DEFUN (bgp_listen_range,
apply_mask (&range); apply_mask (&range);
/* Check if same listen range is already configured. */
existing_group = listen_range_exists (bgp, &range, 1);
if (existing_group)
{
if (strcmp (existing_group->name, argv[1]) == 0)
return CMD_SUCCESS;
else
{
vty_out (vty, "%% Same listen range is attached to peer-group %s%s",
existing_group->name, VTY_NEWLINE);
return CMD_WARNING;
}
}
/* Check if an overlapping listen range exists. */
if (listen_range_exists (bgp, &range, 0))
{
vty_out (vty, "%% Listen range overlaps with existing listen range%s",
VTY_NEWLINE);
return CMD_WARNING;
}
group = peer_group_lookup (bgp, argv[1]); group = peer_group_lookup (bgp, argv[1]);
if (! group) if (! group)
@ -3399,8 +3446,7 @@ DEFUN (neighbor_nexthop_self_force,
{ {
return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty), return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty), bgp_node_safi (vty),
(PEER_FLAG_FORCE_NEXTHOP_SELF | PEER_FLAG_FORCE_NEXTHOP_SELF);
PEER_FLAG_NEXTHOP_SELF));
} }
DEFUN (no_neighbor_nexthop_self, DEFUN (no_neighbor_nexthop_self,
@ -3413,11 +3459,10 @@ DEFUN (no_neighbor_nexthop_self,
{ {
return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty), return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty), bgp_node_safi (vty),
(PEER_FLAG_NEXTHOP_SELF | PEER_FLAG_NEXTHOP_SELF);
PEER_FLAG_FORCE_NEXTHOP_SELF));
} }
ALIAS (no_neighbor_nexthop_self, DEFUN (no_neighbor_nexthop_self_force,
no_neighbor_nexthop_self_force_cmd, no_neighbor_nexthop_self_force_cmd,
NO_NEIGHBOR_CMD2 "next-hop-self force", NO_NEIGHBOR_CMD2 "next-hop-self force",
NO_STR NO_STR
@ -3425,6 +3470,11 @@ ALIAS (no_neighbor_nexthop_self,
NEIGHBOR_ADDR_STR2 NEIGHBOR_ADDR_STR2
"Disable the next hop calculation for this neighbor\n" "Disable the next hop calculation for this neighbor\n"
"Set the next hop to self for reflected routes\n") "Set the next hop to self for reflected routes\n")
{
return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_FORCE_NEXTHOP_SELF);
}
/* neighbor as-override */ /* neighbor as-override */
DEFUN (neighbor_as_override, DEFUN (neighbor_as_override,
@ -3460,10 +3510,6 @@ DEFUN (neighbor_remove_private_as,
NEIGHBOR_ADDR_STR2 NEIGHBOR_ADDR_STR2
"Remove private ASNs in outbound updates\n") "Remove private ASNs in outbound updates\n")
{ {
peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS_ALL|
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty), return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty), bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS); PEER_FLAG_REMOVE_PRIVATE_AS);
@ -3477,12 +3523,8 @@ DEFUN (neighbor_remove_private_as_all,
"Remove private ASNs in outbound updates\n" "Remove private ASNs in outbound updates\n"
"Apply to all AS numbers") "Apply to all AS numbers")
{ {
peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty), return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty), bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS|
PEER_FLAG_REMOVE_PRIVATE_AS_ALL); PEER_FLAG_REMOVE_PRIVATE_AS_ALL);
} }
@ -3494,12 +3536,8 @@ DEFUN (neighbor_remove_private_as_replace_as,
"Remove private ASNs in outbound updates\n" "Remove private ASNs in outbound updates\n"
"Replace private ASNs with our ASN in outbound updates\n") "Replace private ASNs with our ASN in outbound updates\n")
{ {
peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS_ALL);
return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty), return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty), bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS|
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE); PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
} }
@ -3514,9 +3552,7 @@ DEFUN (neighbor_remove_private_as_all_replace_as,
{ {
return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty), return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty), bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS| PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE);
PEER_FLAG_REMOVE_PRIVATE_AS_ALL|
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
} }
DEFUN (no_neighbor_remove_private_as, DEFUN (no_neighbor_remove_private_as,
@ -3529,12 +3565,10 @@ DEFUN (no_neighbor_remove_private_as,
{ {
return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty), return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty), bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS| PEER_FLAG_REMOVE_PRIVATE_AS);
PEER_FLAG_REMOVE_PRIVATE_AS_ALL|
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
} }
ALIAS (no_neighbor_remove_private_as, DEFUN (no_neighbor_remove_private_as_all,
no_neighbor_remove_private_as_all_cmd, no_neighbor_remove_private_as_all_cmd,
NO_NEIGHBOR_CMD2 "remove-private-AS all", NO_NEIGHBOR_CMD2 "remove-private-AS all",
NO_STR NO_STR
@ -3542,8 +3576,13 @@ ALIAS (no_neighbor_remove_private_as,
NEIGHBOR_ADDR_STR2 NEIGHBOR_ADDR_STR2
"Remove private ASNs in outbound updates\n" "Remove private ASNs in outbound updates\n"
"Apply to all AS numbers") "Apply to all AS numbers")
{
return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS_ALL);
}
ALIAS (no_neighbor_remove_private_as, DEFUN (no_neighbor_remove_private_as_replace_as,
no_neighbor_remove_private_as_replace_as_cmd, no_neighbor_remove_private_as_replace_as_cmd,
NO_NEIGHBOR_CMD2 "remove-private-AS replace-AS", NO_NEIGHBOR_CMD2 "remove-private-AS replace-AS",
NO_STR NO_STR
@ -3551,8 +3590,13 @@ ALIAS (no_neighbor_remove_private_as,
NEIGHBOR_ADDR_STR2 NEIGHBOR_ADDR_STR2
"Remove private ASNs in outbound updates\n" "Remove private ASNs in outbound updates\n"
"Replace private ASNs with our ASN in outbound updates\n") "Replace private ASNs with our ASN in outbound updates\n")
{
return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE);
}
ALIAS (no_neighbor_remove_private_as, DEFUN (no_neighbor_remove_private_as_all_replace_as,
no_neighbor_remove_private_as_all_replace_as_cmd, no_neighbor_remove_private_as_all_replace_as_cmd,
NO_NEIGHBOR_CMD2 "remove-private-AS all replace-AS", NO_NEIGHBOR_CMD2 "remove-private-AS all replace-AS",
NO_STR NO_STR
@ -3561,6 +3605,11 @@ ALIAS (no_neighbor_remove_private_as,
"Remove private ASNs in outbound updates\n" "Remove private ASNs in outbound updates\n"
"Apply to all AS numbers" "Apply to all AS numbers"
"Replace private ASNs with our ASN in outbound updates\n") "Replace private ASNs with our ASN in outbound updates\n")
{
return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
bgp_node_safi (vty),
PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE);
}
/* neighbor send-community. */ /* neighbor send-community. */
@ -9153,8 +9202,12 @@ bgp_show_peer_afi (struct vty *vty, struct peer *p, afi_t afi, safi_t safi,
if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
json_object_boolean_true_add(json_addr, "inboundSoftConfigPermit"); json_object_boolean_true_add(json_addr, "inboundSoftConfigPermit");
if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
json_object_boolean_true_add(json_addr, "privateAsNumsAllReplacedInUpdatesToNbr");
else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
json_object_boolean_true_add(json_addr, "privateAsNumsReplacedInUpdatesToNbr"); json_object_boolean_true_add(json_addr, "privateAsNumsReplacedInUpdatesToNbr");
else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_ALL))
json_object_boolean_true_add(json_addr, "privateAsNumsAllRemovedInUpdatesToNbr");
else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS)) else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS))
json_object_boolean_true_add(json_addr, "privateAsNumsRemovedInUpdatesToNbr"); json_object_boolean_true_add(json_addr, "privateAsNumsRemovedInUpdatesToNbr");
@ -9336,8 +9389,12 @@ bgp_show_peer_afi (struct vty *vty, struct peer *p, afi_t afi, safi_t safi,
if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
vty_out (vty, " Inbound soft reconfiguration allowed%s", VTY_NEWLINE); vty_out (vty, " Inbound soft reconfiguration allowed%s", VTY_NEWLINE);
if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
vty_out (vty, " Private AS numbers (all) replaced in updates to this neighbor%s", VTY_NEWLINE);
else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
vty_out (vty, " Private AS numbers replaced in updates to this neighbor%s", VTY_NEWLINE); vty_out (vty, " Private AS numbers replaced in updates to this neighbor%s", VTY_NEWLINE);
else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_ALL))
vty_out (vty, " Private AS numbers (all) removed in updates to this neighbor%s", VTY_NEWLINE);
else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS)) else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS))
vty_out (vty, " Private AS numbers removed in updates to this neighbor%s", VTY_NEWLINE); vty_out (vty, " Private AS numbers removed in updates to this neighbor%s", VTY_NEWLINE);

View File

@ -438,6 +438,7 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
struct in_addr nexthop; struct in_addr nexthop;
struct prefix_ipv4 p; struct prefix_ipv4 p;
unsigned int ifindex; unsigned int ifindex;
int i;
s = zclient->ibuf; s = zclient->ibuf;
nexthop.s_addr = 0; nexthop.s_addr = 0;
@ -497,6 +498,20 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
api.metric, api.metric,
api.tag); api.tag);
} }
/*
* The ADD message is actually an UPDATE and there is no explicit DEL
* for a prior redistributed route, if any. So, perform an implicit
* DEL processing for the same redistributed route from any other
* source type.
*/
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
{
if (i != api.type)
bgp_redistribute_delete((struct prefix *)&p, i, api.instance);
}
/* Now perform the add/update. */
bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL, ifindex, bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL, ifindex,
api.metric, api.type, api.instance, api.tag); api.metric, api.type, api.instance, api.tag);
} }
@ -530,6 +545,7 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length)
struct in6_addr nexthop; struct in6_addr nexthop;
struct prefix_ipv6 p; struct prefix_ipv6 p;
unsigned int ifindex; unsigned int ifindex;
int i;
s = zclient->ibuf; s = zclient->ibuf;
memset (&nexthop, 0, sizeof (struct in6_addr)); memset (&nexthop, 0, sizeof (struct in6_addr));
@ -595,6 +611,19 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length)
api.metric, api.metric,
api.tag); api.tag);
} }
/*
* The ADD message is actually an UPDATE and there is no explicit DEL
* for a prior redistributed route, if any. So, perform an implicit
* DEL processing for the same redistributed route from any other
* source type.
*/
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
{
if (i != api.type)
bgp_redistribute_delete((struct prefix *)&p, i, api.instance);
}
bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop, ifindex, bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop, ifindex,
api.metric, api.type, api.instance, api.tag); api.metric, api.type, api.instance, api.tag);
} }
@ -1709,9 +1738,6 @@ bgp_zebra_init (struct thread_master *master)
zclient->nexthop_update = bgp_read_nexthop_update; zclient->nexthop_update = bgp_read_nexthop_update;
zclient->import_check_update = bgp_read_import_check_update; zclient->import_check_update = bgp_read_import_check_update;
/* Interface related init. */
if_init ();
bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE); bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE);
bgp_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE); bgp_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE);
} }

View File

@ -722,6 +722,35 @@ peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
return CHECK_FLAG (peer->af_flags[afi][safi], flag); return CHECK_FLAG (peer->af_flags[afi][safi], flag);
} }
/* Return true if flag is set for the peer but not the peer-group */
static int
peergroup_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
{
struct peer *g_peer = NULL;
if (peer_af_flag_check (peer, afi, safi, flag))
{
if (peer_group_active (peer))
{
g_peer = peer->group->conf;
/* If this flag is not set for the peer's peer-group then return true */
if (!peer->af_group[afi][safi] || !peer_af_flag_check (g_peer, afi, safi, flag))
{
return 1;
}
}
/* peer is not in a peer-group but the flag is set to return true */
else
{
return 1;
}
}
return 0;
}
/* Reset all address family specific configuration. */ /* Reset all address family specific configuration. */
static void static void
peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi) peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
@ -1694,7 +1723,7 @@ peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
/* De-activate the address family configuration. */ /* De-activate the address family configuration. */
peer->afc[afi][safi] = 0; peer->afc[afi][safi] = 0;
peer_af_flag_reset (peer, afi, safi);
if (peer_af_delete(peer, afi, safi) != 0) if (peer_af_delete(peer, afi, safi) != 0)
{ {
zlog_err("couldn't delete af structure for peer %s", peer->host); zlog_err("couldn't delete af structure for peer %s", peer->host);
@ -3448,6 +3477,7 @@ static const struct peer_flag_action peer_af_flag_action_list[] =
{ PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out }, { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
{ PEER_FLAG_FORCE_NEXTHOP_SELF, 1, peer_change_reset_out }, { PEER_FLAG_FORCE_NEXTHOP_SELF, 1, peer_change_reset_out },
{ PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out }, { PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out },
{ PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE,1, peer_change_reset_out },
{ 0, 0, 0 } { 0, 0, 0 }
}; };
@ -3570,10 +3600,6 @@ peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
if (! found) if (! found)
return BGP_ERR_INVALID_FLAG; return BGP_ERR_INVALID_FLAG;
/* Not for peer-group member. */
if (action.not_for_member && peer_group_active (peer))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
/* When unset the peer-group member's flag we have to check /* When unset the peer-group member's flag we have to check
peer-group configuration. */ peer-group configuration. */
if (! set && peer_group_active (peer)) if (! set && peer_group_active (peer))
@ -3581,8 +3607,6 @@ peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
{ {
if (flag == PEER_FLAG_SHUTDOWN) if (flag == PEER_FLAG_SHUTDOWN)
return BGP_ERR_PEER_GROUP_SHUTDOWN; return BGP_ERR_PEER_GROUP_SHUTDOWN;
else
return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
} }
/* Flag conflict check. */ /* Flag conflict check. */
@ -3646,14 +3670,6 @@ peer_flag_unset (struct peer *peer, u_int32_t flag)
return peer_flag_modify (peer, flag, 0); return peer_flag_modify (peer, flag, 0);
} }
static int
peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
{
if (peer->af_group[afi][safi])
return 1;
return 0;
}
static int static int
peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag, peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
int set) int set)
@ -3673,20 +3689,12 @@ peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
if (! found) if (! found)
return BGP_ERR_INVALID_FLAG; return BGP_ERR_INVALID_FLAG;
/* Adress family must be activated. */ /* Special check for reflector client. */
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
/* Not for peer-group member. */
if (action.not_for_member && peer_is_group_member (peer, afi, safi))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
/* Spcecial check for reflector client. */
if (flag & PEER_FLAG_REFLECTOR_CLIENT if (flag & PEER_FLAG_REFLECTOR_CLIENT
&& peer_sort (peer) != BGP_PEER_IBGP) && peer_sort (peer) != BGP_PEER_IBGP)
return BGP_ERR_NOT_INTERNAL_PEER; return BGP_ERR_NOT_INTERNAL_PEER;
/* Spcecial check for remove-private-AS. */ /* Special check for remove-private-AS. */
if (flag & PEER_FLAG_REMOVE_PRIVATE_AS if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
&& peer_sort (peer) == BGP_PEER_IBGP) && peer_sort (peer) == BGP_PEER_IBGP)
return BGP_ERR_REMOVE_PRIVATE_AS; return BGP_ERR_REMOVE_PRIVATE_AS;
@ -3696,12 +3704,6 @@ peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
&& peer_sort (peer) == BGP_PEER_IBGP) && peer_sort (peer) == BGP_PEER_IBGP)
return BGP_ERR_AS_OVERRIDE; return BGP_ERR_AS_OVERRIDE;
/* When unset the peer-group member's flag we have to check
peer-group configuration. */
if (! set && peer->af_group[afi][safi])
if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
/* When current flag configuration is same as requested one. */ /* When current flag configuration is same as requested one. */
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
{ {
@ -4162,14 +4164,6 @@ peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
/* Adress family must be activated. */
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
/* Default originate can't be used for peer group memeber. */
if (peer_is_group_member (peer, afi, safi))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE) if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
|| (rmap && ! peer->default_rmap[afi][safi].name) || (rmap && ! peer->default_rmap[afi][safi].name)
|| (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0)) || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
@ -4224,14 +4218,6 @@ peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
/* Adress family must be activated. */
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
/* Default originate can't be used for peer group memeber. */
if (peer_is_group_member (peer, afi, safi))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
{ {
UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE); UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
@ -4339,10 +4325,6 @@ peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
/* Not for peer group memeber. */
if (peer_group_active (peer))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
/* keepalive value check. */ /* keepalive value check. */
if (keepalive > 65535) if (keepalive > 65535)
return BGP_ERR_INVALID_VALUE; return BGP_ERR_INVALID_VALUE;
@ -4380,9 +4362,6 @@ peer_timers_unset (struct peer *peer)
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (peer_group_active (peer))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
/* Clear configuration. */ /* Clear configuration. */
UNSET_FLAG (peer->config, PEER_CONFIG_TIMER); UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
peer->keepalive = 0; peer->keepalive = 0;
@ -4409,9 +4388,6 @@ peer_timers_connect_set (struct peer *peer, u_int32_t connect)
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (peer_group_active (peer))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
if (connect > 65535) if (connect > 65535)
return BGP_ERR_INVALID_VALUE; return BGP_ERR_INVALID_VALUE;
@ -4442,9 +4418,6 @@ peer_timers_connect_unset (struct peer *peer)
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (peer_group_active (peer))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
/* Clear configuration. */ /* Clear configuration. */
UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT); UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
peer->connect = 0; peer->connect = 0;
@ -4472,9 +4445,6 @@ peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (peer_group_active (peer))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
if (routeadv > 600) if (routeadv > 600)
return BGP_ERR_INVALID_VALUE; return BGP_ERR_INVALID_VALUE;
@ -4510,9 +4480,6 @@ peer_advertise_interval_unset (struct peer *peer)
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (peer_group_active (peer))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV); UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
peer->routeadv = 0; peer->routeadv = 0;
@ -4640,9 +4607,6 @@ peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
if (bgp->as == as) if (bgp->as == as)
return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS; return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
if (peer_group_active (peer))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
if (peer->as == as) if (peer->as == as)
return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS; return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
@ -4710,9 +4674,6 @@ peer_local_as_unset (struct peer *peer)
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (peer_group_active (peer))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
if (! peer->change_local_as) if (! peer->change_local_as)
return 0; return 0;
@ -4822,11 +4783,6 @@ peer_password_unset (struct peer *peer)
if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
{ {
if (peer_group_active (peer)
&& peer->group->conf->password
&& strcmp (peer->group->conf->password, peer->password) == 0)
return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
else else
@ -4903,15 +4859,9 @@ peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
if (direct != FILTER_IN && direct != FILTER_OUT) if (direct != FILTER_IN && direct != FILTER_OUT)
return BGP_ERR_INVALID_VALUE; return BGP_ERR_INVALID_VALUE;
if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
filter = &peer->filter[afi][safi]; filter = &peer->filter[afi][safi];
if (filter->plist[direct].name) if (filter->plist[direct].name)
@ -4956,15 +4906,9 @@ peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
if (direct != FILTER_IN && direct != FILTER_OUT) if (direct != FILTER_IN && direct != FILTER_OUT)
return BGP_ERR_INVALID_VALUE; return BGP_ERR_INVALID_VALUE;
if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
filter = &peer->filter[afi][safi]; filter = &peer->filter[afi][safi];
/* apply peer-group filter */ /* apply peer-group filter */
@ -5080,15 +5024,9 @@ peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
if (direct != FILTER_IN && direct != FILTER_OUT) if (direct != FILTER_IN && direct != FILTER_OUT)
return BGP_ERR_INVALID_VALUE; return BGP_ERR_INVALID_VALUE;
if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
filter = &peer->filter[afi][safi]; filter = &peer->filter[afi][safi];
if (filter->dlist[direct].name) if (filter->dlist[direct].name)
@ -5132,15 +5070,9 @@ peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
if (direct != FILTER_IN && direct != FILTER_OUT) if (direct != FILTER_IN && direct != FILTER_OUT)
return BGP_ERR_INVALID_VALUE; return BGP_ERR_INVALID_VALUE;
if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
filter = &peer->filter[afi][safi]; filter = &peer->filter[afi][safi];
/* apply peer-group filter */ /* apply peer-group filter */
@ -5259,15 +5191,9 @@ peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
if (direct != FILTER_IN && direct != FILTER_OUT) if (direct != FILTER_IN && direct != FILTER_OUT)
return BGP_ERR_INVALID_VALUE; return BGP_ERR_INVALID_VALUE;
if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
filter = &peer->filter[afi][safi]; filter = &peer->filter[afi][safi];
if (filter->aslist[direct].name) if (filter->aslist[direct].name)
@ -5308,15 +5234,9 @@ peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
if (direct != FILTER_IN && direct != FILTER_OUT) if (direct != FILTER_IN && direct != FILTER_OUT)
return BGP_ERR_INVALID_VALUE; return BGP_ERR_INVALID_VALUE;
if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
filter = &peer->filter[afi][safi]; filter = &peer->filter[afi][safi];
/* apply peer-group filter */ /* apply peer-group filter */
@ -5445,17 +5365,10 @@ peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
if (direct != RMAP_IN && direct != RMAP_OUT && if (direct != RMAP_IN && direct != RMAP_OUT &&
direct != RMAP_IMPORT && direct != RMAP_EXPORT) direct != RMAP_IMPORT && direct != RMAP_EXPORT)
return BGP_ERR_INVALID_VALUE; return BGP_ERR_INVALID_VALUE;
if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
&& peer_is_group_member (peer, afi, safi))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
filter = &peer->filter[afi][safi]; filter = &peer->filter[afi][safi];
if (filter->map[direct].name) if (filter->map[direct].name)
@ -5498,17 +5411,10 @@ peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
if (direct != RMAP_IN && direct != RMAP_OUT && if (direct != RMAP_IN && direct != RMAP_OUT &&
direct != RMAP_IMPORT && direct != RMAP_EXPORT) direct != RMAP_IMPORT && direct != RMAP_EXPORT)
return BGP_ERR_INVALID_VALUE; return BGP_ERR_INVALID_VALUE;
if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
&& peer_is_group_member (peer, afi, safi))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
filter = &peer->filter[afi][safi]; filter = &peer->filter[afi][safi];
/* apply peer-group filter */ /* apply peer-group filter */
@ -5567,12 +5473,6 @@ peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
if (peer_is_group_member (peer, afi, safi))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
filter = &peer->filter[afi][safi]; filter = &peer->filter[afi][safi];
if (filter->usmap.name) if (filter->usmap.name)
@ -5612,12 +5512,6 @@ peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
if (peer_is_group_member (peer, afi, safi))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
filter = &peer->filter[afi][safi]; filter = &peer->filter[afi][safi];
if (filter->usmap.name) if (filter->usmap.name)
@ -5656,9 +5550,6 @@ peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
peer->pmax[afi][safi] = max; peer->pmax[afi][safi] = max;
peer->pmax_threshold[afi][safi] = threshold; peer->pmax_threshold[afi][safi] = threshold;
@ -5704,9 +5595,6 @@ peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
struct peer_group *group; struct peer_group *group;
struct listnode *node, *nnode; struct listnode *node, *nnode;
if (! peer->afc[afi][safi])
return BGP_ERR_PEER_INACTIVE;
/* apply peer-group config */ /* apply peer-group config */
if (peer->af_group[afi][safi]) if (peer->af_group[afi][safi])
{ {
@ -6141,9 +6029,35 @@ peer_uptime (time_t uptime2, char *buf, size_t len, u_char use_json, json_object
return buf; return buf;
} }
static void
afi_header_vty_out (struct vty *vty, afi_t afi, safi_t safi,
int *write, const char *format, ...)
{
va_list args;
int len = 0;
char buf[1024];
bgp_config_write_family_header (vty, afi, safi, write);
if (vty_shell (vty))
{
va_start (args, format);
vprintf (format, args);
va_end (args);
}
else
{
va_start (args, format);
len = vsnprintf (buf, sizeof(buf), format, args);
va_end (args);
buffer_put (vty->obuf, (u_char *) buf, len);
}
}
static void static void
bgp_config_write_filter (struct vty *vty, struct peer *peer, bgp_config_write_filter (struct vty *vty, struct peer *peer,
afi_t afi, safi_t safi) afi_t afi, safi_t safi, int *write)
{ {
struct bgp_filter *filter; struct bgp_filter *filter;
struct bgp_filter *gfilter = NULL; struct bgp_filter *gfilter = NULL;
@ -6160,55 +6074,93 @@ bgp_config_write_filter (struct vty *vty, struct peer *peer,
if (filter->dlist[in].name) if (filter->dlist[in].name)
if (! gfilter || ! gfilter->dlist[in].name if (! gfilter || ! gfilter->dlist[in].name
|| strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0) || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
vty_out (vty, " neighbor %s distribute-list %s in%s", addr, {
filter->dlist[in].name, VTY_NEWLINE); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s distribute-list %s in%s",
addr, filter->dlist[in].name, VTY_NEWLINE);
}
if (filter->dlist[out].name && ! gfilter) if (filter->dlist[out].name && ! gfilter)
vty_out (vty, " neighbor %s distribute-list %s out%s", addr, {
filter->dlist[out].name, VTY_NEWLINE); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s distribute-list %s out%s",
addr, filter->dlist[out].name, VTY_NEWLINE);
}
/* prefix-list. */ /* prefix-list. */
if (filter->plist[in].name) if (filter->plist[in].name)
if (! gfilter || ! gfilter->plist[in].name if (! gfilter || ! gfilter->plist[in].name
|| strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0) || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
vty_out (vty, " neighbor %s prefix-list %s in%s", addr, {
filter->plist[in].name, VTY_NEWLINE); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s prefix-list %s in%s",
addr, filter->plist[in].name, VTY_NEWLINE);
}
if (filter->plist[out].name && ! gfilter) if (filter->plist[out].name && ! gfilter)
vty_out (vty, " neighbor %s prefix-list %s out%s", addr, {
filter->plist[out].name, VTY_NEWLINE); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s prefix-list %s out%s",
addr, filter->plist[out].name, VTY_NEWLINE);
}
/* route-map. */ /* route-map. */
if (filter->map[RMAP_IN].name) if (filter->map[RMAP_IN].name)
if (! gfilter || ! gfilter->map[RMAP_IN].name if (! gfilter || ! gfilter->map[RMAP_IN].name
|| strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0) || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
vty_out (vty, " neighbor %s route-map %s in%s", addr, {
filter->map[RMAP_IN].name, VTY_NEWLINE); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s route-map %s in%s",
addr, filter->map[RMAP_IN].name, VTY_NEWLINE);
}
if (filter->map[RMAP_OUT].name && ! gfilter) if (filter->map[RMAP_OUT].name && ! gfilter)
vty_out (vty, " neighbor %s route-map %s out%s", addr, {
filter->map[RMAP_OUT].name, VTY_NEWLINE); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s route-map %s out%s",
addr, filter->map[RMAP_OUT].name, VTY_NEWLINE);
}
if (filter->map[RMAP_IMPORT].name && ! gfilter) if (filter->map[RMAP_IMPORT].name && ! gfilter)
vty_out (vty, " neighbor %s route-map %s import%s", addr, {
filter->map[RMAP_IMPORT].name, VTY_NEWLINE); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s route-map %s import%s",
addr, filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
}
if (filter->map[RMAP_EXPORT].name) if (filter->map[RMAP_EXPORT].name)
if (! gfilter || ! gfilter->map[RMAP_EXPORT].name if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
|| strcmp (filter->map[RMAP_EXPORT].name, || strcmp (filter->map[RMAP_EXPORT].name, gfilter->map[RMAP_EXPORT].name) != 0)
gfilter->map[RMAP_EXPORT].name) != 0) {
vty_out (vty, " neighbor %s route-map %s export%s", addr, afi_header_vty_out (vty, afi, safi, write,
filter->map[RMAP_EXPORT].name, VTY_NEWLINE); " neighbor %s route-map %s export%s",
addr, filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
}
/* unsuppress-map */ /* unsuppress-map */
if (filter->usmap.name && ! gfilter) if (filter->usmap.name && ! gfilter)
vty_out (vty, " neighbor %s unsuppress-map %s%s", addr, {
filter->usmap.name, VTY_NEWLINE); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s unsuppress-map %s%s",
addr, filter->usmap.name, VTY_NEWLINE);
}
/* filter-list. */ /* filter-list. */
if (filter->aslist[in].name) if (filter->aslist[in].name)
if (! gfilter || ! gfilter->aslist[in].name if (! gfilter || ! gfilter->aslist[in].name
|| strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0) || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
vty_out (vty, " neighbor %s filter-list %s in%s", addr, {
filter->aslist[in].name, VTY_NEWLINE); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s filter-list %s in%s",
addr, filter->aslist[in].name, VTY_NEWLINE);
}
if (filter->aslist[out].name && ! gfilter) if (filter->aslist[out].name && ! gfilter)
vty_out (vty, " neighbor %s filter-list %s out%s", addr, {
filter->aslist[out].name, VTY_NEWLINE); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s filter-list %s out%s",
addr, filter->aslist[out].name, VTY_NEWLINE);
}
} }
/* BGP peer configuration display function. */ /* BGP peer configuration display function. */
@ -6446,6 +6398,7 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
} }
if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) && if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
peer->connect != BGP_DEFAULT_CONNECT_RETRY &&
! peer_group_active (peer)) ! peer_group_active (peer))
{ {
vty_out (vty, " neighbor %s timers connect %d%s", addr, vty_out (vty, " neighbor %s timers connect %d%s", addr,
@ -6518,11 +6471,11 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
} }
} }
/* BGP peer configuration display function. */ /* BGP peer configuration display function. */
static void static void
bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp,
struct peer *peer, afi_t afi, safi_t safi) struct peer *peer, afi_t afi, safi_t safi,
int *write)
{ {
struct peer *g_peer = NULL; struct peer *g_peer = NULL;
char *addr; char *addr;
@ -6543,22 +6496,31 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp,
****** Per AF to the neighbor ****** ****** Per AF to the neighbor ******
************************************/ ************************************/
if (peer->af_group[afi][safi]) if (peer->af_group[afi][safi])
vty_out (vty, " neighbor %s peer-group %s%s", addr, {
peer->group->name, VTY_NEWLINE); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s peer-group %s%s", addr,
peer->group->name, VTY_NEWLINE);
}
else else
vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE); if (peer->afc[afi][safi])
{
afi_header_vty_out (vty, afi, safi, write,
" neighbor %s activate%s",
addr, VTY_NEWLINE);
}
/* ORF capability. */ /* ORF capability. */
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM) if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) ||
|| CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM))
if (! peer->af_group[afi][safi])
{ {
vty_out (vty, " neighbor %s capability orf prefix-list", addr); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s capability orf prefix-list",
addr);
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM) if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) &&
&& CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM))
vty_out (vty, " both"); vty_out (vty, " both");
else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)) else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM))
vty_out (vty, " send"); vty_out (vty, " send");
else else
vty_out (vty, " receive"); vty_out (vty, " receive");
@ -6566,87 +6528,138 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp,
} }
/* Route reflector client. */ /* Route reflector client. */
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT) if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT))
&& ! peer->af_group[afi][safi]) {
vty_out (vty, " neighbor %s route-reflector-client%s", addr, afi_header_vty_out (vty, afi, safi, write,
VTY_NEWLINE); " neighbor %s route-reflector-client%s",
addr, VTY_NEWLINE);
}
/* Nexthop self. */ /* next-hop-self force */
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_FORCE_NEXTHOP_SELF) if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_FORCE_NEXTHOP_SELF))
&& ! peer->af_group[afi][safi]) {
vty_out (vty, " neighbor %s next-hop-self force%s", afi_header_vty_out (vty, afi, safi, write,
addr, VTY_NEWLINE); " neighbor %s next-hop-self force%s",
else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF) addr, VTY_NEWLINE);
&& ! peer->af_group[afi][safi]) }
vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
/* next-hop-self */
if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF))
{
afi_header_vty_out (vty, afi, safi, write,
" neighbor %s next-hop-self%s",
addr, VTY_NEWLINE);
}
/* remove-private-AS */ /* remove-private-AS */
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS) && !peer->af_group[afi][safi]) if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
{ {
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL) && afi_header_vty_out (vty, afi, safi, write,
peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) " neighbor %s remove-private-AS all replace-AS%s",
vty_out (vty, " neighbor %s remove-private-AS all replace-AS%s", addr, VTY_NEWLINE); addr, VTY_NEWLINE);
}
else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
vty_out (vty, " neighbor %s remove-private-AS replace-AS%s", addr, VTY_NEWLINE); {
afi_header_vty_out (vty, afi, safi, write,
" neighbor %s remove-private-AS replace-AS%s",
addr, VTY_NEWLINE);
}
else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL))
vty_out (vty, " neighbor %s remove-private-AS all%s", addr, VTY_NEWLINE); {
afi_header_vty_out (vty, afi, safi, write,
" neighbor %s remove-private-AS all%s",
addr, VTY_NEWLINE);
}
else else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS))
vty_out (vty, " neighbor %s remove-private-AS%s", addr, VTY_NEWLINE); {
afi_header_vty_out (vty, afi, safi, write,
" neighbor %s remove-private-AS%s",
addr, VTY_NEWLINE);
} }
/* as-override */ /* as-override */
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE) && if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE))
!peer->af_group[afi][safi]) {
vty_out (vty, " neighbor %s as-override%s", addr, VTY_NEWLINE); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s as-override%s",
addr, VTY_NEWLINE);
}
/* send-community print. */ /* send-community print. */
if (! peer->af_group[afi][safi]) if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
{ {
if (bgp_option_check (BGP_OPT_CONFIG_CISCO)) if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
{ && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) {
&& peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) afi_header_vty_out (vty, afi, safi, write,
vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE); " neighbor %s send-community both%s",
else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) addr, VTY_NEWLINE);
vty_out (vty, " neighbor %s send-community extended%s", }
addr, VTY_NEWLINE); else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)) {
vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE); afi_header_vty_out (vty, afi, safi, write,
} " neighbor %s send-community extended%s",
else addr, VTY_NEWLINE);
{ }
if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
&& ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) {
vty_out (vty, " no neighbor %s send-community both%s", afi_header_vty_out (vty, afi, safi, write,
addr, VTY_NEWLINE); " neighbor %s send-community%s",
else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) addr, VTY_NEWLINE);
vty_out (vty, " no neighbor %s send-community extended%s", }
addr, VTY_NEWLINE); }
else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)) else
vty_out (vty, " no neighbor %s send-community%s", {
addr, VTY_NEWLINE); if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) &&
} peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) &&
!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) &&
peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
{
afi_header_vty_out (vty, afi, safi, write,
" no neighbor %s send-community both%s",
addr, VTY_NEWLINE);
}
else if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) &&
peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
{
afi_header_vty_out (vty, afi, safi, write,
" no neighbor %s send-community extended%s",
addr, VTY_NEWLINE);
}
else if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) &&
peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
{
afi_header_vty_out (vty, afi, safi, write,
" no neighbor %s send-community%s",
addr, VTY_NEWLINE);
}
} }
/* Default information */ /* Default information */
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE) if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE) ||
&& ! peer->af_group[afi][safi]) (g_peer &&
((peer->default_rmap[afi][safi].name && !g_peer->default_rmap[afi][safi].name) ||
(!peer->default_rmap[afi][safi].name && g_peer->default_rmap[afi][safi].name) ||
(peer->default_rmap[afi][safi].name &&
strcmp(peer->default_rmap[afi][safi].name, g_peer->default_rmap[afi][safi].name)))))
{ {
vty_out (vty, " neighbor %s default-originate", addr); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s default-originate", addr);
if (peer->default_rmap[afi][safi].name) if (peer->default_rmap[afi][safi].name)
vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name); vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
vty_out (vty, "%s", VTY_NEWLINE); vty_out (vty, "%s", VTY_NEWLINE);
} }
/* Soft reconfiguration inbound. */ /* Soft reconfiguration inbound. */
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SOFT_RECONFIG))
if (! peer->af_group[afi][safi] || {
! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) afi_header_vty_out (vty, afi, safi, write,
vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr, " neighbor %s soft-reconfiguration inbound%s",
VTY_NEWLINE); addr, VTY_NEWLINE);
}
/* maximum-prefix. */ /* maximum-prefix. */
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
@ -6656,7 +6669,9 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp,
|| CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING) || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
!= CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
{ {
vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s maximum-prefix %ld",
addr, peer->pmax[afi][safi]);
if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT) if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
vty_out (vty, " %d", peer->pmax_threshold[afi][safi]); vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
@ -6667,14 +6682,20 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp,
} }
/* Route server client. */ /* Route server client. */
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_RSERVER_CLIENT))
&& ! peer->af_group[afi][safi]) {
vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s route-server-client%s",
addr, VTY_NEWLINE);
}
/* Nexthop-local unchanged. */ /* Nexthop-local unchanged. */
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED))
&& ! peer->af_group[afi][safi]) {
vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE); afi_header_vty_out (vty, afi, safi, write,
" neighbor %s nexthop-local unchanged%s",
addr, VTY_NEWLINE);
}
/* Allow AS in. */ /* Allow AS in. */
if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN)) if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
@ -6683,33 +6704,46 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp,
|| peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi]) || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
{ {
if (peer->allowas_in[afi][safi] == 3) if (peer->allowas_in[afi][safi] == 3)
vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE); {
else afi_header_vty_out (vty, afi, safi, write,
vty_out (vty, " neighbor %s allowas-in %d%s", addr, " neighbor %s allowas-in%s",
peer->allowas_in[afi][safi], VTY_NEWLINE); addr, VTY_NEWLINE);
}
else
{
afi_header_vty_out (vty, afi, safi, write,
" neighbor %s allowas-in %d%s",
addr, peer->allowas_in[afi][safi], VTY_NEWLINE);
}
} }
/* Filter. */ /* Filter. */
bgp_config_write_filter (vty, peer, afi, safi); bgp_config_write_filter (vty, peer, afi, safi, write);
/* atribute-unchanged. */ /* atribute-unchanged. */
if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED) if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
|| CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED) || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
|| CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
&& ! peer->af_group[afi][safi])
{ {
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED) if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED)
&& CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED) && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED)
&& CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED))
vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE); {
afi_header_vty_out (vty, afi, safi, write,
" neighbor %s attribute-unchanged%s",
addr, VTY_NEWLINE);
}
else else
vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr, {
(CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ? afi_header_vty_out (vty, afi, safi, write,
" as-path" : "", " neighbor %s attribute-unchanged%s%s%s%s", addr,
(CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ? peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ?
" next-hop" : "", " as-path" : "",
(CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ? peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) ?
" med" : "", VTY_NEWLINE); " next-hop" : "",
peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED) ?
" med" : "", VTY_NEWLINE);
}
} }
} }
@ -6760,27 +6794,17 @@ bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
bgp_config_write_redistribute (vty, bgp, afi, safi, &write); bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
{ bgp_config_write_peer_af (vty, bgp, group->conf, afi, safi, &write);
if (group->conf->afc[afi][safi])
{
bgp_config_write_family_header (vty, afi, safi, &write);
bgp_config_write_peer_af (vty, bgp, group->conf, afi, safi);
}
}
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
{ {
/* Skip dynamic neighbors. */ /* Skip dynamic neighbors. */
if (peer_dynamic_neighbor (peer)) if (peer_dynamic_neighbor (peer))
continue; continue;
if (peer->afc[afi][safi]) /* Do not display doppelganger peers */
{ if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE))
if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)) bgp_config_write_peer_af (vty, bgp, peer, afi, safi, &write);
{
bgp_config_write_family_header (vty, afi, safi, &write);
bgp_config_write_peer_af (vty, bgp, peer, afi, safi);
}
}
} }
bgp_config_write_maxpaths (vty, bgp, afi, safi, &write); bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);

View File

@ -647,6 +647,7 @@ struct peer
#define PEER_FLAG_REMOVE_PRIVATE_AS_ALL (1 << 18) /* remove-private-as all */ #define PEER_FLAG_REMOVE_PRIVATE_AS_ALL (1 << 18) /* remove-private-as all */
#define PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE (1 << 19) /* remove-private-as replace-as */ #define PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE (1 << 19) /* remove-private-as replace-as */
#define PEER_FLAG_AS_OVERRIDE (1 << 20) /* as-override */ #define PEER_FLAG_AS_OVERRIDE (1 << 20) /* as-override */
#define PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE (1 << 21) /* remove-private-as all replace-as */
/* MD5 password */ /* MD5 password */
char *password; char *password;
@ -1068,30 +1069,27 @@ enum bgp_clear_type
#define BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT -13 #define BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT -13
#define BGP_ERR_MULTIPLE_INSTANCE_NOT_SET -14 #define BGP_ERR_MULTIPLE_INSTANCE_NOT_SET -14
#define BGP_ERR_AS_MISMATCH -15 #define BGP_ERR_AS_MISMATCH -15
#define BGP_ERR_PEER_INACTIVE -16 #define BGP_ERR_PEER_FLAG_CONFLICT -16
#define BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER -17 #define BGP_ERR_PEER_GROUP_SHUTDOWN -17
#define BGP_ERR_PEER_GROUP_HAS_THE_FLAG -18 #define BGP_ERR_PEER_FILTER_CONFLICT -18
#define BGP_ERR_PEER_FLAG_CONFLICT -19 #define BGP_ERR_NOT_INTERNAL_PEER -19
#define BGP_ERR_PEER_GROUP_SHUTDOWN -20 #define BGP_ERR_REMOVE_PRIVATE_AS -20
#define BGP_ERR_PEER_FILTER_CONFLICT -21 #define BGP_ERR_AF_UNCONFIGURED -21
#define BGP_ERR_NOT_INTERNAL_PEER -22 #define BGP_ERR_SOFT_RECONFIG_UNCONFIGURED -22
#define BGP_ERR_REMOVE_PRIVATE_AS -23 #define BGP_ERR_INSTANCE_MISMATCH -23
#define BGP_ERR_AF_UNCONFIGURED -24 #define BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP -24
#define BGP_ERR_SOFT_RECONFIG_UNCONFIGURED -25 #define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS -25
#define BGP_ERR_INSTANCE_MISMATCH -26 #define BGP_ERR_TCPSIG_FAILED -26
#define BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP -27 #define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK -27
#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS -28 #define BGP_ERR_NO_IBGP_WITH_TTLHACK -28
#define BGP_ERR_TCPSIG_FAILED -29 #define BGP_ERR_NO_INTERFACE_CONFIG -29
#define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK -30 #define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS -30
#define BGP_ERR_NO_IBGP_WITH_TTLHACK -31 #define BGP_ERR_AS_OVERRIDE -31
#define BGP_ERR_NO_INTERFACE_CONFIG -32 #define BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT -32
#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS -33 #define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS -33
#define BGP_ERR_AS_OVERRIDE -34 #define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND -34
#define BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT -35 #define BGP_ERR_INVALID_FOR_DYNAMIC_PEER -35
#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS -36 #define BGP_ERR_MAX -36
#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND -37
#define BGP_ERR_INVALID_FOR_DYNAMIC_PEER -38
#define BGP_ERR_MAX -39
/* /*
* Enumeration of different policy kinds a peer can be configured with. * Enumeration of different policy kinds a peer can be configured with.

View File

@ -78,12 +78,12 @@ When the program terminates, retain routes added by \fBbgpd\fR.
Print the version and exit. Print the version and exit.
.SH FILES .SH FILES
.TP .TP
.BI /usr/local/sbin/bgpd .BI /usr/lib/quagga/bgpd
The default location of the The default location of the
.B bgpd .B bgpd
binary. binary.
.TP .TP
.BI /usr/local/etc/bgpd.conf .BI /etc/quagga/bgpd.conf
The default location of the The default location of the
.B bgpd .B bgpd
config file. config file.

View File

@ -67,12 +67,12 @@ Specify the user to run as. Default is \fIquagga\fR.
Print the version and exit. Print the version and exit.
.SH FILES .SH FILES
.TP .TP
.BI /usr/local/sbin/isisd .BI /usr/lib/quagga/isisd
The default location of the The default location of the
.B isisd .B isisd
binary. binary.
.TP .TP
.BI /usr/local/etc/isisd.conf .BI /etc/quagga/isisd.conf
The default location of the The default location of the
.B isisd .B isisd
config file. config file.

View File

@ -68,12 +68,12 @@ Specify the user to run as. Default is \fIquagga\fR.
Print the version and exit. Print the version and exit.
.SH FILES .SH FILES
.TP .TP
.BI /usr/local/sbin/ospf6d .BI /usr/lib/quagga/ospf6d
The default location of the The default location of the
.B ospf6d .B ospf6d
binary. binary.
.TP .TP
.BI /usr/local/etc/ospf6d.conf .BI /etc/quagga/ospf6d.conf
The default location of the The default location of the
.B ospf6d .B ospf6d
config file. config file.

View File

@ -70,12 +70,12 @@ Enable OSPF apiserver. Default is disabled.
Print the version and exit. Print the version and exit.
.SH FILES .SH FILES
.TP .TP
.BI /usr/local/sbin/ospfd .BI /usr/lib/quagga/ospfd
The default location of the The default location of the
.B ospfd .B ospfd
binary. binary.
.TP .TP
.BI /usr/local/etc/ospfd.conf .BI /etc/quagga/ospfd.conf
The default location of the The default location of the
.B ospfd .B ospfd
config file. config file.

View File

@ -71,12 +71,12 @@ When the program terminates, retain routes added by \fBripd\fR.
Print the version and exit. Print the version and exit.
.SH FILES .SH FILES
.TP .TP
.BI /usr/local/sbin/ripd .BI /usr/lib/quagga/ripd
The default location of the The default location of the
.B ripd .B ripd
binary. binary.
.TP .TP
.BI /usr/local/etc/ripd.conf .BI /etc/quagga/ripd.conf
The default location of the The default location of the
.B ripd .B ripd
config file. config file.

View File

@ -71,12 +71,12 @@ When the program terminates, retain routes added by \fBripd\fR.
Print the version and exit. Print the version and exit.
.SH FILES .SH FILES
.TP .TP
.BI /usr/local/sbin/ripngd .BI /usr/lib/quagga/ripngd
The default location of the The default location of the
.B ripngd .B ripngd
binary. binary.
.TP .TP
.BI /usr/local/etc/ripngd.conf .BI /etc/quagga/ripngd.conf
The default location of the The default location of the
.B ripngd .B ripngd
config file. config file.

View File

@ -68,12 +68,12 @@ Display a usage message on standard output and exit.
This should be the name of the pager to use. Default is \fBmore\fR. This should be the name of the pager to use. Default is \fBmore\fR.
.SH FILES .SH FILES
.TP .TP
.BI /usr/local/etc/vtysh.conf .BI /etc/quagga/vtysh.conf
The default location of the The default location of the
.B vtysh .B vtysh
config file. config file.
.TP .TP
.BI /usr/local/etc/Quagga.conf .BI /etc/quagga/Quagga.conf
The default location of the integrated Quagga routing engine config file The default location of the integrated Quagga routing engine config file
if integrated config file is in use (not default). if integrated config file is in use (not default).
.SH WARNING .SH WARNING

View File

@ -90,12 +90,12 @@ Note that this affects Linux only.
Print the version and exit. Print the version and exit.
.SH FILES .SH FILES
.TP .TP
.BI /usr/local/sbin/zebra .BI /usr/lib/quagga/zebra
The default location of the The default location of the
.B zebra .B zebra
binary. binary.
.TP .TP
.BI /usr/local/etc/zebra.conf .BI /etc/quagga/zebra.conf
The default location of the The default location of the
.B zebra .B zebra
config file. config file.

View File

@ -2739,7 +2739,6 @@ void
isis_circuit_init () isis_circuit_init ()
{ {
/* Initialize Zebra interface data structure */ /* Initialize Zebra interface data structure */
if_init ();
if_add_hook (IF_NEW_HOOK, isis_if_new_hook); if_add_hook (IF_NEW_HOOK, isis_if_new_hook);
if_add_hook (IF_DELETE_HOOK, isis_if_delete_hook); if_add_hook (IF_DELETE_HOOK, isis_if_delete_hook);

View File

@ -35,6 +35,7 @@
#include "sigevent.h" #include "sigevent.h"
#include "filter.h" #include "filter.h"
#include "zclient.h" #include "zclient.h"
#include "vrf.h"
#include "isisd/dict.h" #include "isisd/dict.h"
#include "include-netbsd/iso.h" #include "include-netbsd/iso.h"
@ -335,6 +336,7 @@ main (int argc, char **argv, char **envp)
vty_init (master); vty_init (master);
memory_init (); memory_init ();
access_list_init(); access_list_init();
vrf_init ();
isis_init (); isis_init ();
isis_circuit_init (); isis_circuit_init ();
isis_spf_cmds_init (); isis_spf_cmds_init ();

View File

@ -14,7 +14,7 @@ libzebra_la_SOURCES = \
filter.c routemap.c distribute.c stream.c str.c log.c plist.c \ filter.c routemap.c distribute.c stream.c str.c log.c plist.c \
zclient.c sockopt.c smux.c agentx.c snmp.c md5.c if_rmap.c keychain.c privs.c \ zclient.c sockopt.c smux.c agentx.c snmp.c md5.c if_rmap.c keychain.c privs.c \
sigevent.c pqueue.c jhash.c memtypes.c workqueue.c nexthop.c json.c \ sigevent.c pqueue.c jhash.c memtypes.c workqueue.c nexthop.c json.c \
ptm_lib.c csv.c bfd.c ptm_lib.c csv.c bfd.c vrf.c
BUILT_SOURCES = memtypes.h route_types.h gitversion.h BUILT_SOURCES = memtypes.h route_types.h gitversion.h
@ -30,7 +30,7 @@ pkginclude_HEADERS = \
plist.h zclient.h sockopt.h smux.h md5.h if_rmap.h keychain.h \ plist.h zclient.h sockopt.h smux.h md5.h if_rmap.h keychain.h \
privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \ privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \
workqueue.h route_types.h libospf.h nexthop.h json.h \ workqueue.h route_types.h libospf.h nexthop.h json.h \
ptm_lib.h csv.h bfd.h ptm_lib.h csv.h bfd.h vrf.h
EXTRA_DIST = \ EXTRA_DIST = \
regex.c regex-gnu.h \ regex.c regex-gnu.h \

259
lib/if.c
View File

@ -27,6 +27,7 @@
#include "vector.h" #include "vector.h"
#include "vty.h" #include "vty.h"
#include "command.h" #include "command.h"
#include "vrf.h"
#include "if.h" #include "if.h"
#include "sockunion.h" #include "sockunion.h"
#include "prefix.h" #include "prefix.h"
@ -36,7 +37,7 @@
#include "str.h" #include "str.h"
#include "log.h" #include "log.h"
/* Master list of interfaces. */ /* List of interfaces in only the default VRF */
struct list *iflist; struct list *iflist;
int ptm_enable = 0; int ptm_enable = 0;
@ -45,7 +46,7 @@ struct if_master
{ {
int (*if_new_hook) (struct interface *); int (*if_new_hook) (struct interface *);
int (*if_delete_hook) (struct interface *); int (*if_delete_hook) (struct interface *);
} if_master; } if_master = {0,};
/* Compare interface names, returning an integer greater than, equal to, or /* Compare interface names, returning an integer greater than, equal to, or
* less than 0, (following the strcmp convention), according to the * less than 0, (following the strcmp convention), according to the
@ -114,9 +115,10 @@ if_cmp_func (struct interface *ifp1, struct interface *ifp2)
/* Create new interface structure. */ /* Create new interface structure. */
struct interface * struct interface *
if_create (const char *name, int namelen) if_create_vrf (const char *name, int namelen, vrf_id_t vrf_id)
{ {
struct interface *ifp; struct interface *ifp;
struct list *intf_list = vrf_iflist_get (vrf_id);
ifp = XCALLOC (MTYPE_IF, sizeof (struct interface)); ifp = XCALLOC (MTYPE_IF, sizeof (struct interface));
ifp->ifindex = IFINDEX_INTERNAL; ifp->ifindex = IFINDEX_INTERNAL;
@ -125,11 +127,12 @@ if_create (const char *name, int namelen)
assert (namelen <= INTERFACE_NAMSIZ); /* Need space for '\0' at end. */ assert (namelen <= INTERFACE_NAMSIZ); /* Need space for '\0' at end. */
strncpy (ifp->name, name, namelen); strncpy (ifp->name, name, namelen);
ifp->name[namelen] = '\0'; ifp->name[namelen] = '\0';
if (if_lookup_by_name(ifp->name) == NULL) ifp->vrf_id = vrf_id;
listnode_add_sort (iflist, ifp); if (if_lookup_by_name_vrf (ifp->name, vrf_id) == NULL)
listnode_add_sort (intf_list, ifp);
else else
zlog_err("if_create(%s): corruption detected -- interface with this " zlog_err("if_create(%s): corruption detected -- interface with this "
"name exists already!", ifp->name); "name exists already in VRF %u!", ifp->name, vrf_id);
ifp->connected = list_new (); ifp->connected = list_new ();
ifp->connected->del = (void (*) (void *)) connected_free; ifp->connected->del = (void (*) (void *)) connected_free;
@ -145,6 +148,12 @@ if_create (const char *name, int namelen)
return ifp; return ifp;
} }
struct interface *
if_create (const char *name, int namelen)
{
return if_create_vrf (name, namelen, VRF_DEFAULT);
}
/* Delete interface structure. */ /* Delete interface structure. */
void void
if_delete_retain (struct interface *ifp) if_delete_retain (struct interface *ifp)
@ -163,7 +172,7 @@ if_delete_retain (struct interface *ifp)
void void
if_delete (struct interface *ifp) if_delete (struct interface *ifp)
{ {
listnode_delete (iflist, ifp); listnode_delete (vrf_iflist (ifp->vrf_id), ifp);
if_delete_retain(ifp); if_delete_retain(ifp);
@ -191,12 +200,12 @@ if_add_hook (int type, int (*func)(struct interface *ifp))
/* Interface existance check by index. */ /* Interface existance check by index. */
struct interface * struct interface *
if_lookup_by_index (unsigned int index) if_lookup_by_index_vrf (unsigned int index, vrf_id_t vrf_id)
{ {
struct listnode *node; struct listnode *node;
struct interface *ifp; struct interface *ifp;
for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
{ {
if (ifp->ifindex == index) if (ifp->ifindex == index)
return ifp; return ifp;
@ -204,33 +213,51 @@ if_lookup_by_index (unsigned int index)
return NULL; return NULL;
} }
struct interface *
if_lookup_by_index (unsigned int index)
{
return if_lookup_by_index_vrf (index, VRF_DEFAULT);
}
const char * const char *
ifindex2ifname (unsigned int index) ifindex2ifname_vrf (unsigned int index, vrf_id_t vrf_id)
{ {
struct interface *ifp; struct interface *ifp;
return ((ifp = if_lookup_by_index(index)) != NULL) ? return ((ifp = if_lookup_by_index_vrf (index, vrf_id)) != NULL) ?
ifp->name : "unknown"; ifp->name : "unknown";
} }
const char *
ifindex2ifname (unsigned int index)
{
return ifindex2ifname_vrf (index, VRF_DEFAULT);
}
unsigned int
ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id)
{
struct interface *ifp;
return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp->ifindex
: IFINDEX_INTERNAL;
}
unsigned int unsigned int
ifname2ifindex (const char *name) ifname2ifindex (const char *name)
{ {
struct interface *ifp; return ifname2ifindex_vrf (name, VRF_DEFAULT);
return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp->ifindex
: IFINDEX_INTERNAL;
} }
/* Interface existance check by interface name. */ /* Interface existance check by interface name. */
struct interface * struct interface *
if_lookup_by_name (const char *name) if_lookup_by_name_vrf (const char *name, vrf_id_t vrf_id)
{ {
struct listnode *node; struct listnode *node;
struct interface *ifp; struct interface *ifp;
if (name) if (name)
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
{ {
if (strcmp(name, ifp->name) == 0) if (strcmp(name, ifp->name) == 0)
return ifp; return ifp;
@ -239,7 +266,13 @@ if_lookup_by_name (const char *name)
} }
struct interface * struct interface *
if_lookup_by_name_len(const char *name, size_t namelen) if_lookup_by_name (const char *name)
{
return if_lookup_by_name_vrf (name, VRF_DEFAULT);
}
struct interface *
if_lookup_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id)
{ {
struct listnode *node; struct listnode *node;
struct interface *ifp; struct interface *ifp;
@ -247,7 +280,7 @@ if_lookup_by_name_len(const char *name, size_t namelen)
if (namelen > INTERFACE_NAMSIZ) if (namelen > INTERFACE_NAMSIZ)
return NULL; return NULL;
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
{ {
if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0')) if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0'))
return ifp; return ifp;
@ -255,9 +288,15 @@ if_lookup_by_name_len(const char *name, size_t namelen)
return NULL; return NULL;
} }
struct interface *
if_lookup_by_name_len(const char *name, size_t namelen)
{
return if_lookup_by_name_len_vrf (name, namelen, VRF_DEFAULT);
}
/* Lookup interface by IPv4 address. */ /* Lookup interface by IPv4 address. */
struct interface * struct interface *
if_lookup_exact_address (void *src, int family) if_lookup_exact_address_vrf (void *src, int family, vrf_id_t vrf_id)
{ {
struct listnode *node; struct listnode *node;
struct listnode *cnode; struct listnode *cnode;
@ -265,7 +304,7 @@ if_lookup_exact_address (void *src, int family)
struct prefix *p; struct prefix *p;
struct connected *c; struct connected *c;
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
{ {
for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
{ {
@ -289,9 +328,15 @@ if_lookup_exact_address (void *src, int family)
return NULL; return NULL;
} }
struct interface *
if_lookup_exact_address (void *src, int family)
{
return if_lookup_exact_address_vrf (src, family, VRF_DEFAULT);
}
/* Lookup interface by IPv4 address. */ /* Lookup interface by IPv4 address. */
struct interface * struct interface *
if_lookup_address (void *matchaddr, int family) if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id)
{ {
struct listnode *node; struct listnode *node;
struct prefix addr; struct prefix addr;
@ -316,7 +361,7 @@ if_lookup_address (void *matchaddr, int family)
match = NULL; match = NULL;
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
{ {
for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
{ {
@ -332,6 +377,12 @@ if_lookup_address (void *matchaddr, int family)
return match; return match;
} }
struct interface *
if_lookup_address (void *matchaddr, int family)
{
return if_lookup_address_vrf (matchaddr, family, VRF_DEFAULT);
}
/* Lookup anchor interface by IPv4 address. */ /* Lookup anchor interface by IPv4 address. */
struct connected * struct connected *
if_anchor_lookup_by_address (struct in_addr src) if_anchor_lookup_by_address (struct in_addr src)
@ -364,14 +415,14 @@ if_anchor_lookup_by_address (struct in_addr src)
/* Lookup interface by prefix */ /* Lookup interface by prefix */
struct interface * struct interface *
if_lookup_prefix (struct prefix *prefix) if_lookup_prefix_vrf (struct prefix *prefix, vrf_id_t vrf_id)
{ {
struct listnode *node; struct listnode *node;
struct listnode *cnode; struct listnode *cnode;
struct interface *ifp; struct interface *ifp;
struct connected *c; struct connected *c;
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
{ {
for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
{ {
@ -384,24 +435,42 @@ if_lookup_prefix (struct prefix *prefix)
return NULL; return NULL;
} }
struct interface *
if_lookup_prefix (struct prefix *prefix)
{
return if_lookup_prefix_vrf (prefix, VRF_DEFAULT);
}
/* Get interface by name if given name interface doesn't exist create /* Get interface by name if given name interface doesn't exist create
one. */ one. */
struct interface * struct interface *
if_get_by_name (const char *name) if_get_by_name_vrf (const char *name, vrf_id_t vrf_id)
{ {
struct interface *ifp; struct interface *ifp;
return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp : return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp :
if_create(name, strlen(name)); if_create_vrf (name, strlen(name), vrf_id);
} }
struct interface * struct interface *
if_get_by_name_len(const char *name, size_t namelen) if_get_by_name (const char *name)
{
return if_get_by_name_vrf (name, VRF_DEFAULT);
}
struct interface *
if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id)
{ {
struct interface *ifp; struct interface *ifp;
return ((ifp = if_lookup_by_name_len(name, namelen)) != NULL) ? ifp : return ((ifp = if_lookup_by_name_len_vrf (name, namelen, vrf_id)) != NULL) ? \
if_create(name, namelen); ifp : if_create_vrf (name, namelen, vrf_id);
}
struct interface *
if_get_by_name_len (const char *name, size_t namelen)
{
return if_get_by_name_len_vrf (name, namelen, VRF_DEFAULT);
} }
/* Does interface up ? */ /* Does interface up ? */
@ -521,12 +590,12 @@ if_flag_dump (unsigned long flag)
static void static void
if_dump (const struct interface *ifp) if_dump (const struct interface *ifp)
{ {
zlog_info ("Interface %s index %d metric %d mtu %d " zlog_info ("Interface %s vrf %u index %d metric %d mtu %d "
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
"mtu6 %d " "mtu6 %d "
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
"%s", "%s",
ifp->name, ifp->ifindex, ifp->metric, ifp->mtu, ifp->name, ifp->vrf_id, ifp->ifindex, ifp->metric, ifp->mtu,
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
ifp->mtu6, ifp->mtu6,
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
@ -537,11 +606,15 @@ if_dump (const struct interface *ifp)
void void
if_dump_all (void) if_dump_all (void)
{ {
struct list *intf_list;
struct listnode *node; struct listnode *node;
void *p; void *p;
vrf_iter_t iter;
for (ALL_LIST_ELEMENTS_RO (iflist, node, p)) for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
if_dump (p); if ((intf_list = vrf_iter2iflist (iter)) != NULL)
for (ALL_LIST_ELEMENTS_RO (intf_list, node, p))
if_dump (p);
} }
DEFUN (interface_desc, DEFUN (interface_desc,
@ -601,12 +674,12 @@ DEFUN (no_interface_desc,
* - no idea, just get the name in its entirety. * - no idea, just get the name in its entirety.
*/ */
static struct interface * static struct interface *
if_sunwzebra_get (const char *name, size_t nlen) if_sunwzebra_get (const char *name, size_t nlen, vrf_id_t vrf_id)
{ {
struct interface *ifp; struct interface *ifp;
size_t seppos = 0; size_t seppos = 0;
if ( (ifp = if_lookup_by_name_len(name, nlen)) != NULL) if ( (ifp = if_lookup_by_name_len_vrf (name, nlen, vrf_id)) != NULL)
return ifp; return ifp;
/* hunt the primary interface name... */ /* hunt the primary interface name... */
@ -615,9 +688,9 @@ if_sunwzebra_get (const char *name, size_t nlen)
/* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */ /* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */
if (seppos < nlen) if (seppos < nlen)
return if_get_by_name_len (name, seppos); return if_get_by_name_len_vrf (name, seppos, vrf_id);
else else
return if_get_by_name_len (name, nlen); return if_get_by_name_len_vrf (name, nlen, vrf_id);
} }
#endif /* SUNOS_5 */ #endif /* SUNOS_5 */
@ -629,6 +702,7 @@ DEFUN (interface,
{ {
struct interface *ifp; struct interface *ifp;
size_t sl; size_t sl;
vrf_id_t vrf_id = VRF_DEFAULT;
if ((sl = strlen(argv[0])) > INTERFACE_NAMSIZ) if ((sl = strlen(argv[0])) > INTERFACE_NAMSIZ)
{ {
@ -638,10 +712,13 @@ DEFUN (interface,
return CMD_WARNING; return CMD_WARNING;
} }
if (argc > 1)
VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]);
#ifdef SUNOS_5 #ifdef SUNOS_5
ifp = if_sunwzebra_get (argv[0], sl); ifp = if_sunwzebra_get (argv[0], sl, vrf_id);
#else #else
ifp = if_get_by_name_len(argv[0], sl); ifp = if_get_by_name_len_vrf (argv[0], sl, vrf_id);
#endif /* SUNOS_5 */ #endif /* SUNOS_5 */
vty->index = ifp; vty->index = ifp;
@ -650,6 +727,13 @@ DEFUN (interface,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
ALIAS (interface,
interface_vrf_cmd,
"interface IFNAME " VRF_CMD_STR,
"Select an interface to configure\n"
"Interface's name\n"
VRF_CMD_HELP_STR)
DEFUN_NOSH (no_interface, DEFUN_NOSH (no_interface,
no_interface_cmd, no_interface_cmd,
"no interface IFNAME", "no interface IFNAME",
@ -659,8 +743,12 @@ DEFUN_NOSH (no_interface,
{ {
// deleting interface // deleting interface
struct interface *ifp; struct interface *ifp;
vrf_id_t vrf_id = VRF_DEFAULT;
ifp = if_lookup_by_name (argv[0]); if (argc > 1)
VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]);
ifp = if_lookup_by_name_vrf (argv[0], vrf_id);
if (ifp == NULL) if (ifp == NULL)
{ {
@ -680,6 +768,14 @@ DEFUN_NOSH (no_interface,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
ALIAS (no_interface,
no_interface_vrf_cmd,
"no interface IFNAME " VRF_CMD_STR,
NO_STR
"Delete a pseudo interface's configuration\n"
"Interface's name\n"
VRF_CMD_HELP_STR)
/* For debug purpose. */ /* For debug purpose. */
DEFUN (show_address, DEFUN (show_address,
show_address_cmd, show_address_cmd,
@ -692,8 +788,12 @@ DEFUN (show_address,
struct interface *ifp; struct interface *ifp;
struct connected *ifc; struct connected *ifc;
struct prefix *p; struct prefix *p;
vrf_id_t vrf_id = VRF_DEFAULT;
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) if (argc > 0)
VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]);
for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
{ {
for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc)) for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
{ {
@ -707,6 +807,52 @@ DEFUN (show_address,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
ALIAS (show_address,
show_address_vrf_cmd,
"show address " VRF_CMD_STR,
SHOW_STR
"address\n"
VRF_CMD_HELP_STR)
DEFUN (show_address_vrf_all,
show_address_vrf_all_cmd,
"show address " VRF_ALL_CMD_STR,
SHOW_STR
"address\n"
VRF_ALL_CMD_HELP_STR)
{
struct list *intf_list;
struct listnode *node;
struct listnode *node2;
struct interface *ifp;
struct connected *ifc;
struct prefix *p;
vrf_iter_t iter;
for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
{
intf_list = vrf_iter2iflist (iter);
if (!intf_list || !listcount (intf_list))
continue;
vty_out (vty, "%sVRF %u%s%s", VTY_NEWLINE, vrf_iter2id (iter),
VTY_NEWLINE, VTY_NEWLINE);
for (ALL_LIST_ELEMENTS_RO (intf_list, node, ifp))
{
for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
{
p = ifc->address;
if (p->family == AF_INET)
vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
VTY_NEWLINE);
}
}
}
return CMD_SUCCESS;
}
/* Allocate connected structure. */ /* Allocate connected structure. */
struct connected * struct connected *
connected_new (void) connected_new (void)
@ -773,8 +919,8 @@ connected_log (struct connected *connected, char *str)
ifp = connected->ifp; ifp = connected->ifp;
p = connected->address; p = connected->address;
snprintf (logbuf, BUFSIZ, "%s interface %s %s %s/%d ", snprintf (logbuf, BUFSIZ, "%s interface %s vrf %u %s %s/%d ",
str, ifp->name, prefix_family_str (p), str, ifp->name, ifp->vrf_id, prefix_family_str (p),
inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
p->prefixlen); p->prefixlen);
@ -1004,35 +1150,36 @@ ifaddr_ipv4_lookup (struct in_addr *addr, unsigned int ifindex)
/* Initialize interface list. */ /* Initialize interface list. */
void void
if_init (void) if_init (vrf_id_t vrf_id, struct list **intf_list)
{ {
iflist = list_new (); *intf_list = list_new ();
#if 0 #if 0
ifaddr_ipv4_table = route_table_init (); ifaddr_ipv4_table = route_table_init ();
#endif /* ifaddr_ipv4_table */ #endif /* ifaddr_ipv4_table */
if (iflist) { (*intf_list)->cmp = (int (*)(void *, void *))if_cmp_func;
iflist->cmp = (int (*)(void *, void *))if_cmp_func;
return;
}
memset (&if_master, 0, sizeof if_master); if (vrf_id == VRF_DEFAULT)
iflist = *intf_list;
} }
void void
if_terminate (void) if_terminate (vrf_id_t vrf_id, struct list **intf_list)
{ {
for (;;) for (;;)
{ {
struct interface *ifp; struct interface *ifp;
ifp = listnode_head (iflist); ifp = listnode_head (*intf_list);
if (ifp == NULL) if (ifp == NULL)
break; break;
if_delete (ifp); if_delete (ifp);
} }
list_delete (iflist); list_delete (*intf_list);
iflist = NULL; *intf_list = NULL;
if (vrf_id == VRF_DEFAULT)
iflist = NULL;
} }

View File

@ -145,6 +145,8 @@ struct interface
#ifdef HAVE_NET_RT_IFLIST #ifdef HAVE_NET_RT_IFLIST
struct if_data stats; struct if_data stats;
#endif /* HAVE_NET_RT_IFLIST */ #endif /* HAVE_NET_RT_IFLIST */
vrf_id_t vrf_id;
}; };
/* Connected address structure. */ /* Connected address structure. */
@ -271,17 +273,38 @@ extern struct interface *if_lookup_address (void *matchaddr, int family);
extern struct interface *if_lookup_prefix (struct prefix *prefix); extern struct interface *if_lookup_prefix (struct prefix *prefix);
extern struct connected *if_anchor_lookup_by_address (struct in_addr src); extern struct connected *if_anchor_lookup_by_address (struct in_addr src);
extern struct interface *if_create_vrf (const char *name, int namelen,
vrf_id_t vrf_id);
extern struct interface *if_lookup_by_index_vrf (unsigned int,
vrf_id_t vrf_id);
extern struct interface *if_lookup_exact_address_vrf (void *matchaddr, int family,
vrf_id_t vrf_id);
extern struct interface *if_lookup_address_vrf (void *matchaddr, int family,
vrf_id_t vrf_id);
extern struct interface *if_lookup_prefix_vrf (struct prefix *prefix,
vrf_id_t vrf_id);
/* These 2 functions are to be used when the ifname argument is terminated /* These 2 functions are to be used when the ifname argument is terminated
by a '\0' character: */ by a '\0' character: */
extern struct interface *if_lookup_by_name (const char *ifname); extern struct interface *if_lookup_by_name (const char *ifname);
extern struct interface *if_get_by_name (const char *ifname); extern struct interface *if_get_by_name (const char *ifname);
extern struct interface *if_lookup_by_name_vrf (const char *ifname,
vrf_id_t vrf_id);
extern struct interface *if_get_by_name_vrf (const char *ifname,
vrf_id_t vrf_id);
/* For these 2 functions, the namelen argument should be the precise length /* For these 2 functions, the namelen argument should be the precise length
of the ifname string (not counting any optional trailing '\0' character). of the ifname string (not counting any optional trailing '\0' character).
In most cases, strnlen should be used to calculate the namelen value. */ In most cases, strnlen should be used to calculate the namelen value. */
extern struct interface *if_lookup_by_name_len(const char *ifname, extern struct interface *if_lookup_by_name_len(const char *ifname,
size_t namelen); size_t namelen);
extern struct interface *if_get_by_name_len(const char *ifname, size_t namelen); extern struct interface *if_get_by_name_len(const char *ifname,size_t namelen);
extern struct interface *if_lookup_by_name_len_vrf(const char *ifname,
size_t namelen, vrf_id_t vrf_id);
extern struct interface *if_get_by_name_len_vrf(const char *ifname,
size_t namelen, vrf_id_t vrf_id);
/* Delete the interface, but do not free the structure, and leave it in the /* Delete the interface, but do not free the structure, and leave it in the
@ -302,8 +325,8 @@ extern int if_is_broadcast (struct interface *);
extern int if_is_pointopoint (struct interface *); extern int if_is_pointopoint (struct interface *);
extern int if_is_multicast (struct interface *); extern int if_is_multicast (struct interface *);
extern void if_add_hook (int, int (*)(struct interface *)); extern void if_add_hook (int, int (*)(struct interface *));
extern void if_init (void); extern void if_init (vrf_id_t, struct list **);
extern void if_terminate (void); extern void if_terminate (vrf_id_t, struct list **);
extern void if_dump_all (void); extern void if_dump_all (void);
extern const char *if_flag_dump(unsigned long); extern const char *if_flag_dump(unsigned long);
@ -311,11 +334,13 @@ extern const char *if_flag_dump(unsigned long);
ifindex2ifname uses internal interface info, whereas if_indextoname must ifindex2ifname uses internal interface info, whereas if_indextoname must
make a system call. */ make a system call. */
extern const char *ifindex2ifname (unsigned int); extern const char *ifindex2ifname (unsigned int);
extern const char *ifindex2ifname_vrf (unsigned int, vrf_id_t vrf_id);
/* Please use ifname2ifindex instead of if_nametoindex where possible; /* Please use ifname2ifindex instead of if_nametoindex where possible;
ifname2ifindex uses internal interface info, whereas if_nametoindex must ifname2ifindex uses internal interface info, whereas if_nametoindex must
make a system call. */ make a system call. */
extern unsigned int ifname2ifindex(const char *ifname); extern unsigned int ifname2ifindex(const char *ifname);
extern unsigned int ifname2ifindex_vrf(const char *ifname, vrf_id_t vrf_id);
/* Connected address functions. */ /* Connected address functions. */
extern struct connected *connected_new (void); extern struct connected *connected_new (void);
@ -345,8 +370,12 @@ extern struct cmd_element interface_desc_cmd;
extern struct cmd_element no_interface_desc_cmd; extern struct cmd_element no_interface_desc_cmd;
extern struct cmd_element interface_cmd; extern struct cmd_element interface_cmd;
extern struct cmd_element no_interface_cmd; extern struct cmd_element no_interface_cmd;
extern struct cmd_element interface_vrf_cmd;
extern struct cmd_element no_interface_vrf_cmd;
extern struct cmd_element interface_pseudo_cmd; extern struct cmd_element interface_pseudo_cmd;
extern struct cmd_element no_interface_pseudo_cmd; extern struct cmd_element no_interface_pseudo_cmd;
extern struct cmd_element show_address_cmd; extern struct cmd_element show_address_cmd;
extern struct cmd_element show_address_vrf_cmd;
extern struct cmd_element show_address_vrf_all_cmd;
#endif /* _ZEBRA_IF_H */ #endif /* _ZEBRA_IF_H */

View File

@ -437,41 +437,28 @@ memory_init (void)
const char * const char *
mtype_memstr (char *buf, size_t len, unsigned long bytes) mtype_memstr (char *buf, size_t len, unsigned long bytes)
{ {
unsigned int t, g, m, k; unsigned int m, k;
/* easy cases */ /* easy cases */
if (!bytes) if (!bytes)
return "0 bytes"; return "0 bytes";
if (bytes == 1) if (bytes == 1)
return "1 byte"; return "1 byte";
if (sizeof (unsigned long) >= 8) /*
/* Hacked to make it not warn on ILP32 machines * When we pass the 2gb barrier mallinfo() can no longer report
* Shift will always be 40 at runtime. See below too */ * correct data so it just does something odd...
t = bytes >> (sizeof (unsigned long) >= 8 ? 40 : 0); * Reporting like Terrabytes of data. Which makes users...
else * edgy.. yes edgy that's the term for it.
t = 0; * So let's just give up gracefully
g = bytes >> 30; */
if (bytes > 0x7fffffff)
return "> 2GB";
m = bytes >> 20; m = bytes >> 20;
k = bytes >> 10; k = bytes >> 10;
if (t > 10) if (m > 10)
{
/* The shift will always be 39 at runtime.
* Just hacked to make it not warn on 'smaller' machines.
* Static compiler analysis should mean no extra code
*/
if (bytes & (1UL << (sizeof (unsigned long) >= 8 ? 39 : 0)))
t++;
snprintf (buf, len, "%4d TiB", t);
}
else if (g > 10)
{
if (bytes & (1 << 29))
g++;
snprintf (buf, len, "%d GiB", g);
}
else if (m > 10)
{ {
if (bytes & (1 << 19)) if (bytes & (1 << 19))
m++; m++;

View File

@ -73,14 +73,15 @@ struct memory_list memory_list_lib[] =
{ MTYPE_PQUEUE_DATA, "Priority queue data" }, { MTYPE_PQUEUE_DATA, "Priority queue data" },
{ MTYPE_HOST, "Host config" }, { MTYPE_HOST, "Host config" },
{ MTYPE_BFD_INFO, "BFD info" }, { MTYPE_BFD_INFO, "BFD info" },
{ MTYPE_VRF, "VRF" },
{ MTYPE_VRF_NAME, "VRF name" },
{ -1, NULL }, { -1, NULL },
}; };
struct memory_list memory_list_zebra[] = struct memory_list memory_list_zebra[] =
{ {
{ MTYPE_RTADV_PREFIX, "Router Advertisement Prefix" }, { MTYPE_RTADV_PREFIX, "Router Advertisement Prefix" },
{ MTYPE_VRF, "VRF" }, { MTYPE_ZEBRA_VRF, "ZEBRA VRF" },
{ MTYPE_VRF_NAME, "VRF name" },
{ MTYPE_NEXTHOP, "Nexthop" }, { MTYPE_NEXTHOP, "Nexthop" },
{ MTYPE_RIB, "RIB" }, { MTYPE_RIB, "RIB" },
{ MTYPE_RIB_QUEUE, "RIB process work queue" }, { MTYPE_RIB_QUEUE, "RIB process work queue" },
@ -88,6 +89,7 @@ struct memory_list memory_list_zebra[] =
{ MTYPE_RIB_DEST, "RIB destination" }, { MTYPE_RIB_DEST, "RIB destination" },
{ MTYPE_RIB_TABLE_INFO, "RIB table info" }, { MTYPE_RIB_TABLE_INFO, "RIB table info" },
{ MTYPE_RNH, "Nexthop tracking object" }, { MTYPE_RNH, "Nexthop tracking object" },
{ MTYPE_NETLINK_NAME, "Netlink name" },
{ -1, NULL }, { -1, NULL },
}; };

View File

@ -766,14 +766,15 @@ str2prefix (const char *str, struct prefix *p)
return 0; return 0;
} }
int const char *
prefix2str (const struct prefix *p, char *str, int size) prefix2str (union prefix46constptr pu, char *str, int size)
{ {
const struct prefix *p = pu.p;
char buf[BUFSIZ]; char buf[BUFSIZ];
inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ); inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ);
snprintf (str, size, "%s/%d", buf, p->prefixlen); snprintf (str, size, "%s/%d", buf, p->prefixlen);
return 0; return str;
} }
struct prefix * struct prefix *

View File

@ -179,7 +179,7 @@ extern void prefix_free (struct prefix *);
extern const char *prefix_family_str (const struct prefix *); extern const char *prefix_family_str (const struct prefix *);
extern int prefix_blen (const struct prefix *); extern int prefix_blen (const struct prefix *);
extern int str2prefix (const char *, 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_match (const struct prefix *, const struct prefix *);
extern int prefix_same (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 *); extern int prefix_cmp (const struct prefix *, const struct prefix *);

View File

@ -66,6 +66,38 @@ struct route_map_list
/* Master list of route map. */ /* Master list of route map. */
static struct route_map_list route_map_master = { NULL, NULL, NULL, NULL, NULL }; static struct route_map_list route_map_master = { NULL, NULL, NULL, NULL, NULL };
struct hash *route_map_master_hash = NULL;
static unsigned int
route_map_hash_key_make (void *p)
{
const struct route_map *map = p;
return string_hash_make (map->name);
}
static int
route_map_hash_cmp(const void *p1, const void *p2)
{
const struct route_map *map1 = p1;
const struct route_map *map2 = p2;
if (map1->deleted == map2->deleted)
{
if (map1->name && map2->name)
{
if (!strcmp (map1->name, map2->name))
{
return 1;
}
}
else if (!map1->name && !map2->name)
{
return 1;
}
}
return 0;
}
enum route_map_upd8_type enum route_map_upd8_type
{ {
@ -127,7 +159,10 @@ route_map_add (const char *name)
map = route_map_new (name); map = route_map_new (name);
list = &route_map_master; list = &route_map_master;
/* Add map to the hash */
hash_get(route_map_master_hash, map, hash_alloc_intern);
map->next = NULL; map->next = NULL;
map->prev = list->tail; map->prev = list->tail;
if (list->tail) if (list->tail)
@ -172,6 +207,7 @@ route_map_free_map (struct route_map *map)
else else
list->head = map->next; list->head = map->next;
hash_release(route_map_master_hash, map);
XFREE (MTYPE_ROUTE_MAP_NAME, map->name); XFREE (MTYPE_ROUTE_MAP_NAME, map->name);
XFREE (MTYPE_ROUTE_MAP, map); XFREE (MTYPE_ROUTE_MAP, map);
} }
@ -211,14 +247,17 @@ struct route_map *
route_map_lookup_by_name (const char *name) route_map_lookup_by_name (const char *name)
{ {
struct route_map *map; struct route_map *map;
struct route_map tmp_map;
if (!name) if (!name)
return NULL; return NULL;
for (map = route_map_master.head; map; map = map->next) // map.deleted is 0 via memset
if ((strcmp (map->name, name) == 0) && (!map->deleted)) memset(&tmp_map, 0, sizeof(struct route_map));
return map; tmp_map.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name);
return NULL; map = hash_lookup(route_map_master_hash, &tmp_map);
XFREE(MTYPE_ROUTE_MAP_NAME, tmp_map.name);
return map;
} }
int int
@ -226,17 +265,30 @@ route_map_mark_updated (const char *name, int del_later)
{ {
struct route_map *map; struct route_map *map;
int ret = -1; int ret = -1;
struct route_map tmp_map;
/* We need to do this walk manually instead of calling lookup_by_name() if (!name)
* because the lookup function doesn't return route maps marked as return (ret);
* deleted.
map = route_map_lookup_by_name(name);
/* If we did not find the routemap with deleted=0 try again
* with deleted=1
*/ */
for (map = route_map_master.head; map; map = map->next) if (!map)
if (strcmp (map->name, name) == 0) {
{ memset(&tmp_map, 0, sizeof(struct route_map));
map->to_be_processed = 1; tmp_map.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name);
ret = 0; tmp_map.deleted = 1;
} map = hash_lookup(route_map_master_hash, &tmp_map);
XFREE(MTYPE_ROUTE_MAP_NAME, tmp_map.name);
}
if (map)
{
map->to_be_processed = 1;
ret = 0;
}
return(ret); return(ret);
} }
@ -386,8 +438,12 @@ vty_show_route_map (struct vty *vty, const char *name)
} }
else else
{ {
vty_out (vty, "%%route-map %s not found%s", name, VTY_NEWLINE); if (zlog_default)
return CMD_WARNING; vty_out (vty, "%s", zlog_proto_names[zlog_default->protocol]);
if (zlog_default->instance)
vty_out (vty, " %d", zlog_default->instance);
vty_out (vty, ": 'route-map %s' not found%s", name, VTY_NEWLINE);
return CMD_SUCCESS;
} }
} }
else else
@ -1049,6 +1105,7 @@ route_map_init (void)
/* Make vector for match and set. */ /* Make vector for match and set. */
route_match_vec = vector_init (1); route_match_vec = vector_init (1);
route_set_vec = vector_init (1); route_set_vec = vector_init (1);
route_map_master_hash = hash_create(route_map_hash_key_make, route_map_hash_cmp);
} }
void void

401
lib/vrf.c Normal file
View File

@ -0,0 +1,401 @@
/*
* VRF functions.
* Copyright (C) 2014 6WIND S.A.
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2, or (at your
* option) any later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Zebra; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <zebra.h>
#include "if.h"
#include "vrf.h"
#include "prefix.h"
#include "table.h"
#include "log.h"
#include "memory.h"
#define VRF_DEFAULT_NAME "Default-IP-Routing-Table"
struct vrf
{
/* Identifier, same as the vector index */
vrf_id_t vrf_id;
/* Name */
char *name;
/* Master list of interfaces belonging to this VRF */
struct list *iflist;
/* User data */
void *info;
};
/* Holding VRF hooks */
struct vrf_master
{
int (*vrf_new_hook) (vrf_id_t, void **);
int (*vrf_delete_hook) (vrf_id_t, void **);
int (*vrf_enable_hook) (vrf_id_t, void **);
int (*vrf_disable_hook) (vrf_id_t, void **);
} vrf_master = {0,};
/* VRF table */
struct route_table *vrf_table = NULL;
static int vrf_is_enabled (struct vrf *vrf);
static int vrf_enable (struct vrf *vrf);
static void vrf_disable (struct vrf *vrf);
/* Build the table key */
static void
vrf_build_key (vrf_id_t vrf_id, struct prefix *p)
{
p->family = AF_INET;
p->prefixlen = IPV4_MAX_BITLEN;
p->u.prefix4.s_addr = vrf_id;
}
/* Get a VRF. If not found, create one. */
static struct vrf *
vrf_get (vrf_id_t vrf_id)
{
struct prefix p;
struct route_node *rn;
struct vrf *vrf;
vrf_build_key (vrf_id, &p);
rn = route_node_get (vrf_table, &p);
if (rn->info)
{
vrf = (struct vrf *)rn->info;
route_unlock_node (rn); /* get */
return vrf;
}
vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
vrf->vrf_id = vrf_id;
rn->info = vrf;
/* Initialize interfaces. */
if_init (vrf_id, &vrf->iflist);
zlog_info ("VRF %u is created.", vrf_id);
if (vrf_master.vrf_new_hook)
(*vrf_master.vrf_new_hook) (vrf_id, &vrf->info);
return vrf;
}
/* Delete a VRF. This is called in vrf_terminate(). */
static void
vrf_delete (struct vrf *vrf)
{
zlog_info ("VRF %u is to be deleted.", vrf->vrf_id);
if (vrf_is_enabled (vrf))
vrf_disable (vrf);
if (vrf_master.vrf_delete_hook)
(*vrf_master.vrf_delete_hook) (vrf->vrf_id, &vrf->info);
if_terminate (vrf->vrf_id, &vrf->iflist);
if (vrf->name)
XFREE (MTYPE_VRF_NAME, vrf->name);
XFREE (MTYPE_VRF, vrf);
}
/* Look up a VRF by identifier. */
static struct vrf *
vrf_lookup (vrf_id_t vrf_id)
{
struct prefix p;
struct route_node *rn;
struct vrf *vrf = NULL;
vrf_build_key (vrf_id, &p);
rn = route_node_lookup (vrf_table, &p);
if (rn)
{
vrf = (struct vrf *)rn->info;
route_unlock_node (rn); /* lookup */
}
return vrf;
}
/*
* Check whether the VRF is enabled - that is, whether the VRF
* is ready to allocate resources. Currently there's only one
* type of resource: socket.
*/
static int
vrf_is_enabled (struct vrf *vrf)
{
return vrf && vrf->vrf_id == VRF_DEFAULT;
}
/*
* Enable a VRF - that is, let the VRF be ready to use.
* The VRF_ENABLE_HOOK callback will be called to inform
* that they can allocate resources in this VRF.
*
* RETURN: 1 - enabled successfully; otherwise, 0.
*/
static int
vrf_enable (struct vrf *vrf)
{
/* Till now, only the default VRF can be enabled. */
if (vrf->vrf_id == VRF_DEFAULT)
{
zlog_info ("VRF %u is enabled.", vrf->vrf_id);
if (vrf_master.vrf_enable_hook)
(*vrf_master.vrf_enable_hook) (vrf->vrf_id, &vrf->info);
return 1;
}
return 0;
}
/*
* Disable a VRF - that is, let the VRF be unusable.
* The VRF_DELETE_HOOK callback will be called to inform
* that they must release the resources in the VRF.
*/
static void
vrf_disable (struct vrf *vrf)
{
if (vrf_is_enabled (vrf))
{
zlog_info ("VRF %u is to be disabled.", vrf->vrf_id);
/* Till now, nothing to be done for the default VRF. */
if (vrf_master.vrf_disable_hook)
(*vrf_master.vrf_disable_hook) (vrf->vrf_id, &vrf->info);
}
}
/* Add a VRF hook. Please add hooks before calling vrf_init(). */
void
vrf_add_hook (int type, int (*func)(vrf_id_t, void **))
{
switch (type) {
case VRF_NEW_HOOK:
vrf_master.vrf_new_hook = func;
break;
case VRF_DELETE_HOOK:
vrf_master.vrf_delete_hook = func;
break;
case VRF_ENABLE_HOOK:
vrf_master.vrf_enable_hook = func;
break;
case VRF_DISABLE_HOOK:
vrf_master.vrf_disable_hook = func;
break;
default:
break;
}
}
/* Return the iterator of the first VRF. */
vrf_iter_t
vrf_first (void)
{
struct route_node *rn;
for (rn = route_top (vrf_table); rn; rn = route_next (rn))
if (rn->info)
{
route_unlock_node (rn); /* top/next */
return (vrf_iter_t)rn;
}
return VRF_ITER_INVALID;
}
/* Return the next VRF iterator to the given iterator. */
vrf_iter_t
vrf_next (vrf_iter_t iter)
{
struct route_node *rn = NULL;
/* Lock it first because route_next() will unlock it. */
if (iter != VRF_ITER_INVALID)
rn = route_next (route_lock_node ((struct route_node *)iter));
for (; rn; rn = route_next (rn))
if (rn->info)
{
route_unlock_node (rn); /* next */
return (vrf_iter_t)rn;
}
return VRF_ITER_INVALID;
}
/* Return the VRF iterator of the given VRF ID. If it does not exist,
* the iterator of the next existing VRF is returned. */
vrf_iter_t
vrf_iterator (vrf_id_t vrf_id)
{
struct prefix p;
struct route_node *rn;
vrf_build_key (vrf_id, &p);
rn = route_node_get (vrf_table, &p);
if (rn->info)
{
/* OK, the VRF exists. */
route_unlock_node (rn); /* get */
return (vrf_iter_t)rn;
}
/* Find the next VRF. */
for (rn = route_next (rn); rn; rn = route_next (rn))
if (rn->info)
{
route_unlock_node (rn); /* next */
return (vrf_iter_t)rn;
}
return VRF_ITER_INVALID;
}
/* Obtain the VRF ID from the given VRF iterator. */
vrf_id_t
vrf_iter2id (vrf_iter_t iter)
{
struct route_node *rn = (struct route_node *) iter;
return (rn && rn->info) ? ((struct vrf *)rn->info)->vrf_id : VRF_DEFAULT;
}
/* Obtain the data pointer from the given VRF iterator. */
void *
vrf_iter2info (vrf_iter_t iter)
{
struct route_node *rn = (struct route_node *) iter;
return (rn && rn->info) ? ((struct vrf *)rn->info)->info : NULL;
}
/* Obtain the interface list from the given VRF iterator. */
struct list *
vrf_iter2iflist (vrf_iter_t iter)
{
struct route_node *rn = (struct route_node *) iter;
return (rn && rn->info) ? ((struct vrf *)rn->info)->iflist : NULL;
}
/* Get the data pointer of the specified VRF. If not found, create one. */
void *
vrf_info_get (vrf_id_t vrf_id)
{
struct vrf *vrf = vrf_get (vrf_id);
return vrf->info;
}
/* Look up the data pointer of the specified VRF. */
void *
vrf_info_lookup (vrf_id_t vrf_id)
{
struct vrf *vrf = vrf_lookup (vrf_id);
return vrf ? vrf->info : NULL;
}
/* Look up the interface list in a VRF. */
struct list *
vrf_iflist (vrf_id_t vrf_id)
{
struct vrf * vrf = vrf_lookup (vrf_id);
return vrf ? vrf->iflist : NULL;
}
/* Get the interface list of the specified VRF. Create one if not find. */
struct list *
vrf_iflist_get (vrf_id_t vrf_id)
{
struct vrf * vrf = vrf_get (vrf_id);
return vrf->iflist;
}
/* Initialize VRF module. */
void
vrf_init (void)
{
struct vrf *default_vrf;
/* Allocate VRF table. */
vrf_table = route_table_init ();
/* The default VRF always exists. */
default_vrf = vrf_get (VRF_DEFAULT);
if (!default_vrf)
{
zlog_err ("vrf_init: failed to create the default VRF!");
exit (1);
}
/* Set the default VRF name. */
default_vrf->name = XSTRDUP (MTYPE_VRF_NAME, VRF_DEFAULT_NAME);
/* Enable the default VRF. */
if (!vrf_enable (default_vrf))
{
zlog_err ("vrf_init: failed to enable the default VRF!");
exit (1);
}
}
/* Terminate VRF module. */
void
vrf_terminate (void)
{
struct route_node *rn;
struct vrf *vrf;
for (rn = route_top (vrf_table); rn; rn = route_next (rn))
if ((vrf = rn->info) != NULL)
vrf_delete (vrf);
route_table_finish (vrf_table);
vrf_table = NULL;
}
/* Create a socket for the VRF. */
int
vrf_socket (int domain, int type, int protocol, vrf_id_t vrf_id)
{
int ret = -1;
if (!vrf_is_enabled (vrf_lookup (vrf_id)))
{
errno = ENOSYS;
return -1;
}
if (vrf_id == VRF_DEFAULT)
ret = socket (domain, type, protocol);
else
errno = ENOSYS;
return ret;
}

127
lib/vrf.h Normal file
View File

@ -0,0 +1,127 @@
/*
* VRF related header.
* Copyright (C) 2014 6WIND S.A.
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2, or (at your
* option) any later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Zebra; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _ZEBRA_VRF_H
#define _ZEBRA_VRF_H
#include "linklist.h"
/* The default VRF ID */
#define VRF_DEFAULT 0
/*
* The command strings
*/
#define VRF_CMD_STR "vrf <0-65535>"
#define VRF_CMD_HELP_STR "Specify the VRF\nThe VRF ID\n"
#define VRF_ALL_CMD_STR "vrf all"
#define VRF_ALL_CMD_HELP_STR "Specify the VRF\nAll VRFs\n"
/*
* VRF hooks
*/
#define VRF_NEW_HOOK 0 /* a new VRF is just created */
#define VRF_DELETE_HOOK 1 /* a VRF is to be deleted */
#define VRF_ENABLE_HOOK 2 /* a VRF is ready to use */
#define VRF_DISABLE_HOOK 3 /* a VRF is to be unusable */
/*
* Add a specific hook to VRF module.
* @param1: hook type
* @param2: the callback function
* - param 1: the VRF ID
* - param 2: the address of the user data pointer (the user data
* can be stored in or freed from there)
*/
extern void vrf_add_hook (int, int (*)(vrf_id_t, void **));
/*
* VRF iteration
*/
typedef void * vrf_iter_t;
#define VRF_ITER_INVALID NULL /* invalid value of the iterator */
/*
* VRF iteration utilities. Example for the usage:
*
* vrf_iter_t iter = vrf_first();
* for (; iter != VRF_ITER_INVALID; iter = vrf_next (iter))
*
* or
*
* vrf_iter_t iter = vrf_iterator (<a given VRF ID>);
* for (; iter != VRF_ITER_INVALID; iter = vrf_next (iter))
*/
/* Return the iterator of the first VRF. */
extern vrf_iter_t vrf_first (void);
/* Return the next VRF iterator to the given iterator. */
extern vrf_iter_t vrf_next (vrf_iter_t);
/* Return the VRF iterator of the given VRF ID. If it does not exist,
* the iterator of the next existing VRF is returned. */
extern vrf_iter_t vrf_iterator (vrf_id_t);
/*
* VRF iterator to properties
*/
extern vrf_id_t vrf_iter2id (vrf_iter_t);
extern void *vrf_iter2info (vrf_iter_t);
extern struct list *vrf_iter2iflist (vrf_iter_t);
/*
* Utilities to obtain the user data
*/
/* Get the data pointer of the specified VRF. If not found, create one. */
extern void *vrf_info_get (vrf_id_t);
/* Look up the data pointer of the specified VRF. */
extern void *vrf_info_lookup (vrf_id_t);
/*
* Utilities to obtain the interface list
*/
/* Look up the interface list of the specified VRF. */
extern struct list *vrf_iflist (vrf_id_t);
/* Get the interface list of the specified VRF. Create one if not find. */
extern struct list *vrf_iflist_get (vrf_id_t);
/*
* VRF initializer/destructor
*/
/* Please add hooks before calling vrf_init(). */
extern void vrf_init (void);
extern void vrf_terminate (void);
/*
* VRF utilities
*/
/* Create a socket serving for the given VRF */
extern int vrf_socket (int, int, int, vrf_id_t);
#endif /*_ZEBRA_VRF_H*/

View File

@ -556,6 +556,9 @@ typedef u_int8_t safi_t;
typedef u_int16_t zebra_size_t; typedef u_int16_t zebra_size_t;
typedef u_int16_t zebra_command_t; typedef u_int16_t zebra_command_t;
/* VRF ID type. */
typedef u_int16_t vrf_id_t;
/* FIFO -- first in first out structure and macros. */ /* FIFO -- first in first out structure and macros. */
struct fifo struct fifo
{ {

View File

@ -36,6 +36,7 @@
#include "privs.h" #include "privs.h"
#include "sigevent.h" #include "sigevent.h"
#include "zclient.h" #include "zclient.h"
#include "vrf.h"
#include "ospf6d.h" #include "ospf6d.h"
#include "ospf6_top.h" #include "ospf6_top.h"
@ -151,7 +152,7 @@ ospf6_exit (int status)
ospf6_asbr_terminate (); ospf6_asbr_terminate ();
ospf6_lsa_terminate (); ospf6_lsa_terminate ();
if_terminate (); vrf_terminate ();
vty_terminate (); vty_terminate ();
cmd_terminate (); cmd_terminate ();
@ -322,7 +323,7 @@ main (int argc, char *argv[], char *envp[])
cmd_init (1); cmd_init (1);
vty_init (master); vty_init (master);
memory_init (); memory_init ();
if_init (); vrf_init ();
access_list_init (); access_list_init ();
prefix_list_init (); prefix_list_init ();

View File

@ -1269,7 +1269,6 @@ void
ospf_if_init () ospf_if_init ()
{ {
/* Initialize Zebra interface data structure. */ /* Initialize Zebra interface data structure. */
if_init ();
om->iflist = iflist; om->iflist = iflist;
if_add_hook (IF_NEW_HOOK, ospf_if_new_hook); if_add_hook (IF_NEW_HOOK, ospf_if_new_hook);
if_add_hook (IF_DELETE_HOOK, ospf_if_delete_hook); if_add_hook (IF_DELETE_HOOK, ospf_if_delete_hook);

View File

@ -39,6 +39,7 @@
#include "privs.h" #include "privs.h"
#include "sigevent.h" #include "sigevent.h"
#include "zclient.h" #include "zclient.h"
#include "vrf.h"
#include "ospfd/ospfd.h" #include "ospfd/ospfd.h"
#include "ospfd/ospf_interface.h" #include "ospfd/ospf_interface.h"
@ -300,6 +301,7 @@ main (int argc, char **argv)
debug_init (); debug_init ();
vty_init (master); vty_init (master);
memory_init (); memory_init ();
vrf_init ();
access_list_init (); access_list_init ();
prefix_list_init (); prefix_list_init ();

View File

@ -2077,7 +2077,6 @@ void
rip_if_init (void) rip_if_init (void)
{ {
/* Default initial size of interface vector. */ /* Default initial size of interface vector. */
if_init();
if_add_hook (IF_NEW_HOOK, rip_interface_new_hook); if_add_hook (IF_NEW_HOOK, rip_interface_new_hook);
if_add_hook (IF_DELETE_HOOK, rip_interface_delete_hook); if_add_hook (IF_DELETE_HOOK, rip_interface_delete_hook);

View File

@ -33,6 +33,7 @@
#include "privs.h" #include "privs.h"
#include "sigevent.h" #include "sigevent.h"
#include "zclient.h" #include "zclient.h"
#include "vrf.h"
#include "ripd/ripd.h" #include "ripd/ripd.h"
@ -280,6 +281,7 @@ main (int argc, char **argv)
vty_init (master); vty_init (master);
memory_init (); memory_init ();
keychain_init (); keychain_init ();
vrf_init ();
/* RIP related initialization. */ /* RIP related initialization. */
rip_init (); rip_init ();

View File

@ -35,6 +35,7 @@
#include "table.h" #include "table.h"
#include "thread.h" #include "thread.h"
#include "privs.h" #include "privs.h"
#include "vrf.h"
#include "ripngd/ripngd.h" #include "ripngd/ripngd.h"
#include "ripngd/ripng_debug.h" #include "ripngd/ripng_debug.h"
@ -1200,7 +1201,6 @@ void
ripng_if_init () ripng_if_init ()
{ {
/* Interface initialize. */ /* Interface initialize. */
iflist = list_new ();
if_add_hook (IF_NEW_HOOK, ripng_if_new_hook); if_add_hook (IF_NEW_HOOK, ripng_if_new_hook);
if_add_hook (IF_DELETE_HOOK, ripng_if_delete_hook); if_add_hook (IF_DELETE_HOOK, ripng_if_delete_hook);

View File

@ -34,6 +34,7 @@
#include "if.h" #include "if.h"
#include "privs.h" #include "privs.h"
#include "sigevent.h" #include "sigevent.h"
#include "vrf.h"
#include "ripngd/ripngd.h" #include "ripngd/ripngd.h"
@ -276,6 +277,7 @@ main (int argc, char **argv)
cmd_init (1); cmd_init (1);
vty_init (master); vty_init (master);
memory_init (); memory_init ();
vrf_init ();
/* RIPngd inits. */ /* RIPngd inits. */
ripng_init (); ripng_init ();

View File

@ -31,6 +31,7 @@ print <<EOF;
EOF EOF
$ignore{'"interface IFNAME"'} = "ignore"; $ignore{'"interface IFNAME"'} = "ignore";
$ignore{'"interface IFNAME " "vrf <0-65535>"'} = "ignore";
$ignore{'"ip vrf NAME"'} = "ignore"; $ignore{'"ip vrf NAME"'} = "ignore";
$ignore{'"router rip"'} = "ignore"; $ignore{'"router rip"'} = "ignore";
$ignore{'"router ripng"'} = "ignore"; $ignore{'"router ripng"'} = "ignore";

View File

@ -39,6 +39,7 @@
#include "vtysh/vtysh.h" #include "vtysh/vtysh.h"
#include "log.h" #include "log.h"
#include "bgpd/bgp_vty.h" #include "bgpd/bgp_vty.h"
#include "vrf.h"
/* Struct VTY. */ /* Struct VTY. */
struct vty *vty; struct vty *vty;
@ -1498,6 +1499,14 @@ DEFUNSH (VTYSH_INTERFACE,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
ALIAS_SH (VTYSH_ZEBRA,
vtysh_interface,
vtysh_interface_vrf_cmd,
"interface IFNAME " VRF_CMD_STR,
"Select an interface to configure\n"
"Interface's name\n"
VRF_CMD_HELP_STR)
/* TODO Implement "no interface command in isisd. */ /* TODO Implement "no interface command in isisd. */
DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D, DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D,
vtysh_no_interface_cmd, vtysh_no_interface_cmd,
@ -1506,6 +1515,14 @@ DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D,
"Delete a pseudo interface's configuration\n" "Delete a pseudo interface's configuration\n"
"Interface's name\n") "Interface's name\n")
DEFSH (VTYSH_ZEBRA,
vtysh_no_interface_vrf_cmd,
"no interface IFNAME " VRF_CMD_STR,
NO_STR
"Delete a pseudo interface's configuration\n"
"Interface's name\n"
VRF_CMD_HELP_STR)
/* TODO Implement interface description commands in ripngd, ospf6d /* TODO Implement interface description commands in ripngd, ospf6d
* and isisd. */ * and isisd. */
DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD, DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD,
@ -2823,6 +2840,8 @@ vtysh_init_vty (void)
install_element (KEYCHAIN_KEY_NODE, &key_chain_cmd); install_element (KEYCHAIN_KEY_NODE, &key_chain_cmd);
install_element (CONFIG_NODE, &vtysh_interface_cmd); install_element (CONFIG_NODE, &vtysh_interface_cmd);
install_element (CONFIG_NODE, &vtysh_no_interface_cmd); install_element (CONFIG_NODE, &vtysh_no_interface_cmd);
install_element (CONFIG_NODE, &vtysh_interface_vrf_cmd);
install_element (CONFIG_NODE, &vtysh_no_interface_vrf_cmd);
install_element (ENABLE_NODE, &vtysh_show_running_config_cmd); install_element (ENABLE_NODE, &vtysh_show_running_config_cmd);
install_element (ENABLE_NODE, &vtysh_show_running_config_daemon_cmd); install_element (ENABLE_NODE, &vtysh_show_running_config_daemon_cmd);
install_element (ENABLE_NODE, &vtysh_copy_runningconfig_startupconfig_cmd); install_element (ENABLE_NODE, &vtysh_copy_runningconfig_startupconfig_cmd);

View File

@ -209,15 +209,15 @@ connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
return; return;
rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex, 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, 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) if (IS_ZEBRA_DEBUG_RIB)
zlog_debug ("%s: calling rib_update", __func__); zlog_debug ("%s: calling rib_update", __func__);
rib_update (); rib_update (ifp->vrf_id);
} }
/* Add connected IPv4 route to the interface. */ /* Add connected IPv4 route to the interface. */
@ -327,14 +327,16 @@ connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
return; return;
/* Same logic as for connected_up_ipv4(): push the changes into the head. */ /* 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) if (IS_ZEBRA_DEBUG_RIB)
zlog_debug ("%s: calling rib_update_static", __func__); zlog_debug ("%s: calling rib_update_static", __func__);
rib_update_static (); rib_update_static (ifp->vrf_id);
} }
void void
@ -397,7 +399,7 @@ connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
if (IS_ZEBRA_DEBUG_RIB) if (IS_ZEBRA_DEBUG_RIB)
zlog_debug ("%s: calling rib_update_static", __func__); zlog_debug ("%s: calling rib_update_static", __func__);
rib_update_static(); rib_update_static(ifp->vrf_id);
} }
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
@ -420,13 +422,13 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
return; return;
#endif #endif
rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, RT_TABLE_MAIN, rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
ifp->metric, 0, SAFI_UNICAST); RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST);
if (IS_ZEBRA_DEBUG_RIB) if (IS_ZEBRA_DEBUG_RIB)
zlog_debug ("%s: calling rib_update", __func__); zlog_debug ("%s: calling rib_update", __func__);
rib_update (); rib_update (ifp->vrf_id);
} }
/* Add connected IPv6 route to the interface. */ /* 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)) if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
return; 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) if (IS_ZEBRA_DEBUG_RIB)
zlog_debug ("%s: calling rib_update_static", __func__); zlog_debug ("%s: calling rib_update_static", __func__);
rib_update_static (); rib_update_static (ifp->vrf_id);
} }
void void
@ -538,6 +541,6 @@ connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
if (IS_ZEBRA_DEBUG_RIB) if (IS_ZEBRA_DEBUG_RIB)
zlog_debug ("%s: calling rib_update_static", __func__); zlog_debug ("%s: calling rib_update_static", __func__);
rib_update_static(); rib_update_static(ifp->vrf_id);
} }
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */

View File

@ -29,8 +29,10 @@
#include "connected.h" #include "connected.h"
#include "memory.h" #include "memory.h"
#include "log.h" #include "log.h"
#include "vrf.h"
#include "zebra/interface.h" #include "zebra/interface.h"
#include "zebra/rib.h"
/* Interface looking up using infamous SIOCGIFCONF. */ /* Interface looking up using infamous SIOCGIFCONF. */
static int static int
@ -442,8 +444,13 @@ interface_info_ioctl ()
/* Lookup all interface information. */ /* Lookup all interface information. */
void 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 /* Linux can do both proc & ioctl, ioctl is the only way to get
interface aliases in 2.2 series kernels. */ interface aliases in 2.2 series kernels. */
#ifdef HAVE_PROC_NET_DEV #ifdef HAVE_PROC_NET_DEV

View File

@ -30,8 +30,10 @@
#include "memory.h" #include "memory.h"
#include "log.h" #include "log.h"
#include "privs.h" #include "privs.h"
#include "vrf.h"
#include "zebra/interface.h" #include "zebra/interface.h"
#include "zebra/rib.h"
void lifreq_set_name (struct lifreq *, const char *); void lifreq_set_name (struct lifreq *, const char *);
int if_get_flags_direct (const char *, uint64_t *, unsigned int af); 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. */ /* Lookup all interface information. */
void 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_INET);
interface_list_ioctl (AF_INET6); interface_list_ioctl (AF_INET6);
interface_list_ioctl (AF_UNSPEC); interface_list_ioctl (AF_UNSPEC);

View File

@ -27,7 +27,7 @@
/* Interface information read by netlink. */ /* Interface information read by netlink. */
void void
interface_list (void) interface_list (struct zebra_vrf *zvrf)
{ {
interface_lookup_netlink (); interface_lookup_netlink (zvrf);
} }

View File

@ -29,9 +29,15 @@
#include "memory.h" #include "memory.h"
#include "ioctl.h" #include "ioctl.h"
#include "log.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/rt.h"
#include "zebra/kernel_socket.h" #include "zebra/kernel_socket.h"
#include "zebra/rib.h"
void void
ifstat_update_sysctl (void) ifstat_update_sysctl (void)
@ -90,7 +96,7 @@ ifstat_update_sysctl (void)
/* Interface listing up function using sysctl(). */ /* Interface listing up function using sysctl(). */
void void
interface_list () interface_list (struct zebra_vrf *zvrf)
{ {
caddr_t ref, buf, end; caddr_t ref, buf, end;
size_t bufsiz; size_t bufsiz;
@ -107,6 +113,12 @@ interface_list ()
0 0
}; };
if (zvrf->vrf_id != VRF_DEFAULT)
{
zlog_warn ("interface_list: ignore VRF %u", zvrf->vrf_id);
return;
}
/* Query buffer size. */ /* Query buffer size. */
if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0)
{ {

View File

@ -32,6 +32,7 @@
#include "connected.h" #include "connected.h"
#include "log.h" #include "log.h"
#include "zclient.h" #include "zclient.h"
#include "vrf.h"
#include "zebra/interface.h" #include "zebra/interface.h"
#include "zebra/rtadv.h" #include "zebra/rtadv.h"
@ -388,21 +389,23 @@ if_add_update (struct interface *ifp)
if (if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) if (if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
{ {
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("interface %s index %d is shutdown. Won't wake it up.", zlog_debug ("interface %s vrf %u index %d is shutdown. "
ifp->name, ifp->ifindex); "Won't wake it up.",
ifp->name, ifp->vrf_id, ifp->ifindex);
return; return;
} }
if_addr_wakeup (ifp); if_addr_wakeup (ifp);
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("interface %s index %d becomes active.", zlog_debug ("interface %s vrf %u index %d becomes active.",
ifp->name, ifp->ifindex); ifp->name, ifp->vrf_id, ifp->ifindex);
} }
else else
{ {
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("interface %s index %d is added.", ifp->name, ifp->ifindex); zlog_debug ("interface %s vrf %u index %d is added.",
ifp->name, ifp->vrf_id, ifp->ifindex);
} }
} }
@ -419,8 +422,8 @@ if_delete_update (struct interface *ifp)
if (if_is_up(ifp)) if (if_is_up(ifp))
{ {
zlog_err ("interface %s index %d is still up while being deleted.", zlog_err ("interface %s vrf %u index %d is still up while being deleted.",
ifp->name, ifp->ifindex); ifp->name, ifp->vrf_id, ifp->ifindex);
return; return;
} }
@ -428,8 +431,8 @@ if_delete_update (struct interface *ifp)
UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE); UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("interface %s index %d is now inactive.", zlog_debug ("interface %s vrf %u index %d is now inactive.",
ifp->name, ifp->ifindex); ifp->name, ifp->vrf_id, ifp->ifindex);
/* Delete connected routes from the kernel. */ /* Delete connected routes from the kernel. */
if (ifp->connected) if (ifp->connected)
@ -641,7 +644,7 @@ if_up (struct interface *ifp)
ifp->name); ifp->name);
/* Examine all static routes. */ /* Examine all static routes. */
rib_update (); rib_update (ifp->vrf_id);
} }
/* Interface goes down. We have to manage different behavior of based /* Interface goes down. We have to manage different behavior of based
@ -678,7 +681,7 @@ if_down (struct interface *ifp)
zlog_debug ("%s: calling rib_update_static on interface %s down", __func__, zlog_debug ("%s: calling rib_update_static on interface %s down", __func__,
ifp->name); ifp->name);
rib_update_static (); rib_update_static (ifp->vrf_id);
if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp); if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp);
@ -846,6 +849,8 @@ if_dump_vty (struct vty *vty, struct interface *ifp)
zebra_ptm_show_status(vty, ifp); zebra_ptm_show_status(vty, ifp);
vty_out (vty, " vrf: %u%s", ifp->vrf_id, VTY_NEWLINE);
if (ifp->desc) if (ifp->desc)
vty_out (vty, " Description: %s%s", ifp->desc, vty_out (vty, " Description: %s%s", ifp->desc,
VTY_NEWLINE); VTY_NEWLINE);
@ -1029,6 +1034,13 @@ DEFUN_NOSH (zebra_interface,
return ret; return ret;
} }
ALIAS (zebra_interface,
zebra_interface_vrf_cmd,
"interface IFNAME " VRF_CMD_STR,
"Select an interface to configure\n"
"Interface's name\n"
VRF_CMD_HELP_STR)
struct cmd_node interface_node = struct cmd_node interface_node =
{ {
INTERFACE_NODE, INTERFACE_NODE,
@ -1036,16 +1048,16 @@ struct cmd_node interface_node =
1 1
}; };
/* Show all or specified interface to vty. */ /* Show all interfaces to vty. */
DEFUN (show_interface, show_interface_cmd, DEFUN (show_interface, show_interface_cmd,
"show interface [IFNAME]", "show interface",
SHOW_STR SHOW_STR
"Interface status and configuration\n" "Interface status and configuration\n")
"Inteface name\n")
{ {
struct listnode *node; struct listnode *node;
struct interface *ifp; struct interface *ifp;
vrf_id_t vrf_id = VRF_DEFAULT;
#ifdef HAVE_PROC_NET_DEV #ifdef HAVE_PROC_NET_DEV
/* If system has interface statistics via proc file system, update /* If system has interface statistics via proc file system, update
statistics. */ statistics. */
@ -1055,39 +1067,144 @@ DEFUN (show_interface, show_interface_cmd,
ifstat_update_sysctl (); ifstat_update_sysctl ();
#endif /* HAVE_NET_RT_IFLIST */ #endif /* HAVE_NET_RT_IFLIST */
/* Specified interface print. */ if (argc > 0)
if (argc != 0) VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]);
{
ifp = if_lookup_by_name (argv[0]);
if (ifp == NULL)
{
vty_out (vty, "%% Can't find interface %s%s", argv[0],
VTY_NEWLINE);
return CMD_WARNING;
}
if_dump_vty (vty, ifp);
return CMD_SUCCESS;
}
/* All interface print. */ /* All interface print. */
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
if_dump_vty (vty, ifp); if_dump_vty (vty, ifp);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN (show_interface_desc, ALIAS (show_interface,
show_interface_desc_cmd, show_interface_vrf_cmd,
"show interface description", "show interface " VRF_CMD_STR,
SHOW_STR SHOW_STR
"Interface status and configuration\n" "Interface status and configuration\n"
"Interface description\n") VRF_CMD_HELP_STR)
/* Show all interfaces to vty. */
DEFUN (show_interface_vrf_all, show_interface_vrf_all_cmd,
"show interface " VRF_ALL_CMD_STR,
SHOW_STR
"Interface status and configuration\n"
VRF_ALL_CMD_HELP_STR)
{
struct listnode *node;
struct interface *ifp;
vrf_iter_t iter;
#ifdef HAVE_PROC_NET_DEV
/* If system has interface statistics via proc file system, update
statistics. */
ifstat_update_proc ();
#endif /* HAVE_PROC_NET_DEV */
#ifdef HAVE_NET_RT_IFLIST
ifstat_update_sysctl ();
#endif /* HAVE_NET_RT_IFLIST */
/* All interface print. */
for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
for (ALL_LIST_ELEMENTS_RO (vrf_iter2iflist (iter), node, ifp))
if_dump_vty (vty, ifp);
return CMD_SUCCESS;
}
/* Show specified interface to vty. */
DEFUN (show_interface_name, show_interface_name_cmd,
"show interface IFNAME",
SHOW_STR
"Interface status and configuration\n"
"Inteface name\n")
{
struct interface *ifp;
vrf_id_t vrf_id = VRF_DEFAULT;
#ifdef HAVE_PROC_NET_DEV
/* If system has interface statistics via proc file system, update
statistics. */
ifstat_update_proc ();
#endif /* HAVE_PROC_NET_DEV */
#ifdef HAVE_NET_RT_IFLIST
ifstat_update_sysctl ();
#endif /* HAVE_NET_RT_IFLIST */
if (argc > 1)
VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]);
/* Specified interface print. */
ifp = if_lookup_by_name_vrf (argv[0], vrf_id);
if (ifp == NULL)
{
vty_out (vty, "%% Can't find interface %s%s", argv[0],
VTY_NEWLINE);
return CMD_WARNING;
}
if_dump_vty (vty, ifp);
return CMD_SUCCESS;
}
ALIAS (show_interface_name,
show_interface_name_vrf_cmd,
"show interface IFNAME " VRF_CMD_STR,
SHOW_STR
"Interface status and configuration\n"
"Inteface name\n"
VRF_CMD_HELP_STR)
/* Show specified interface to vty. */
DEFUN (show_interface_name_vrf_all, show_interface_name_vrf_all_cmd,
"show interface IFNAME " VRF_ALL_CMD_STR,
SHOW_STR
"Interface status and configuration\n"
"Inteface name\n"
VRF_ALL_CMD_HELP_STR)
{
struct interface *ifp;
vrf_iter_t iter;
int found = 0;
#ifdef HAVE_PROC_NET_DEV
/* If system has interface statistics via proc file system, update
statistics. */
ifstat_update_proc ();
#endif /* HAVE_PROC_NET_DEV */
#ifdef HAVE_NET_RT_IFLIST
ifstat_update_sysctl ();
#endif /* HAVE_NET_RT_IFLIST */
/* All interface print. */
for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
{
/* Specified interface print. */
ifp = if_lookup_by_name_vrf (argv[0], vrf_iter2id (iter));
if (ifp)
{
if_dump_vty (vty, ifp);
found++;
}
}
if (!found)
{
vty_out (vty, "%% Can't find interface %s%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
static void
if_show_description (struct vty *vty, vrf_id_t vrf_id)
{ {
struct listnode *node; struct listnode *node;
struct interface *ifp; struct interface *ifp;
vty_out (vty, "Interface Status Protocol Description%s", VTY_NEWLINE); vty_out (vty, "Interface Status Protocol Description%s", VTY_NEWLINE);
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
{ {
int len; int len;
@ -1118,6 +1235,52 @@ DEFUN (show_interface_desc,
vty_out (vty, "%s", ifp->desc); vty_out (vty, "%s", ifp->desc);
vty_out (vty, "%s", VTY_NEWLINE); vty_out (vty, "%s", VTY_NEWLINE);
} }
}
DEFUN (show_interface_desc,
show_interface_desc_cmd,
"show interface description",
SHOW_STR
"Interface status and configuration\n"
"Interface description\n")
{
vrf_id_t vrf_id = VRF_DEFAULT;
if (argc > 0)
VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]);
if_show_description (vty, vrf_id);
return CMD_SUCCESS;
}
ALIAS (show_interface_desc,
show_interface_desc_vrf_cmd,
"show interface description " VRF_CMD_STR,
SHOW_STR
"Interface status and configuration\n"
"Interface description\n"
VRF_CMD_HELP_STR)
DEFUN (show_interface_desc_vrf_all,
show_interface_desc_vrf_all_cmd,
"show interface description " VRF_ALL_CMD_STR,
SHOW_STR
"Interface status and configuration\n"
"Interface description\n"
VRF_ALL_CMD_HELP_STR)
{
vrf_iter_t iter;
for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
if (!list_isempty (vrf_iter2iflist (iter)))
{
vty_out (vty, "%s\tVRF %u%s%s", VTY_NEWLINE,
vrf_iter2id (iter),
VTY_NEWLINE, VTY_NEWLINE);
if_show_description (vty, vrf_iter2id (iter));
}
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -1685,10 +1848,12 @@ if_config_write (struct vty *vty)
{ {
struct listnode *node; struct listnode *node;
struct interface *ifp; struct interface *ifp;
vrf_iter_t iter;
zebra_ptm_write (vty); zebra_ptm_write (vty);
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
for (ALL_LIST_ELEMENTS_RO (vrf_iter2iflist (iter), node, ifp))
{ {
struct zebra_if *if_data; struct zebra_if *if_data;
struct listnode *addrnode; struct listnode *addrnode;
@ -1696,9 +1861,12 @@ if_config_write (struct vty *vty)
struct prefix *p; struct prefix *p;
if_data = ifp->info; if_data = ifp->info;
vty_out (vty, "interface %s%s", ifp->name, if (ifp->vrf_id == VRF_DEFAULT)
VTY_NEWLINE); vty_out (vty, "interface %s%s", ifp->name, VTY_NEWLINE);
else
vty_out (vty, "interface %s vrf %u%s", ifp->name, ifp->vrf_id,
VTY_NEWLINE);
if (if_data) if (if_data)
{ {
@ -1762,7 +1930,6 @@ void
zebra_if_init (void) zebra_if_init (void)
{ {
/* Initialize interface and new hook. */ /* Initialize interface and new hook. */
if_init ();
if_add_hook (IF_NEW_HOOK, if_zebra_new_hook); if_add_hook (IF_NEW_HOOK, if_zebra_new_hook);
if_add_hook (IF_DELETE_HOOK, if_zebra_delete_hook); if_add_hook (IF_DELETE_HOOK, if_zebra_delete_hook);
@ -1770,10 +1937,24 @@ zebra_if_init (void)
install_node (&interface_node, if_config_write); install_node (&interface_node, if_config_write);
install_element (VIEW_NODE, &show_interface_cmd); install_element (VIEW_NODE, &show_interface_cmd);
install_element (VIEW_NODE, &show_interface_vrf_cmd);
install_element (VIEW_NODE, &show_interface_vrf_all_cmd);
install_element (VIEW_NODE, &show_interface_name_cmd);
install_element (VIEW_NODE, &show_interface_name_vrf_cmd);
install_element (VIEW_NODE, &show_interface_name_vrf_all_cmd);
install_element (ENABLE_NODE, &show_interface_cmd); install_element (ENABLE_NODE, &show_interface_cmd);
install_element (ENABLE_NODE, &show_interface_vrf_cmd);
install_element (ENABLE_NODE, &show_interface_vrf_all_cmd);
install_element (ENABLE_NODE, &show_interface_name_cmd);
install_element (ENABLE_NODE, &show_interface_name_vrf_cmd);
install_element (ENABLE_NODE, &show_interface_name_vrf_all_cmd);
install_element (ENABLE_NODE, &show_interface_desc_cmd); install_element (ENABLE_NODE, &show_interface_desc_cmd);
install_element (ENABLE_NODE, &show_interface_desc_vrf_cmd);
install_element (ENABLE_NODE, &show_interface_desc_vrf_all_cmd);
install_element (CONFIG_NODE, &zebra_interface_cmd); install_element (CONFIG_NODE, &zebra_interface_cmd);
install_element (CONFIG_NODE, &zebra_interface_vrf_cmd);
install_element (CONFIG_NODE, &no_interface_cmd); install_element (CONFIG_NODE, &no_interface_cmd);
install_element (CONFIG_NODE, &no_interface_vrf_cmd);
install_default (INTERFACE_NODE); install_default (INTERFACE_NODE);
install_element (INTERFACE_NODE, &interface_desc_cmd); install_element (INTERFACE_NODE, &interface_desc_cmd);
install_element (INTERFACE_NODE, &no_interface_desc_cmd); install_element (INTERFACE_NODE, &no_interface_desc_cmd);

View File

@ -38,11 +38,13 @@
#define IF_ZEBRA_SHUTDOWN_ON 1 #define IF_ZEBRA_SHUTDOWN_ON 1
/* Router advertisement feature. */ /* Router advertisement feature. */
#ifndef RTADV
#if (defined(LINUX_IPV6) && (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1)) || defined(KAME) #if (defined(LINUX_IPV6) && (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1)) || defined(KAME)
#ifdef HAVE_RTADV #ifdef HAVE_RTADV
#define RTADV #define RTADV
#endif #endif
#endif #endif
#endif
#ifdef RTADV #ifdef RTADV
/* Router advertisement parameter. From RFC4861, RFC6275 and RFC4191. */ /* Router advertisement parameter. From RFC4861, RFC6275 and RFC4191. */

View File

@ -8,6 +8,7 @@
#include "zebra/redistribute.h" #include "zebra/redistribute.h"
#include "zebra/connected.h" #include "zebra/connected.h"
#include "zebra/rt_netlink.h" #include "zebra/rt_netlink.h"
#include "zebra/rib.h"
int kernel_add_ipv4 (struct prefix *a, struct rib *b) { return 0; } int kernel_add_ipv4 (struct prefix *a, struct rib *b) { return 0; }
int kernel_update_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; 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 #ifdef HAVE_SYS_WEAK_ALIAS_PRAGMA
#pragma weak route_read = kernel_init #pragma weak route_read = kernel_init
#else #else
void route_read (void) { return; } void route_read (struct zebra_vrf *zvrf) { return; }
#endif #endif

View File

@ -32,11 +32,13 @@
#include "table.h" #include "table.h"
#include "rib.h" #include "rib.h"
#include "privs.h" #include "privs.h"
#include "vrf.h"
#include "zebra/interface.h" #include "zebra/interface.h"
#include "zebra/zserv.h" #include "zebra/zserv.h"
#include "zebra/debug.h" #include "zebra/debug.h"
#include "zebra/kernel_socket.h" #include "zebra/kernel_socket.h"
#include "zebra/rib.h"
extern struct zebra_privs_t zserv_privs; extern struct zebra_privs_t zserv_privs;
extern struct zebra_t zebrad; extern struct zebra_t zebrad;
@ -870,8 +872,8 @@ rtm_read (struct rt_msghdr *rtm)
int ret; int ret;
if (! IS_ZEBRA_DEBUG_RIB) if (! IS_ZEBRA_DEBUG_RIB)
return; return;
ret = rib_lookup_ipv4_route (&p, &gate); ret = rib_lookup_ipv4_route (&p, &gate, VRF_DEFAULT);
inet_ntop (AF_INET, &p.prefix, buf, INET_ADDRSTRLEN); prefix2str (&p, buf, sizeof(buf));
switch (rtm->rtm_type) switch (rtm->rtm_type)
{ {
case RTM_ADD: case RTM_ADD:
@ -935,16 +937,16 @@ rtm_read (struct rt_msghdr *rtm)
*/ */
if (rtm->rtm_type == RTM_CHANGE) if (rtm->rtm_type == RTM_CHANGE)
rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, 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 if (rtm->rtm_type == RTM_GET
|| rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE) || rtm->rtm_type == RTM_CHANGE)
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, 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 else
rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0 zebra_flags, 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 #ifdef HAVE_IPV6
if (dest.sa.sa_family == AF_INET6) if (dest.sa.sa_family == AF_INET6)
@ -977,16 +979,16 @@ rtm_read (struct rt_msghdr *rtm)
*/ */
if (rtm->rtm_type == RTM_CHANGE) if (rtm->rtm_type == RTM_CHANGE)
rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, 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 if (rtm->rtm_type == RTM_GET
|| rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE) || rtm->rtm_type == RTM_CHANGE)
rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, 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 else
rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, 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 */ #endif /* HAVE_IPV6 */
} }
@ -1261,8 +1263,11 @@ kernel_read (struct thread *thread)
/* Make routing socket. */ /* Make routing socket. */
static void static void
routing_socket (void) routing_socket (struct zebra_vrf *zvrf)
{ {
if (zvrf->vrf_id != VRF_DEFAULT)
return;
if ( zserv_privs.change (ZPRIVS_RAISE) ) if ( zserv_privs.change (ZPRIVS_RAISE) )
zlog_err ("routing_socket: Can't raise privileges"); zlog_err ("routing_socket: Can't raise privileges");
@ -1293,7 +1298,13 @@ routing_socket (void)
/* Exported interface function. This function simply calls /* Exported interface function. This function simply calls
routing_socket (). */ routing_socket (). */
void void
kernel_init (void) kernel_init (struct zebra_vrf *zvrf)
{ {
routing_socket (); routing_socket (zvrf);
}
void
kernel_terminate (struct zebra_vrf *zvrf)
{
return;
} }

View File

@ -32,6 +32,7 @@
#include "plist.h" #include "plist.h"
#include "privs.h" #include "privs.h"
#include "sigevent.h" #include "sigevent.h"
#include "vrf.h"
#include "zebra/rib.h" #include "zebra/rib.h"
#include "zebra/zserv.h" #include "zebra/zserv.h"
@ -213,6 +214,82 @@ struct quagga_signal_t zebra_signals[] =
}, },
}; };
/* Callback upon creating a new VRF. */
static int
zebra_vrf_new (vrf_id_t vrf_id, void **info)
{
struct zebra_vrf *zvrf = *info;
if (! zvrf)
{
zvrf = zebra_vrf_alloc (vrf_id);
*info = (void *)zvrf;
router_id_init (zvrf);
}
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);
#ifdef RTADV
rtadv_init (zvrf);
#endif
kernel_init (zvrf);
interface_list (zvrf);
route_read (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);
}
#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);
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 ();
}
/* Main startup routine. */ /* Main startup routine. */
int int
main (int argc, char **argv) main (int argc, char **argv)
@ -336,12 +413,12 @@ main (int argc, char **argv)
rib_init (); rib_init ();
zebra_if_init (); zebra_if_init ();
zebra_debug_init (); zebra_debug_init ();
router_id_init(); router_id_cmd_init ();
zebra_vty_init (); zebra_vty_init ();
access_list_init (); access_list_init ();
prefix_list_init (); prefix_list_init ();
#ifdef RTADV #ifdef RTADV
rtadv_init (); rtadv_cmd_init ();
#endif #endif
#ifdef HAVE_IRDP #ifdef HAVE_IRDP
irdp_init(); irdp_init();
@ -354,10 +431,8 @@ main (int argc, char **argv)
/* For debug purpose. */ /* For debug purpose. */
/* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */ /* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */
/* Make kernel routing socket. */ /* Initialize VRF module, and make kernel routing socket. */
kernel_init (); zebra_vrf_init ();
interface_list ();
route_read ();
#ifdef HAVE_SNMP #ifdef HAVE_SNMP
zebra_snmp_init (); zebra_snmp_init ();

View File

@ -30,6 +30,7 @@
#include "zclient.h" #include "zclient.h"
#include "linklist.h" #include "linklist.h"
#include "log.h" #include "log.h"
#include "vrf.h"
#include "zebra/rib.h" #include "zebra/rib.h"
#include "zebra/zserv.h" #include "zebra/zserv.h"
@ -96,7 +97,7 @@ zebra_redistribute_default (struct zserv *client)
p.family = AF_INET; p.family = AF_INET;
/* Lookup table. */ /* Lookup table. */
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
if (table) if (table)
{ {
rn = route_node_lookup (table, (struct prefix *)&p); rn = route_node_lookup (table, (struct prefix *)&p);
@ -116,7 +117,7 @@ zebra_redistribute_default (struct zserv *client)
p6.family = AF_INET6; p6.family = AF_INET6;
/* Lookup table. */ /* Lookup table. */
table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT);
if (table) if (table)
{ {
rn = route_node_lookup (table, (struct prefix *)&p6); rn = route_node_lookup (table, (struct prefix *)&p6);
@ -140,7 +141,7 @@ zebra_redistribute (struct zserv *client, int type, u_short instance)
struct route_table *table; struct route_table *table;
struct route_node *rn; struct route_node *rn;
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
if (table) if (table)
for (rn = route_top (table); rn; rn = route_next (rn)) for (rn = route_top (table); rn; rn = route_next (rn))
RNODE_FOREACH_RIB (rn, newrib) RNODE_FOREACH_RIB (rn, newrib)
@ -155,7 +156,7 @@ zebra_redistribute (struct zserv *client, int type, u_short instance)
} }
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT);
if (table) if (table)
for (rn = route_top (table); rn; rn = route_next (rn)) for (rn = route_top (table); rn; rn = route_next (rn))
RNODE_FOREACH_RIB (rn, newrib) RNODE_FOREACH_RIB (rn, newrib)
@ -499,7 +500,7 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib)
rib_add_ipv4(ZEBRA_ROUTE_TABLE, rib->table, 0, &p4, rib_add_ipv4(ZEBRA_ROUTE_TABLE, rib->table, 0, &p4,
gate, &nhop->src.ipv4, gate, &nhop->src.ipv4,
nhop->ifindex, zebrad.rtm_table_default, nhop->ifindex, rib->vrf_id, zebrad.rtm_table_default,
rib->metric, rib->metric,
zebra_import_table_distance[AFI_IP][rib->table], zebra_import_table_distance[AFI_IP][rib->table],
SAFI_UNICAST); SAFI_UNICAST);
@ -539,7 +540,7 @@ zebra_del_import_table_entry (struct route_node *rn, struct rib *rib)
p4.prefix = rn->p.u.prefix4; p4.prefix = rn->p.u.prefix4;
rib_delete_ipv4(ZEBRA_ROUTE_TABLE, rib->table, rib->flags, &p4, NULL, rib_delete_ipv4(ZEBRA_ROUTE_TABLE, rib->table, rib->flags, &p4, NULL,
0, zebrad.rtm_table_default, SAFI_UNICAST); 0, rib->vrf_id, zebrad.rtm_table_default, SAFI_UNICAST);
} }
/* DD: Add IPv6 code */ /* DD: Add IPv6 code */
@ -561,7 +562,7 @@ zebra_import_table (afi_t afi, u_int32_t table_id, u_int32_t distance, int add)
if (afi >= AFI_MAX) if (afi >= AFI_MAX)
return (-1); return (-1);
table = vrf_other_route_table(afi, table_id, 0); table = zebra_vrf_other_route_table(afi, table_id, VRF_DEFAULT);
if (table == NULL) if (table == NULL)
{ {
return 0; return 0;

View File

@ -23,6 +23,7 @@
#ifndef _ZEBRA_RIB_H #ifndef _ZEBRA_RIB_H
#define _ZEBRA_RIB_H #define _ZEBRA_RIB_H
#include "linklist.h"
#include "prefix.h" #include "prefix.h"
#include "table.h" #include "table.h"
#include "queue.h" #include "queue.h"
@ -52,6 +53,9 @@ struct rib
/* Source protocol instance */ /* Source protocol instance */
u_short instance; u_short instance;
/* VRF identifier. */
vrf_id_t vrf_id;
/* Which routing table */ /* Which routing table */
uint32_t table; uint32_t table;
@ -171,6 +175,9 @@ struct static_route
struct static_route *prev; struct static_route *prev;
struct static_route *next; struct static_route *next;
/* VRF identifier. */
vrf_id_t vrf_id;
/* Administrative distance. */ /* Administrative distance. */
u_char distance; u_char distance;
@ -187,7 +194,7 @@ struct static_route
#define STATIC_IPV6_IFNAME 6 #define STATIC_IPV6_IFNAME 6
/* /*
* Nexthop value. * Nexthop value.
* *
* Under IPv4 addr and ifname are * Under IPv4 addr and ifname are
* used independentyly. * used independentyly.
@ -205,6 +212,7 @@ struct static_route
*/ */
}; };
/* The following for loop allows to iterate over the nexthop /* The following for loop allows to iterate over the nexthop
* structure of routes. * structure of routes.
* *
@ -251,11 +259,45 @@ struct static_route
: ((tnexthop) = (nexthop)->next)) \ : ((tnexthop) = (nexthop)->next)) \
: (((recursing) = 0),((tnexthop) = (tnexthop)->next))) : (((recursing) = 0),((tnexthop) = (tnexthop)->next)))
/* Routing table instance. */ /* Router advertisement feature. */
struct vrf #ifndef RTADV
#if (defined(LINUX_IPV6) && (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1)) || defined(KAME)
#ifdef HAVE_RTADV
#define RTADV
#endif
#endif
#endif
#if defined (RTADV)
/* Structure which hold status of router advertisement. */
struct rtadv
{ {
/* Identifier. This is same as routing table vector index. */ int sock;
u_int32_t id;
int adv_if_count;
int adv_msec_if_count;
struct thread *ra_read;
struct thread *ra_timer;
};
#endif /* RTADV */
#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
{
/* Identifier. */
vrf_id_t vrf_id;
/* Routing table name. */ /* Routing table name. */
char *name; char *name;
@ -280,6 +322,25 @@ struct vrf
/* Routing tables off of main table for redistribute table */ /* Routing tables off of main table for redistribute table */
struct route_table *other_table[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; 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
*/
struct list _rid_all_sorted_list;
struct list _rid_lo_sorted_list;
struct list *rid_all_sorted_list;
struct list *rid_lo_sorted_list;
struct prefix rid_user_assigned;
#if defined (RTADV)
struct rtadv rtadv;
#endif /* RTADV */
}; };
/* /*
@ -292,9 +353,9 @@ typedef struct rib_table_info_t_
{ {
/* /*
* Back pointer to vrf. * Back pointer to zebra_vrf.
*/ */
struct vrf *vrf; struct zebra_vrf *zvrf;
afi_t afi; afi_t afi;
safi_t safi; safi_t safi;
@ -313,7 +374,7 @@ typedef enum
*/ */
typedef struct rib_tables_iter_t_ typedef struct rib_tables_iter_t_
{ {
uint32_t vrf_id; vrf_id_t vrf_id;
int afi_safi_ix; int afi_safi_ix;
rib_tables_iter_state_t state; rib_tables_iter_state_t state;
@ -341,7 +402,8 @@ extern void rib_lookup_and_pushup (struct prefix_ipv4 *);
#define rib_dump(prefix ,rib) _rib_dump(__func__, prefix, rib) #define rib_dump(prefix ,rib) _rib_dump(__func__, prefix, rib)
extern void _rib_dump (const char *, extern void _rib_dump (const char *,
union prefix46constptr, const struct rib *); 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_LOOKUP_ERROR -1
#define ZEBRA_RIB_FOUND_EXACT 0 #define ZEBRA_RIB_FOUND_EXACT 0
#define ZEBRA_RIB_FOUND_NOGATE 1 #define ZEBRA_RIB_FOUND_NOGATE 1
@ -358,11 +420,12 @@ extern int
rib_bogus_ipv6 (int type, struct prefix_ipv6 *p, rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
struct in6_addr *gate, unsigned int ifindex, int table); struct in6_addr *gate, unsigned int ifindex, int table);
extern struct vrf *vrf_lookup (u_int32_t); extern struct zebra_vrf *zebra_vrf_lookup (vrf_id_t vrf_id);
extern struct route_table *vrf_table (afi_t afi, safi_t safi, u_int32_t id); extern struct zebra_vrf *zebra_vrf_alloc (vrf_id_t);
extern struct route_table *vrf_static_table (afi_t afi, safi_t safi, u_int32_t id); extern struct route_table *zebra_vrf_table (afi_t, safi_t, vrf_id_t);
extern struct route_table *vrf_other_route_table (afi_t afi, u_int32_t table_id, extern struct route_table *zebra_vrf_static_table (afi_t, safi_t, vrf_id_t);
u_int32_t vrf_id); extern struct route_table *zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id,
vrf_id_t vrf_id);
extern int is_zebra_valid_kernel_table(u_int32_t table_id); extern int is_zebra_valid_kernel_table(u_int32_t table_id);
extern int is_zebra_main_routing_table(u_int32_t table_id); extern int is_zebra_main_routing_table(u_int32_t table_id);
extern int zebra_check_addr (struct prefix *p); extern int zebra_check_addr (struct prefix *p);
@ -372,23 +435,24 @@ extern int zebra_check_addr (struct prefix *p);
* also implicitly withdraw equal prefix of same type. */ * also implicitly withdraw equal prefix of same type. */
extern int rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, extern int rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
struct in_addr *gate, struct in_addr *src, 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); u_int32_t, u_char, safi_t);
extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *, 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, extern 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,
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 (vrf_id_t);
extern void rib_update_static (void); extern void rib_update_static (vrf_id_t);
extern void rib_weed_tables (void); extern void rib_weed_tables (void);
extern void rib_sweep_route (void); extern void rib_sweep_route (void);
extern void rib_close_table (struct route_table *);
extern void rib_close (void); extern void rib_close (void);
extern void rib_init (void); extern void rib_init (void);
extern unsigned long rib_score_proto (u_char proto, u_short instance); extern unsigned long rib_score_proto (u_char proto, u_short instance);
@ -398,31 +462,32 @@ extern void rib_queue_add (struct zebra_t *zebra, struct route_node *rn);
extern int extern int
static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, 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 extern int
static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, 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);
extern int extern int
rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, 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, struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id,
u_int32_t metric, u_char distance, safi_t safi); u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi);
extern int extern int
rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, 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 struct route_table *rib_table_ipv6;
extern int extern int
static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
const char *ifname, u_char flags, u_short tag, 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 extern int
rib_add_ipv6_multipath (struct prefix *, struct rib *, safi_t, rib_add_ipv6_multipath (struct prefix *, struct rib *, safi_t,
@ -431,7 +496,7 @@ rib_add_ipv6_multipath (struct prefix *, struct rib *, safi_t,
extern int extern int
static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
const char *ifname, u_short tag, u_char distance, const char *ifname, u_short tag, u_char distance,
u_int32_t vrf_id); vrf_id_t vrf_id);
extern int rib_gc_dest (struct route_node *rn); extern int rib_gc_dest (struct route_node *rn);
extern struct route_table *rib_tables_iter_next (rib_tables_iter_t *iter); extern struct route_table *rib_tables_iter_next (rib_tables_iter_t *iter);
@ -508,10 +573,10 @@ rib_dest_table (rib_dest_t *dest)
/* /*
* rib_dest_vrf * rib_dest_vrf
*/ */
static inline struct vrf * static inline struct zebra_vrf *
rib_dest_vrf (rib_dest_t *dest) rib_dest_vrf (rib_dest_t *dest)
{ {
return rib_table_info (rib_dest_table (dest))->vrf; return rib_table_info (rib_dest_table (dest))->zvrf;
} }
/* /*

View File

@ -36,16 +36,12 @@
#include "log.h" #include "log.h"
#include "table.h" #include "table.h"
#include "rib.h" #include "rib.h"
#include "vrf.h"
#include "zebra/zserv.h" #include "zebra/zserv.h"
#include "zebra/router-id.h" #include "zebra/router-id.h"
#include "zebra/redistribute.h" #include "zebra/redistribute.h"
static struct list _rid_all_sorted_list;
static struct list _rid_lo_sorted_list;
static struct list *rid_all_sorted_list = &_rid_all_sorted_list;
static struct list *rid_lo_sorted_list = &_rid_lo_sorted_list;
static struct prefix rid_user_assigned;
/* master zebra server structure */ /* master zebra server structure */
extern struct zebra_t zebrad; extern struct zebra_t zebrad;
@ -77,44 +73,55 @@ router_id_bad_address (struct connected *ifc)
} }
void void
router_id_get (struct prefix *p) router_id_get (struct prefix *p, vrf_id_t vrf_id)
{ {
struct listnode *node; struct listnode *node;
struct connected *c; struct connected *c;
struct zebra_vrf *zvrf = vrf_info_get (vrf_id);
p->u.prefix4.s_addr = 0; p->u.prefix4.s_addr = 0;
p->family = AF_INET; p->family = AF_INET;
p->prefixlen = 32; p->prefixlen = 32;
if (rid_user_assigned.u.prefix4.s_addr) if (zvrf->rid_user_assigned.u.prefix4.s_addr)
p->u.prefix4.s_addr = rid_user_assigned.u.prefix4.s_addr; p->u.prefix4.s_addr = zvrf->rid_user_assigned.u.prefix4.s_addr;
else if (!list_isempty (rid_lo_sorted_list)) else if (!list_isempty (zvrf->rid_lo_sorted_list))
{ {
node = listtail (rid_lo_sorted_list); node = listtail (zvrf->rid_lo_sorted_list);
c = listgetdata (node); c = listgetdata (node);
p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; p->u.prefix4.s_addr = c->address->u.prefix4.s_addr;
} }
else if (!list_isempty (rid_all_sorted_list)) else if (!list_isempty (zvrf->rid_all_sorted_list))
{ {
node = listtail (rid_all_sorted_list); node = listtail (zvrf->rid_all_sorted_list);
c = listgetdata (node); c = listgetdata (node);
p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; p->u.prefix4.s_addr = c->address->u.prefix4.s_addr;
} }
} }
static void static void
router_id_set (struct prefix *p) router_id_set (struct prefix *p, vrf_id_t vrf_id)
{ {
struct prefix p2; struct prefix p2;
struct listnode *node; struct listnode *node;
struct zserv *client; struct zserv *client;
struct zebra_vrf *zvrf;
rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr; if (p->u.prefix4.s_addr == 0) /* unset */
{
zvrf = vrf_info_lookup (vrf_id);
if (! zvrf)
return;
}
else /* set */
zvrf = vrf_info_get (vrf_id);
router_id_get (&p2); zvrf->rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr;
router_id_get (&p2, vrf_id);
for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client)) for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
zsend_router_id_update (client, &p2); zsend_router_id_update (client, &p2, vrf_id);
} }
void void
@ -125,28 +132,29 @@ router_id_add_address (struct connected *ifc)
struct prefix before; struct prefix before;
struct prefix after; struct prefix after;
struct zserv *client; struct zserv *client;
struct zebra_vrf *zvrf = vrf_info_get (ifc->ifp->vrf_id);
if (router_id_bad_address (ifc)) if (router_id_bad_address (ifc))
return; return;
router_id_get (&before); router_id_get (&before, zvrf->vrf_id);
if (!strncmp (ifc->ifp->name, "lo", 2) if (!strncmp (ifc->ifp->name, "lo", 2)
|| !strncmp (ifc->ifp->name, "dummy", 5)) || !strncmp (ifc->ifp->name, "dummy", 5))
l = rid_lo_sorted_list; l = zvrf->rid_lo_sorted_list;
else else
l = rid_all_sorted_list; l = zvrf->rid_all_sorted_list;
if (!router_id_find_node (l, ifc)) if (!router_id_find_node (l, ifc))
listnode_add_sort (l, ifc); listnode_add_sort (l, ifc);
router_id_get (&after); router_id_get (&after, zvrf->vrf_id);
if (prefix_same (&before, &after)) if (prefix_same (&before, &after))
return; return;
for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client)) for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
zsend_router_id_update (client, &after); zsend_router_id_update (client, &after, zvrf->vrf_id);
} }
void void
@ -158,36 +166,51 @@ router_id_del_address (struct connected *ifc)
struct prefix before; struct prefix before;
struct listnode *node; struct listnode *node;
struct zserv *client; struct zserv *client;
struct zebra_vrf *zvrf = vrf_info_get (ifc->ifp->vrf_id);
if (router_id_bad_address (ifc)) if (router_id_bad_address (ifc))
return; return;
router_id_get (&before); router_id_get (&before, zvrf->vrf_id);
if (!strncmp (ifc->ifp->name, "lo", 2) if (!strncmp (ifc->ifp->name, "lo", 2)
|| !strncmp (ifc->ifp->name, "dummy", 5)) || !strncmp (ifc->ifp->name, "dummy", 5))
l = rid_lo_sorted_list; l = zvrf->rid_lo_sorted_list;
else else
l = rid_all_sorted_list; l = zvrf->rid_all_sorted_list;
if ((c = router_id_find_node (l, ifc))) if ((c = router_id_find_node (l, ifc)))
listnode_delete (l, c); listnode_delete (l, c);
router_id_get (&after); router_id_get (&after, zvrf->vrf_id);
if (prefix_same (&before, &after)) if (prefix_same (&before, &after))
return; return;
for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client)) for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client))
zsend_router_id_update (client, &after); zsend_router_id_update (client, &after, zvrf->vrf_id);
} }
void void
router_id_write (struct vty *vty) router_id_write (struct vty *vty)
{ {
if (rid_user_assigned.u.prefix4.s_addr) struct zebra_vrf *zvrf;
vty_out (vty, "router-id %s%s", inet_ntoa (rid_user_assigned.u.prefix4), vrf_iter_t iter;
VTY_NEWLINE);
for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
if ((zvrf = vrf_iter2info (iter)) != NULL)
if (zvrf->rid_user_assigned.u.prefix4.s_addr)
{
if (zvrf->vrf_id == VRF_DEFAULT)
vty_out (vty, "router-id %s%s",
inet_ntoa (zvrf->rid_user_assigned.u.prefix4),
VTY_NEWLINE);
else
vty_out (vty, "router-id %s vrf %u%s",
inet_ntoa (zvrf->rid_user_assigned.u.prefix4),
zvrf->vrf_id,
VTY_NEWLINE);
}
} }
DEFUN (router_id, DEFUN (router_id,
@ -197,6 +220,7 @@ DEFUN (router_id,
"IP address to use for router-id\n") "IP address to use for router-id\n")
{ {
struct prefix rid; struct prefix rid;
vrf_id_t vrf_id = VRF_DEFAULT;
rid.u.prefix4.s_addr = inet_addr (argv[0]); rid.u.prefix4.s_addr = inet_addr (argv[0]);
if (!rid.u.prefix4.s_addr) if (!rid.u.prefix4.s_addr)
@ -205,11 +229,21 @@ DEFUN (router_id,
rid.prefixlen = 32; rid.prefixlen = 32;
rid.family = AF_INET; rid.family = AF_INET;
router_id_set (&rid); if (argc > 1)
VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]);
router_id_set (&rid, vrf_id);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
ALIAS (router_id,
router_id_vrf_cmd,
"router-id A.B.C.D " VRF_CMD_STR,
"Manually set the router-id\n"
"IP address to use for router-id\n"
VRF_CMD_HELP_STR)
DEFUN (no_router_id, DEFUN (no_router_id,
no_router_id_cmd, no_router_id_cmd,
"no router-id", "no router-id",
@ -217,16 +251,27 @@ DEFUN (no_router_id,
"Remove the manually configured router-id\n") "Remove the manually configured router-id\n")
{ {
struct prefix rid; struct prefix rid;
vrf_id_t vrf_id = VRF_DEFAULT;
rid.u.prefix4.s_addr = 0; rid.u.prefix4.s_addr = 0;
rid.prefixlen = 0; rid.prefixlen = 0;
rid.family = AF_INET; rid.family = AF_INET;
router_id_set (&rid); if (argc > 0)
VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]);
router_id_set (&rid, vrf_id);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
ALIAS (no_router_id,
no_router_id_vrf_cmd,
"no router-id " VRF_CMD_STR,
NO_STR
"Remove the manually configured router-id\n"
VRF_CMD_HELP_STR)
static int static int
router_id_cmp (void *a, void *b) router_id_cmp (void *a, void *b)
{ {
@ -237,18 +282,27 @@ router_id_cmp (void *a, void *b)
} }
void void
router_id_init (void) router_id_cmd_init (void)
{ {
install_element (CONFIG_NODE, &router_id_cmd); install_element (CONFIG_NODE, &router_id_cmd);
install_element (CONFIG_NODE, &no_router_id_cmd); install_element (CONFIG_NODE, &no_router_id_cmd);
install_element (CONFIG_NODE, &router_id_vrf_cmd);
memset (rid_all_sorted_list, 0, sizeof (_rid_all_sorted_list)); install_element (CONFIG_NODE, &no_router_id_vrf_cmd);
memset (rid_lo_sorted_list, 0, sizeof (_rid_lo_sorted_list)); }
memset (&rid_user_assigned, 0, sizeof (rid_user_assigned));
void
rid_all_sorted_list->cmp = router_id_cmp; router_id_init (struct zebra_vrf *zvrf)
rid_lo_sorted_list->cmp = router_id_cmp; {
zvrf->rid_all_sorted_list = &zvrf->_rid_all_sorted_list;
rid_user_assigned.family = AF_INET; zvrf->rid_lo_sorted_list = &zvrf->_rid_lo_sorted_list;
rid_user_assigned.prefixlen = 32;
memset (zvrf->rid_all_sorted_list, 0, sizeof (zvrf->_rid_all_sorted_list));
memset (zvrf->rid_lo_sorted_list, 0, sizeof (zvrf->_rid_lo_sorted_list));
memset (&zvrf->rid_user_assigned, 0, sizeof (zvrf->rid_user_assigned));
zvrf->rid_all_sorted_list->cmp = router_id_cmp;
zvrf->rid_lo_sorted_list->cmp = router_id_cmp;
zvrf->rid_user_assigned.family = AF_INET;
zvrf->rid_user_assigned.prefixlen = 32;
} }

View File

@ -33,8 +33,9 @@
extern void router_id_add_address(struct connected *); extern void router_id_add_address(struct connected *);
extern void router_id_del_address(struct connected *); extern void router_id_del_address(struct connected *);
extern void router_id_init(void); extern void router_id_init(struct zebra_vrf *);
extern void router_id_cmd_init(void);
extern void router_id_write(struct vty *); extern void router_id_write(struct vty *);
extern void router_id_get(struct prefix *); extern void router_id_get(struct prefix *, vrf_id_t);
#endif #endif

View File

@ -37,6 +37,7 @@
#include "thread.h" #include "thread.h"
#include "privs.h" #include "privs.h"
#include "nexthop.h" #include "nexthop.h"
#include "vrf.h"
#include "zebra/zserv.h" #include "zebra/zserv.h"
#include "zebra/rt.h" #include "zebra/rt.h"
@ -46,16 +47,6 @@
#include "rt_netlink.h" #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[] = { static const struct message nlmsg_str[] = {
{RTM_NEWROUTE, "RTM_NEWROUTE"}, {RTM_NEWROUTE, "RTM_NEWROUTE"},
{RTM_DELROUTE, "RTM_DELROUTE"}, {RTM_DELROUTE, "RTM_DELROUTE"},
@ -155,7 +146,7 @@ netlink_recvbuf (struct nlsock *nl, uint32_t newsize)
/* Make socket for Linux netlink interface. */ /* Make socket for Linux netlink interface. */
static int 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; int ret;
struct sockaddr_nl snl; struct sockaddr_nl snl;
@ -169,7 +160,7 @@ netlink_socket (struct nlsock *nl, unsigned long groups)
return -1; return -1;
} }
sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); sock = vrf_socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, vrf_id);
if (sock < 0) if (sock < 0)
{ {
zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name, zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name,
@ -272,8 +263,9 @@ netlink_request (int family, int type, struct nlsock *nl)
/* Receive message from netlink interface and pass those information /* Receive message from netlink interface and pass those information
to the given function. */ to the given function. */
static int static int
netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *,
struct nlsock *nl) vrf_id_t),
struct nlsock *nl, struct zebra_vrf *zvrf)
{ {
int status; int status;
int ret = 0; int ret = 0;
@ -362,7 +354,7 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
} }
/* Deal with errors that occur because of races in link handling */ /* Deal with errors that occur because of races in link handling */
if (nl == &netlink_cmd if (nl == &zvrf->netlink_cmd
&& ((msg_type == RTM_DELROUTE && && ((msg_type == RTM_DELROUTE &&
(-errnum == ENODEV || -errnum == ESRCH)) (-errnum == ENODEV || -errnum == ESRCH))
|| (msg_type == RTM_NEWROUTE && -errnum == EEXIST))) || (msg_type == RTM_NEWROUTE && -errnum == EEXIST)))
@ -375,7 +367,7 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
return 0; return 0;
} }
if (nl == &netlink_cmd if (nl == &zvrf->netlink_cmd
&& msg_type == RTM_NEWROUTE && -errnum == ESRCH) && msg_type == RTM_NEWROUTE && -errnum == ESRCH)
{ {
/* This is known to happen in some situations, don't log /* This is known to happen in some situations, don't log
@ -406,16 +398,17 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
/* skip unsolicited messages originating from command socket /* skip unsolicited messages originating from command socket
* linux sets the originators port-id for {NEW|DEL}ADDR messages, * linux sets the originators port-id for {NEW|DEL}ADDR messages,
* so this has to be checked here. */ * 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)) && (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR))
{ {
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("netlink_parse_info: %s packet comes from %s", zlog_debug ("netlink_parse_info: %s packet comes from %s",
netlink_cmd.name, nl->name); zvrf->netlink_cmd.name, nl->name);
continue; continue;
} }
error = (*filter) (&snl, h); error = (*filter) (&snl, h, zvrf->vrf_id);
if (error < 0) if (error < 0)
{ {
zlog (NULL, LOG_ERR, "%s filter function error", nl->name); zlog (NULL, LOG_ERR, "%s filter function error", nl->name);
@ -486,7 +479,8 @@ netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp)
/* Called from interface_lookup_netlink(). This function is only used /* Called from interface_lookup_netlink(). This function is only used
during bootstrap. */ during bootstrap. */
static int 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; int len;
struct ifinfomsg *ifi; struct ifinfomsg *ifi;
@ -522,7 +516,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
name = (char *) RTA_DATA (tb[IFLA_IFNAME]); name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
/* Add interface. */ /* Add interface. */
ifp = if_get_by_name (name); ifp = if_get_by_name_vrf (name, vrf_id);
set_ifindex(ifp, ifi->ifi_index); set_ifindex(ifp, ifi->ifi_index);
ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->flags = ifi->ifi_flags & 0x0000fffff;
ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]);
@ -539,7 +533,8 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
/* Lookup interface IPv4/IPv6 address. */ /* Lookup interface IPv4/IPv6 address. */
static int 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; int len;
struct ifaddrmsg *ifa; struct ifaddrmsg *ifa;
@ -569,19 +564,19 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
memset (tb, 0, sizeof tb); memset (tb, 0, sizeof tb);
netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len); 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) if (ifp == NULL)
{ {
zlog_err ("netlink_interface_addr can't find interface by index %d", zlog_err ("netlink_interface_addr can't find interface by index %d vrf %u",
ifa->ifa_index); ifa->ifa_index, vrf_id);
return -1; return -1;
} }
if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */ if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
{ {
char buf[BUFSIZ]; char buf[BUFSIZ];
zlog_debug ("netlink_interface_addr %s %s:", zlog_debug ("netlink_interface_addr %s %s vrf %u:",
lookup (nlmsg_str, h->nlmsg_type), ifp->name); lookup (nlmsg_str, h->nlmsg_type), ifp->name, vrf_id);
if (tb[IFA_LOCAL]) if (tb[IFA_LOCAL])
zlog_debug (" IFA_LOCAL %s/%d", zlog_debug (" IFA_LOCAL %s/%d",
inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]), inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]),
@ -674,7 +669,8 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
/* Looking up routing table by netlink interface. */ /* Looking up routing table by netlink interface. */
static int 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; int len;
struct rtmsg *rtm; struct rtmsg *rtm;
@ -755,7 +751,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
if (!tb[RTA_MULTIPATH]) if (!tb[RTA_MULTIPATH])
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, src, index, rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, src, index,
table, metric, 0, SAFI_UNICAST); vrf_id, table, metric, 0, SAFI_UNICAST);
else else
{ {
/* This is a multipath route */ /* This is a multipath route */
@ -771,6 +767,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
rib->distance = 0; rib->distance = 0;
rib->flags = flags; rib->flags = flags;
rib->metric = metric; rib->metric = metric;
rib->vrf_id = vrf_id;
rib->table = table; rib->table = table;
rib->nexthop_num = 0; rib->nexthop_num = 0;
rib->uptime = time (NULL); rib->uptime = time (NULL);
@ -821,8 +818,8 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
memcpy (&p.prefix, dest, 16); memcpy (&p.prefix, dest, 16);
p.prefixlen = rtm->rtm_dst_len; p.prefixlen = rtm->rtm_dst_len;
rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, index, table, rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, index, vrf_id,
metric, 0, SAFI_UNICAST); table, metric, 0, SAFI_UNICAST);
} }
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
@ -846,7 +843,8 @@ static const struct message rtproto_str[] = {
/* Routing information change from the kernel. */ /* Routing information change from the kernel. */
static int 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; int len;
struct rtmsg *rtm; struct rtmsg *rtm;
@ -868,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 (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
{ {
/* If this is not route add/delete message print warning. */ /* 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; return 0;
} }
/* Connected route. */ /* Connected route. */
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("%s %s %s proto %s", zlog_debug ("%s %s %s proto %s vrf %u",
h->nlmsg_type == h->nlmsg_type ==
RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
rtm->rtm_family == AF_INET ? "ipv4" : "ipv6", rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast", 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) if (rtm->rtm_type != RTN_UNICAST)
{ {
@ -911,7 +910,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
if (rtm->rtm_src_len != 0) 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; return 0;
} }
@ -947,19 +946,17 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
{ {
if (h->nlmsg_type == RTM_NEWROUTE) char buf[BUFSIZ];
zlog_debug ("RTM_NEWROUTE %s/%d", zlog_debug ("%s %s vrf %u",
inet_ntoa (p.prefix), p.prefixlen); h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
else prefix2str (&p, buf, sizeof(buf)), vrf_id);
zlog_debug ("RTM_DELROUTE %s/%d",
inet_ntoa (p.prefix), p.prefixlen);
} }
if (h->nlmsg_type == RTM_NEWROUTE) if (h->nlmsg_type == RTM_NEWROUTE)
{ {
if (!tb[RTA_MULTIPATH]) if (!tb[RTA_MULTIPATH])
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, src, index, table, rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, src, index, vrf_id,
metric, 0, SAFI_UNICAST); table, metric, 0, SAFI_UNICAST);
else else
{ {
/* This is a multipath route */ /* This is a multipath route */
@ -975,6 +972,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
rib->distance = 0; rib->distance = 0;
rib->flags = 0; rib->flags = 0;
rib->metric = metric; rib->metric = metric;
rib->vrf_id = vrf_id;
rib->table = table; rib->table = table;
rib->nexthop_num = 0; rib->nexthop_num = 0;
rib->uptime = time (NULL); rib->uptime = time (NULL);
@ -1020,7 +1018,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
} }
else else
rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index,
table, SAFI_UNICAST); vrf_id, table, SAFI_UNICAST);
} }
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
@ -1035,21 +1033,17 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
{ {
if (h->nlmsg_type == RTM_NEWROUTE) zlog_debug ("%s %s vrf %u",
zlog_debug ("RTM_NEWROUTE %s/%d", h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ), prefix2str (&p, buf, sizeof(buf)), vrf_id);
p.prefixlen);
else
zlog_debug ("RTM_DELROUTE %s/%d",
inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
p.prefixlen);
} }
if (h->nlmsg_type == RTM_NEWROUTE) 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_id,
table, metric, 0, SAFI_UNICAST);
else else
rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index,
table, SAFI_UNICAST); vrf_id, table, SAFI_UNICAST);
} }
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
@ -1057,7 +1051,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
} }
static int 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; int len;
struct ifinfomsg *ifi; struct ifinfomsg *ifi;
@ -1070,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 (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
{ {
/* If this is not link add/delete message so print warning. */ /* If this is not link add/delete message so print warning. */
zlog_warn ("netlink_link_change: wrong kernel message %d\n", zlog_warn ("netlink_link_change: wrong kernel message %d vrf %u\n",
h->nlmsg_type); h->nlmsg_type, vrf_id);
return 0; return 0;
} }
@ -1088,7 +1083,8 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
{ {
if (IS_ZEBRA_DEBUG_KERNEL) 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; return 0;
} }
#endif /* IFLA_WIRELESS */ #endif /* IFLA_WIRELESS */
@ -1100,12 +1096,12 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
/* Add interface. */ /* Add interface. */
if (h->nlmsg_type == RTM_NEWLINK) 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 || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
{ {
if (ifp == NULL) if (ifp == NULL)
ifp = if_get_by_name (name); ifp = if_get_by_name_vrf (name, vrf_id);
set_ifindex(ifp, ifi->ifi_index); set_ifindex(ifp, ifi->ifi_index);
ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->flags = ifi->ifi_flags & 0x0000fffff;
@ -1146,12 +1142,12 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
else else
{ {
/* RTM_DELLINK. */ /* RTM_DELLINK. */
ifp = if_lookup_by_name (name); ifp = if_lookup_by_name_vrf (name, vrf_id);
if (ifp == NULL) if (ifp == NULL)
{ {
zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find", zlog_warn ("interface %s vrf %u is deleted but can't find",
name); name, vrf_id);
return 0; return 0;
} }
@ -1162,7 +1158,8 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
} }
static int 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 */ /* JF: Ignore messages that aren't from the kernel */
if ( snl->nl_pid != 0 ) if ( snl->nl_pid != 0 )
@ -1174,25 +1171,26 @@ netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h)
switch (h->nlmsg_type) switch (h->nlmsg_type)
{ {
case RTM_NEWROUTE: case RTM_NEWROUTE:
return netlink_route_change (snl, h); return netlink_route_change (snl, h, vrf_id);
break; break;
case RTM_DELROUTE: case RTM_DELROUTE:
return netlink_route_change (snl, h); return netlink_route_change (snl, h, vrf_id);
break; break;
case RTM_NEWLINK: case RTM_NEWLINK:
return netlink_link_change (snl, h); return netlink_link_change (snl, h, vrf_id);
break; break;
case RTM_DELLINK: case RTM_DELLINK:
return netlink_link_change (snl, h); return netlink_link_change (snl, h, vrf_id);
break; break;
case RTM_NEWADDR: case RTM_NEWADDR:
return netlink_interface_addr (snl, h); return netlink_interface_addr (snl, h, vrf_id);
break; break;
case RTM_DELADDR: case RTM_DELADDR:
return netlink_interface_addr (snl, h); return netlink_interface_addr (snl, h, vrf_id);
break; break;
default: 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; break;
} }
return 0; return 0;
@ -1200,32 +1198,32 @@ netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h)
/* Interface lookup by netlink socket. */ /* Interface lookup by netlink socket. */
int int
interface_lookup_netlink (void) interface_lookup_netlink (struct zebra_vrf *zvrf)
{ {
int ret; int ret;
/* Get interface information. */ /* 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) if (ret < 0)
return ret; return ret;
ret = netlink_parse_info (netlink_interface, &netlink_cmd); ret = netlink_parse_info (netlink_interface, &zvrf->netlink_cmd, zvrf);
if (ret < 0) if (ret < 0)
return ret; return ret;
/* Get IPv4 address of the interfaces. */ /* 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) if (ret < 0)
return ret; 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) if (ret < 0)
return ret; return ret;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
/* Get IPv6 address of the interfaces. */ /* 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) if (ret < 0)
return ret; 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) if (ret < 0)
return ret; return ret;
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
@ -1236,24 +1234,24 @@ interface_lookup_netlink (void)
/* Routing table read function using netlink interface. Only called /* Routing table read function using netlink interface. Only called
bootstrap time. */ bootstrap time. */
int int
netlink_route_read (void) netlink_route_read (struct zebra_vrf *zvrf)
{ {
int ret; int ret;
/* Get IPv4 routing table. */ /* 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) if (ret < 0)
return ret; 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) if (ret < 0)
return ret; return ret;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
/* Get IPv6 routing table. */ /* 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) if (ret < 0)
return ret; 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) if (ret < 0)
return ret; return ret;
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
@ -1326,15 +1324,17 @@ addattr32 (struct nlmsghdr *n, unsigned int maxlen, int type, int data)
} }
static int 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; return 0;
} }
/* sendmsg() to netlink socket then recvmsg(). */ /* sendmsg() to netlink socket then recvmsg(). */
static int static int
netlink_talk (struct nlmsghdr *n, struct nlsock *nl) netlink_talk (struct nlmsghdr *n, struct nlsock *nl, struct zebra_vrf *zvrf)
{ {
int status; int status;
struct sockaddr_nl snl; struct sockaddr_nl snl;
@ -1384,7 +1384,7 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl)
* Get reply from netlink socket. * Get reply from netlink socket.
* The reply should either be an acknowlegement or an error. * 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. */ /* Routing table change via netlink interface. */
@ -1397,6 +1397,8 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate,
struct sockaddr_nl snl; struct sockaddr_nl snl;
int discard; int discard;
struct zebra_vrf *zvrf = vrf_info_lookup (VRF_DEFAULT); //Pending
struct struct
{ {
struct nlmsghdr n; struct nlmsghdr n;
@ -1458,7 +1460,7 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate,
snl.nl_family = AF_NETLINK; snl.nl_family = AF_NETLINK;
/* Talk to netlink socket. */ /* Talk to netlink socket. */
ret = netlink_talk (&req.n, &netlink_cmd); ret = netlink_talk (&req.n, &zvrf->netlink_cmd, VRF_DEFAULT);
if (ret < 0) if (ret < 0)
return -1; return -1;
@ -1759,11 +1761,12 @@ _netlink_route_debug(
struct prefix *p, struct prefix *p,
struct nexthop *nexthop, struct nexthop *nexthop,
const char *routedesc, const char *routedesc,
int family) int family,
struct zebra_vrf *zvrf)
{ {
if (IS_ZEBRA_DEBUG_KERNEL) 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, routedesc,
lookup (nlmsg_str, cmd), lookup (nlmsg_str, cmd),
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
@ -1772,7 +1775,7 @@ _netlink_route_debug(
#else #else
inet_ntoa (p->u.prefix4), inet_ntoa (p->u.prefix4),
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
p->prefixlen, nexthop_type_to_str (nexthop->type)); p->prefixlen, zvrf->vrf_id, nexthop_type_to_str (nexthop->type));
} }
} }
@ -1785,6 +1788,8 @@ netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen)
char buf[256]; char buf[256];
} req; } req;
struct zebra_vrf *zvrf = vrf_info_lookup (VRF_DEFAULT); //Pending
memset(&req.n, 0, sizeof(req.n)); memset(&req.n, 0, sizeof(req.n));
memset(&req.ndm, 0, sizeof(req.ndm)); memset(&req.ndm, 0, sizeof(req.ndm));
@ -1799,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_DST, &addr, 4);
addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); 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. */ /* Routing table change via netlink interface. */
@ -1825,6 +1830,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
char buf[NL_PKT_BUF_SIZE]; char buf[NL_PKT_BUF_SIZE];
} req; } req;
struct zebra_vrf *zvrf = vrf_info_lookup (rib->vrf_id);
memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
bytelen = (family == AF_INET ? 4 : 16); bytelen = (family == AF_INET ? 4 : 16);
@ -1946,7 +1953,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
{ {
routedesc = recursing ? "recursive, 1 hop" : "single hop"; 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, _netlink_route_build_singlepath(routedesc, bytelen,
nexthop, &req.n, &req.r, nexthop, &req.n, &req.r,
sizeof req, cmd); sizeof req, cmd);
@ -2027,7 +2034,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
nexthop_num++; nexthop_num++;
_netlink_route_debug(cmd, p, nexthop, _netlink_route_debug(cmd, p, nexthop,
routedesc, family); routedesc, family, zvrf);
_netlink_route_build_multipath(routedesc, bytelen, _netlink_route_build_multipath(routedesc, bytelen,
nexthop, rta, rtnh, &req.r, &src1); nexthop, rta, rtnh, &req.r, &src1);
rtnh = RTNH_NEXT (rtnh); rtnh = RTNH_NEXT (rtnh);
@ -2075,7 +2082,7 @@ skip:
snl.nl_family = AF_NETLINK; snl.nl_family = AF_NETLINK;
/* Talk to netlink socket. */ /* Talk to netlink socket. */
return netlink_talk (&req.n, &netlink_cmd); return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf);
} }
int int
@ -2138,6 +2145,8 @@ netlink_address (int cmd, int family, struct interface *ifp,
char buf[NL_PKT_BUF_SIZE]; char buf[NL_PKT_BUF_SIZE];
} req; } req;
struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
p = ifc->address; p = ifc->address;
memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE);
@ -2170,7 +2179,7 @@ netlink_address (int cmd, int family, struct interface *ifp,
addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label, addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
strlen (ifc->label) + 1); strlen (ifc->label) + 1);
return netlink_talk (&req.n, &netlink_cmd); return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf);
} }
int int
@ -2192,8 +2201,10 @@ extern struct thread_master *master;
static int static int
kernel_read (struct thread *thread) kernel_read (struct thread *thread)
{ {
netlink_parse_info (netlink_information_fetch, &netlink); struct zebra_vrf *zvrf = (struct zebra_vrf *)THREAD_ARG (thread);
thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); 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; return 0;
} }
@ -2232,7 +2243,7 @@ static void netlink_install_filter (int sock, __u32 pid)
/* Exported interface function. This function simply calls /* Exported interface function. This function simply calls
netlink_socket (). */ netlink_socket (). */
void void
kernel_init (void) kernel_init (struct zebra_vrf *zvrf)
{ {
unsigned long groups; unsigned long groups;
@ -2240,23 +2251,42 @@ kernel_init (void)
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR; groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR;
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
netlink_socket (&netlink, groups); netlink_socket (&zvrf->netlink, groups, zvrf->vrf_id);
netlink_socket (&netlink_cmd, 0); netlink_socket (&zvrf->netlink_cmd, 0, zvrf->vrf_id);
/* Register kernel socket. */ /* Register kernel socket. */
if (netlink.sock > 0) if (zvrf->netlink.sock > 0)
{ {
/* Only want non-blocking on the netlink event socket */ /* Only want non-blocking on the netlink event socket */
if (fcntl (netlink.sock, F_SETFL, O_NONBLOCK) < 0) if (fcntl (zvrf->netlink.sock, F_SETFL, O_NONBLOCK) < 0)
zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", netlink.name, zlog_err ("Can't set %s socket flags: %s", zvrf->netlink.name,
safe_strerror (errno)); safe_strerror (errno));
/* Set receive buffer size if it's set from command line */ /* Set receive buffer size if it's set from command line */
if (nl_rcvbufsize) if (nl_rcvbufsize)
netlink_recvbuf (&netlink, nl_rcvbufsize); netlink_recvbuf (&zvrf->netlink, nl_rcvbufsize);
netlink_install_filter (netlink.sock, netlink_cmd.snl.nl_pid); netlink_install_filter (zvrf->netlink.sock, zvrf->netlink_cmd.snl.nl_pid);
thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); 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;
} }
} }

View File

@ -44,8 +44,8 @@ nl_rtproto_to_str (u_char rtproto);
int int
netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen); netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen);
extern int netlink_route_read(void); extern int interface_lookup_netlink (struct zebra_vrf *zvrf);
extern int interface_lookup_netlink(void); extern int netlink_route_read (struct zebra_vrf *zvrf);
#endif /* HAVE_NETLINK */ #endif /* HAVE_NETLINK */

View File

@ -31,6 +31,7 @@
#include "linklist.h" #include "linklist.h"
#include "command.h" #include "command.h"
#include "privs.h" #include "privs.h"
#include "vrf.h"
#include "zebra/interface.h" #include "zebra/interface.h"
#include "zebra/rtadv.h" #include "zebra/rtadv.h"
@ -62,31 +63,11 @@ extern struct zebra_t zebrad;
enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER, enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER,
RTADV_TIMER_MSEC, RTADV_READ}; RTADV_TIMER_MSEC, RTADV_READ};
static void rtadv_event (enum rtadv_event, int); static void rtadv_event (struct zebra_vrf *, enum rtadv_event, int);
static int if_join_all_router (int, struct interface *); static int if_join_all_router (int, struct interface *);
static int if_leave_all_router (int, struct interface *); static int if_leave_all_router (int, struct interface *);
/* Structure which hold status of router advertisement. */
struct rtadv
{
int sock;
int adv_if_count;
int adv_msec_if_count;
struct thread *ra_read;
struct thread *ra_timer;
};
struct rtadv *rtadv = NULL;
static struct rtadv *
rtadv_new (void)
{
return XCALLOC (MTYPE_TMP, sizeof (struct rtadv));
}
static int static int
rtadv_recv_packet (int sock, u_char *buf, int buflen, rtadv_recv_packet (int sock, u_char *buf, int buflen,
struct sockaddr_in6 *from, unsigned int *ifindex, struct sockaddr_in6 *from, unsigned int *ifindex,
@ -389,24 +370,25 @@ rtadv_send_packet (int sock, struct interface *ifp)
static int static int
rtadv_timer (struct thread *thread) rtadv_timer (struct thread *thread)
{ {
struct zebra_vrf *zvrf = THREAD_ARG (thread);
struct listnode *node, *nnode; struct listnode *node, *nnode;
struct interface *ifp; struct interface *ifp;
struct zebra_if *zif; struct zebra_if *zif;
int period; int period;
rtadv->ra_timer = NULL; zvrf->rtadv.ra_timer = NULL;
if (rtadv->adv_msec_if_count == 0) if (zvrf->rtadv.adv_msec_if_count == 0)
{ {
period = 1000; /* 1 s */ period = 1000; /* 1 s */
rtadv_event (RTADV_TIMER, 1 /* 1 s */); rtadv_event (zvrf, RTADV_TIMER, 1 /* 1 s */);
} }
else else
{ {
period = 10; /* 10 ms */ period = 10; /* 10 ms */
rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */); rtadv_event (zvrf, RTADV_TIMER_MSEC, 10 /* 10 ms */);
} }
for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp)) for (ALL_LIST_ELEMENTS (vrf_iflist (zvrf->vrf_id), node, nnode, ifp))
{ {
if (if_is_loopback (ifp) || ! if_is_operative (ifp)) if (if_is_loopback (ifp) || ! if_is_operative (ifp))
continue; continue;
@ -421,7 +403,7 @@ rtadv_timer (struct thread *thread)
/* FIXME: using MaxRtrAdvInterval each time isn't what section /* FIXME: using MaxRtrAdvInterval each time isn't what section
6.2.4 of RFC4861 tells to do. */ 6.2.4 of RFC4861 tells to do. */
zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval; zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
rtadv_send_packet (rtadv->sock, ifp); rtadv_send_packet (zvrf->rtadv.sock, ifp);
} }
} }
} }
@ -431,9 +413,11 @@ rtadv_timer (struct thread *thread)
static void static void
rtadv_process_solicit (struct interface *ifp) rtadv_process_solicit (struct interface *ifp)
{ {
zlog_info ("Router solicitation received on %s", ifp->name); struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
rtadv_send_packet (rtadv->sock, ifp); zlog_info ("Router solicitation received on %s vrf %u", ifp->name, zvrf->vrf_id);
rtadv_send_packet (zvrf->rtadv.sock, ifp);
} }
static void static void
@ -513,17 +497,17 @@ rtadv_process_advert (u_char *msg, unsigned int len, struct interface *ifp,
static void static void
rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit, rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit,
struct sockaddr_in6 *from) struct sockaddr_in6 *from, vrf_id_t vrf_id)
{ {
struct icmp6_hdr *icmph; struct icmp6_hdr *icmph;
struct interface *ifp; struct interface *ifp;
struct zebra_if *zif; struct zebra_if *zif;
/* Interface search. */ /* Interface search. */
ifp = if_lookup_by_index (ifindex); ifp = if_lookup_by_index_vrf (ifindex, vrf_id);
if (ifp == NULL) if (ifp == NULL)
{ {
zlog_warn ("Unknown interface index: %d", ifindex); zlog_warn ("Unknown interface index: %d, vrf %u", ifindex, vrf_id);
return; return;
} }
@ -578,12 +562,13 @@ rtadv_read (struct thread *thread)
struct sockaddr_in6 from; struct sockaddr_in6 from;
unsigned int ifindex = 0; unsigned int ifindex = 0;
int hoplimit = -1; int hoplimit = -1;
struct zebra_vrf *zvrf = THREAD_ARG (thread);
sock = THREAD_FD (thread); sock = THREAD_FD (thread);
rtadv->ra_read = NULL; zvrf->rtadv.ra_read = NULL;
/* Register myself. */ /* Register myself. */
rtadv_event (RTADV_READ, sock); rtadv_event (zvrf, RTADV_READ, sock);
len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit); len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
@ -593,13 +578,13 @@ rtadv_read (struct thread *thread)
return len; return len;
} }
rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit, &from); rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit, &from, zvrf->vrf_id);
return 0; return 0;
} }
static int static int
rtadv_make_socket (void) rtadv_make_socket (vrf_id_t vrf_id)
{ {
int sock; int sock;
int ret; int ret;
@ -609,7 +594,7 @@ rtadv_make_socket (void)
zlog_err ("rtadv_make_socket: could not raise privs, %s", zlog_err ("rtadv_make_socket: could not raise privs, %s",
safe_strerror (errno) ); safe_strerror (errno) );
sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); sock = vrf_socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, vrf_id);
if ( zserv_privs.change (ZPRIVS_LOWER) ) if ( zserv_privs.change (ZPRIVS_LOWER) )
zlog_err ("rtadv_make_socket: could not lower privs, %s", zlog_err ("rtadv_make_socket: could not lower privs, %s",
@ -731,9 +716,11 @@ DEFUN (ipv6_nd_suppress_ra,
{ {
struct interface *ifp; struct interface *ifp;
struct zebra_if *zif; struct zebra_if *zif;
struct zebra_vrf *zvrf;
ifp = vty->index; ifp = vty->index;
zif = ifp->info; zif = ifp->info;
zvrf = vrf_info_lookup (ifp->vrf_id);
if (if_is_loopback (ifp)) if (if_is_loopback (ifp))
{ {
@ -745,12 +732,12 @@ DEFUN (ipv6_nd_suppress_ra,
{ {
zif->rtadv.AdvSendAdvertisements = 0; zif->rtadv.AdvSendAdvertisements = 0;
zif->rtadv.AdvIntervalTimer = 0; zif->rtadv.AdvIntervalTimer = 0;
rtadv->adv_if_count--; zvrf->rtadv.adv_if_count--;
if_leave_all_router (rtadv->sock, ifp); if_leave_all_router (zvrf->rtadv.sock, ifp);
if (rtadv->adv_if_count == 0) if (zvrf->rtadv.adv_if_count == 0)
rtadv_event (RTADV_STOP, 0); rtadv_event (zvrf, RTADV_STOP, 0);
} }
return CMD_SUCCESS; return CMD_SUCCESS;
@ -766,9 +753,11 @@ DEFUN (no_ipv6_nd_suppress_ra,
{ {
struct interface *ifp; struct interface *ifp;
struct zebra_if *zif; struct zebra_if *zif;
struct zebra_vrf *zvrf;
ifp = vty->index; ifp = vty->index;
zif = ifp->info; zif = ifp->info;
zvrf = vrf_info_lookup (ifp->vrf_id);
if (if_is_loopback (ifp)) if (if_is_loopback (ifp))
{ {
@ -780,12 +769,12 @@ DEFUN (no_ipv6_nd_suppress_ra,
{ {
zif->rtadv.AdvSendAdvertisements = 1; zif->rtadv.AdvSendAdvertisements = 1;
zif->rtadv.AdvIntervalTimer = 0; zif->rtadv.AdvIntervalTimer = 0;
rtadv->adv_if_count++; zvrf->rtadv.adv_if_count++;
if_join_all_router (rtadv->sock, ifp); if_join_all_router (zvrf->rtadv.sock, ifp);
if (rtadv->adv_if_count == 1) if (zvrf->rtadv.adv_if_count == 1)
rtadv_event (RTADV_START, rtadv->sock); rtadv_event (zvrf, RTADV_START, zvrf->rtadv.sock);
} }
return CMD_SUCCESS; return CMD_SUCCESS;
@ -802,6 +791,7 @@ DEFUN (ipv6_nd_ra_interval_msec,
unsigned interval; unsigned interval;
struct interface *ifp = (struct interface *) vty->index; struct interface *ifp = (struct interface *) vty->index;
struct zebra_if *zif = ifp->info; struct zebra_if *zif = ifp->info;
struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 70, 1800000); VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 70, 1800000);
if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000))
@ -811,10 +801,10 @@ DEFUN (ipv6_nd_ra_interval_msec,
} }
if (zif->rtadv.MaxRtrAdvInterval % 1000) if (zif->rtadv.MaxRtrAdvInterval % 1000)
rtadv->adv_msec_if_count--; zvrf->rtadv.adv_msec_if_count--;
if (interval % 1000) if (interval % 1000)
rtadv->adv_msec_if_count++; zvrf->rtadv.adv_msec_if_count++;
zif->rtadv.MaxRtrAdvInterval = interval; zif->rtadv.MaxRtrAdvInterval = interval;
zif->rtadv.MinRtrAdvInterval = 0.33 * interval; zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
@ -834,6 +824,7 @@ DEFUN (ipv6_nd_ra_interval,
unsigned interval; unsigned interval;
struct interface *ifp = (struct interface *) vty->index; struct interface *ifp = (struct interface *) vty->index;
struct zebra_if *zif = ifp->info; struct zebra_if *zif = ifp->info;
struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 1, 1800); VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 1, 1800);
if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime))
@ -843,7 +834,7 @@ DEFUN (ipv6_nd_ra_interval,
} }
if (zif->rtadv.MaxRtrAdvInterval % 1000) if (zif->rtadv.MaxRtrAdvInterval % 1000)
rtadv->adv_msec_if_count--; zvrf->rtadv.adv_msec_if_count--;
/* convert to milliseconds */ /* convert to milliseconds */
interval = interval * 1000; interval = interval * 1000;
@ -865,12 +856,14 @@ DEFUN (no_ipv6_nd_ra_interval,
{ {
struct interface *ifp; struct interface *ifp;
struct zebra_if *zif; struct zebra_if *zif;
struct zebra_vrf *zvrf;
ifp = (struct interface *) vty->index; ifp = (struct interface *) vty->index;
zif = ifp->info; zif = ifp->info;
zvrf = vrf_info_lookup (ifp->vrf_id);
if (zif->rtadv.MaxRtrAdvInterval % 1000) if (zif->rtadv.MaxRtrAdvInterval % 1000)
rtadv->adv_msec_if_count--; zvrf->rtadv.adv_msec_if_count--;
zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL; zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL; zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
@ -1609,9 +1602,6 @@ rtadv_config_write (struct vty *vty, struct interface *ifp)
u_char buf[INET6_ADDRSTRLEN]; u_char buf[INET6_ADDRSTRLEN];
int interval; int interval;
if (! rtadv)
return;
zif = ifp->info; zif = ifp->info;
if (! if_is_loopback (ifp)) if (! if_is_loopback (ifp))
@ -1696,16 +1686,18 @@ rtadv_config_write (struct vty *vty, struct interface *ifp)
static void static void
rtadv_event (enum rtadv_event event, int val) rtadv_event (struct zebra_vrf *zvrf, enum rtadv_event event, int val)
{ {
struct rtadv *rtadv = &zvrf->rtadv;
switch (event) switch (event)
{ {
case RTADV_START: case RTADV_START:
if (! rtadv->ra_read) if (! rtadv->ra_read)
rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val); rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, zvrf, val);
if (! rtadv->ra_timer) if (! rtadv->ra_timer)
rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer, rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
NULL, 0); zvrf, 0);
break; break;
case RTADV_STOP: case RTADV_STOP:
if (rtadv->ra_timer) if (rtadv->ra_timer)
@ -1721,17 +1713,17 @@ rtadv_event (enum rtadv_event event, int val)
break; break;
case RTADV_TIMER: case RTADV_TIMER:
if (! rtadv->ra_timer) if (! rtadv->ra_timer)
rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL, rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, zvrf,
val); val);
break; break;
case RTADV_TIMER_MSEC: case RTADV_TIMER_MSEC:
if (! rtadv->ra_timer) if (! rtadv->ra_timer)
rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer, rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
NULL, val); zvrf, val);
break; break;
case RTADV_READ: case RTADV_READ:
if (! rtadv->ra_read) if (! rtadv->ra_read)
rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val); rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, zvrf, val);
break; break;
default: default:
break; break;
@ -1740,17 +1732,29 @@ rtadv_event (enum rtadv_event event, int val)
} }
void void
rtadv_init (void) rtadv_init (struct zebra_vrf *zvrf)
{ {
int sock; zvrf->rtadv.sock = rtadv_make_socket (zvrf->vrf_id);
}
sock = rtadv_make_socket (); void
if (sock < 0) rtadv_terminate (struct zebra_vrf *zvrf)
return; {
rtadv_event (zvrf, RTADV_STOP, 0);
rtadv = rtadv_new (); if (zvrf->rtadv.sock >= 0)
rtadv->sock = sock; {
close (zvrf->rtadv.sock);
zvrf->rtadv.sock = -1;
}
zvrf->rtadv.adv_if_count = 0;
zvrf->rtadv.adv_msec_if_count = 0;
}
void
rtadv_cmd_init (void)
{
install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd); install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd); install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd); install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
@ -1845,7 +1849,17 @@ if_leave_all_router (int sock, struct interface *ifp)
#else #else
void void
rtadv_init (void) rtadv_init (struct zebra_vrf *zvrf)
{
/* Empty.*/;
}
void
rtadv_terminate (struct zebra_vrf *zvrf)
{
/* Empty.*/;
}
void
rtadv_cmd_init (void)
{ {
/* Empty.*/; /* Empty.*/;
} }

View File

@ -59,7 +59,6 @@ struct rtadv_prefix
}; };
extern void rtadv_config_write (struct vty *, struct interface *); extern void rtadv_config_write (struct vty *, struct interface *);
extern void rtadv_init (void);
/* RFC4584 Extension to Sockets API for Mobile IPv6 */ /* RFC4584 Extension to Sockets API for Mobile IPv6 */
@ -101,4 +100,8 @@ extern const char *rtadv_pref_strs[];
#endif /* RTADV */ #endif /* RTADV */
extern void rtadv_init (struct zebra_vrf *);
extern void rtadv_terminate (struct zebra_vrf *);
extern void rtadv_cmd_init (void);
#endif /* _ZEBRA_RTADV_H */ #endif /* _ZEBRA_RTADV_H */

View File

@ -25,6 +25,7 @@
#include "prefix.h" #include "prefix.h"
#include "log.h" #include "log.h"
#include "if.h" #include "if.h"
#include "vrf.h"
#include "zebra/rib.h" #include "zebra/rib.h"
#include "zebra/zserv.h" #include "zebra/zserv.h"
@ -90,11 +91,11 @@ handle_route_entry (mib2_ipRouteEntry_t *routeEntry)
gateway.s_addr = routeEntry->ipRouteNextHop; gateway.s_addr = routeEntry->ipRouteNextHop;
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &prefix, 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 void
route_read (void) route_read (struct zebra_vrf *zvrf)
{ {
char storage[RT_BUFSIZ]; char storage[RT_BUFSIZ];
@ -109,6 +110,10 @@ route_read (void)
struct strbuf msgdata; struct strbuf msgdata;
int flags, dev, retval, process; int flags, dev, retval, process;
if (zvrf->vrf_id != VRF_DEFAULT) {
return;
}
if ((dev = open (_PATH_GETMSG_ROUTE, O_RDWR)) == -1) { if ((dev = open (_PATH_GETMSG_ROUTE, O_RDWR)) == -1) {
zlog_warn ("can't open %s: %s", _PATH_GETMSG_ROUTE, zlog_warn ("can't open %s: %s", _PATH_GETMSG_ROUTE,
safe_strerror (errno)); safe_strerror (errno));

View File

@ -25,7 +25,7 @@
#include "zebra/zserv.h" #include "zebra/zserv.h"
#include "zebra/rt_netlink.h" #include "zebra/rt_netlink.h"
void route_read (void) void route_read (struct zebra_vrf *zvrf)
{ {
netlink_route_read (); netlink_route_read (zvrf);
} }

View File

@ -24,6 +24,7 @@
#include "memory.h" #include "memory.h"
#include "log.h" #include "log.h"
#include "vrf.h"
#include "zebra/zserv.h" #include "zebra/zserv.h"
#include "zebra/rt.h" #include "zebra/rt.h"
@ -31,7 +32,7 @@
/* Kernel routing table read up by sysctl function. */ /* Kernel routing table read up by sysctl function. */
void void
route_read (void) route_read (struct zebra_vrf *zvrf)
{ {
caddr_t buf, end, ref; caddr_t buf, end, ref;
size_t bufsiz; size_t bufsiz;
@ -47,7 +48,10 @@ route_read (void)
NET_RT_DUMP, NET_RT_DUMP,
0 0
}; };
if (zvrf->vrf_id != VRF_DEFAULT)
return;
/* Get buffer size. */ /* Get buffer size. */
if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0)
{ {

View File

@ -29,6 +29,7 @@
#include "log.h" #include "log.h"
#include "privs.h" #include "privs.h"
#include "sigevent.h" #include "sigevent.h"
#include "vrf.h"
#include "zebra/rib.h" #include "zebra/rib.h"
#include "zebra/zserv.h" #include "zebra/zserv.h"
@ -201,6 +202,71 @@ struct quagga_signal_t zebra_signals[] =
}, },
}; };
/* Callback upon creating a new VRF. */
static int
zebra_vrf_new (vrf_id_t vrf_id, void **info)
{
struct zebra_vrf *zvrf = *info;
if (! zvrf)
{
zvrf = zebra_vrf_alloc (vrf_id);
*info = (void *)zvrf;
}
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);
kernel_init (zvrf);
route_read (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);
}
kernel_terminate (zvrf);
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 ();
}
/* Main startup routine. */ /* Main startup routine. */
int int
main (int argc, char **argv) main (int argc, char **argv)
@ -292,7 +358,6 @@ main (int argc, char **argv)
cmd_init (1); cmd_init (1);
vty_init (zebrad.master); vty_init (zebrad.master);
memory_init (); memory_init ();
if_init();
zebra_debug_init (); zebra_debug_init ();
zebra_if_init (); zebra_if_init ();
test_cmd_init (); test_cmd_init ();
@ -302,8 +367,7 @@ main (int argc, char **argv)
access_list_init (); access_list_init ();
/* Make kernel routing socket. */ /* Make kernel routing socket. */
kernel_init (); zebra_vrf_init ();
route_read ();
zebra_vty_init(); zebra_vty_init();
/* Configuration file read*/ /* Configuration file read*/

View File

@ -330,7 +330,7 @@ zfpm_is_table_for_fpm (struct route_table *table)
* We only send the unicast tables in the main instance to the FPM * We only send the unicast tables in the main instance to the FPM
* at this point. * at this point.
*/ */
if (info->vrf->id != 0) if (info->zvrf->vrf_id != 0)
return 0; return 0;
if (info->safi != SAFI_UNICAST) if (info->safi != SAFI_UNICAST)

View File

@ -246,7 +246,7 @@ netlink_route_info_fill (netlink_route_info_t *ri, int cmd,
ri->af = rib_dest_af (dest); ri->af = rib_dest_af (dest);
ri->nlmsg_type = cmd; ri->nlmsg_type = cmd;
ri->rtm_table = rib_dest_vrf (dest)->id; ri->rtm_table = rib_dest_vrf (dest)->vrf_id;
ri->rtm_protocol = RTPROT_UNSPEC; ri->rtm_protocol = RTPROT_UNSPEC;
/* /*

View File

@ -35,6 +35,7 @@
#include "prefix.h" #include "prefix.h"
#include "routemap.h" #include "routemap.h"
#include "nexthop.h" #include "nexthop.h"
#include "vrf.h"
#include "zebra/rib.h" #include "zebra/rib.h"
#include "zebra/rt.h" #include "zebra/rt.h"
@ -78,137 +79,29 @@ static const struct
/* no entry/default: 150 */ /* no entry/default: 150 */
}; };
/* Vector for routing table. */
static vector vrf_vector;
/* /*
* vrf_table_create * nexthop_type_to_str
*/ */
static void const char *
vrf_table_create (struct vrf *vrf, afi_t afi, safi_t safi) nexthop_type_to_str (enum nexthop_types_t nh_type)
{ {
rib_table_info_t *info; static const char *desc[] = {
struct route_table *table; "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",
};
assert (!vrf->table[afi][safi]); if (nh_type >= ZEBRA_NUM_OF (desc))
return "<Invalid nh type>";
table = route_table_init (); return desc[nh_type];
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)
{
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;
if (vrf->other_table[afi][table_id] == NULL)
{
vrf->other_table[afi][table_id] = route_table_init();
}
return (vrf->other_table[afi][table_id]);
} }
int int
@ -583,7 +476,7 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
p.prefix = nexthop->gate.ipv4; p.prefix = nexthop->gate.ipv4;
/* Lookup table. */ /* Lookup table. */
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, rib->vrf_id);
if (! table) if (! table)
return 0; return 0;
@ -791,7 +684,7 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
p.prefix = nexthop->gate.ipv6; p.prefix = nexthop->gate.ipv6;
/* Lookup table. */ /* Lookup table. */
table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, rib->vrf_id);
if (! table) if (! table)
return 0; return 0;
@ -944,7 +837,7 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
} }
struct rib * 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 prefix_ipv4 p;
struct route_table *table; struct route_table *table;
@ -954,7 +847,7 @@ rib_match_ipv4 (struct in_addr addr)
int recursing; int recursing;
/* Lookup table. */ /* Lookup table. */
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
return 0; return 0;
@ -1006,7 +899,7 @@ rib_match_ipv4 (struct in_addr addr)
} }
struct rib * 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_table *table;
struct route_node *rn; struct route_node *rn;
@ -1015,7 +908,7 @@ rib_lookup_ipv4 (struct prefix_ipv4 *p)
int recursing; int recursing;
/* Lookup table. */ /* Lookup table. */
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
return 0; return 0;
@ -1062,7 +955,8 @@ rib_lookup_ipv4 (struct prefix_ipv4 *p)
* 3: no matches found * 3: no matches found
*/ */
int 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_table *table;
struct route_node *rn; struct route_node *rn;
@ -1072,7 +966,7 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate)
int nexthops_active; int nexthops_active;
/* Lookup table. */ /* Lookup table. */
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
return ZEBRA_RIB_LOOKUP_ERROR; return ZEBRA_RIB_LOOKUP_ERROR;
@ -1127,7 +1021,7 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate)
} }
struct rib * 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 prefix_ipv6 p;
struct route_table *table; struct route_table *table;
@ -1137,7 +1031,7 @@ rib_match_ipv6 (struct in6_addr *addr)
int recursing; int recursing;
/* Lookup table. */ /* Lookup table. */
table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
if (! table) if (! table)
return 0; return 0;
@ -1220,7 +1114,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib,
switch (nexthop->type) switch (nexthop->type)
{ {
case NEXTHOP_TYPE_IFINDEX: 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)) if (ifp && if_is_operative(ifp))
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
else else
@ -1229,7 +1123,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib,
case NEXTHOP_TYPE_IPV6_IFNAME: case NEXTHOP_TYPE_IPV6_IFNAME:
family = AFI_IP6; family = AFI_IP6;
case NEXTHOP_TYPE_IFNAME: 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 (ifp && if_is_operative(ifp))
{ {
if (set) if (set)
@ -1264,7 +1158,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib,
family = AFI_IP6; family = AFI_IP6;
if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6)) 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)) if (ifp && if_is_operative(ifp))
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
else else
@ -1306,7 +1200,8 @@ nexthop_active_check (struct route_node *rn, struct rib *rib,
memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr)); memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr));
/* It'll get set if required inside */ /* 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 (ret == RMAP_DENYMATCH)
{ {
if (IS_ZEBRA_DEBUG_RIB) if (IS_ZEBRA_DEBUG_RIB)
@ -2238,7 +2133,7 @@ rib_delnode (struct route_node *rn, struct rib *rib)
int int
rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
struct in_addr *gate, struct in_addr *src, 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) u_int32_t metric, u_char distance, safi_t safi)
{ {
struct rib *rib; struct rib *rib;
@ -2250,11 +2145,11 @@ rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
/* Lookup table. */ /* Lookup table. */
if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) 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_id);
} }
else else
{ {
table = vrf_other_route_table (AFI_IP, table_id, 0); table = zebra_vrf_other_route_table (AFI_IP, table_id, vrf_id);
} }
if (! table) if (! table)
return 0; return 0;
@ -2314,6 +2209,7 @@ rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
rib->flags = flags; rib->flags = flags;
rib->metric = metric; rib->metric = metric;
rib->table = table_id; rib->table = table_id;
rib->vrf_id = vrf_id;
rib->nexthop_num = 0; rib->nexthop_num = 0;
rib->uptime = time (NULL); rib->uptime = time (NULL);
@ -2367,8 +2263,8 @@ void _rib_dump (const char * func,
struct nexthop *nexthop, *tnexthop; struct nexthop *nexthop, *tnexthop;
int recursing; int recursing;
inet_ntop (p->family, &p->u.prefix, straddr, INET6_ADDRSTRLEN); zlog_debug ("%s: dumping RIB entry %p for %s vrf %u", func, rib,
zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr, p->prefixlen); prefix2str(pp, straddr, sizeof(straddr)), rib->vrf_id);
zlog_debug zlog_debug
( (
"%s: refcnt == %lu, uptime == %lu, type == %u, instance == %d, table == %d", "%s: refcnt == %lu, uptime == %lu, type == %u, instance == %d, table == %d",
@ -2426,10 +2322,10 @@ void rib_lookup_and_dump (struct prefix_ipv4 * p)
char prefix_buf[INET_ADDRSTRLEN]; char prefix_buf[INET_ADDRSTRLEN];
/* Lookup table. */ /* Lookup table. */
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
if (! table) if (! table)
{ {
zlog_err ("%s: vrf_table() returned NULL", __func__); zlog_err ("%s: zebra_vrf_table() returned NULL", __func__);
return; return;
} }
@ -2475,9 +2371,9 @@ void rib_lookup_and_pushup (struct prefix_ipv4 * p)
struct rib *rib; struct rib *rib;
unsigned changed = 0; 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; return;
} }
@ -2527,11 +2423,11 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
/* Lookup table. */ /* Lookup table. */
if ((rib->table == zebrad.rtm_table_default) || (rib->table == RT_TABLE_MAIN)) 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, rib->vrf_id);
} }
else else
{ {
table = vrf_other_route_table (AFI_IP, rib->table, 0); table = zebra_vrf_other_route_table (AFI_IP, rib->table, rib->vrf_id);
} }
if (! table) if (! table)
return 0; return 0;
@ -2601,7 +2497,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
/* XXX factor with rib_delete_ipv6 */ /* XXX factor with rib_delete_ipv6 */
int int
rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, 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) u_int32_t table_id, safi_t safi)
{ {
struct route_table *table; struct route_table *table;
@ -2617,11 +2513,11 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
/* Lookup table. */ /* Lookup table. */
if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) 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_id);
} }
else else
{ {
table = vrf_other_route_table(AFI_IP, table_id, 0); table = zebra_vrf_other_route_table(AFI_IP, table_id, vrf_id);
} }
if (! table) if (! table)
return 0; return 0;
@ -2632,15 +2528,13 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
{ {
if (gate) if (gate)
zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d", zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u via %s ifindex %d",
inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), prefix2str (p, buf1, sizeof(buf1)), vrf_id,
p->prefixlen,
inet_ntoa (*gate), inet_ntoa (*gate),
ifindex); ifindex);
else else
zlog_debug ("rib_delete_ipv4(): route delete %s/%d ifindex %d", zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u ifindex %d",
inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), prefix2str (p, buf1, sizeof(buf1)), vrf_id,
p->prefixlen,
ifindex); ifindex);
} }
@ -2651,15 +2545,13 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
{ {
if (gate) if (gate)
zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib", zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), prefix2str (p, buf1, sizeof(buf1)), vrf_id,
p->prefixlen,
inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN), inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
ifindex); ifindex);
else else
zlog_debug ("route %s/%d ifindex %d doesn't exist in rib", zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), prefix2str (p, buf1, sizeof(buf1)), vrf_id,
p->prefixlen,
ifindex); ifindex);
} }
return ZEBRA_ERR_RTNOEXIST; return ZEBRA_ERR_RTNOEXIST;
@ -2744,16 +2636,15 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
{ {
if (gate) if (gate)
zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib", zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), "doesn't exist in rib",
p->prefixlen, prefix2str (p, buf1, sizeof(buf1)), vrf_id,
inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN), inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
ifindex, ifindex,
type); type);
else else
zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib", zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), prefix2str (p, buf1, sizeof(buf1)), vrf_id,
p->prefixlen,
ifindex, ifindex,
type); type);
} }
@ -2779,7 +2670,7 @@ static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ro
struct prefix nh_p; struct prefix nh_p;
/* Lookup table. */ /* Lookup table. */
table = vrf_table (afi, safi, 0); table = zebra_vrf_table (afi, safi, si->vrf_id);
if (! table) if (! table)
return; return;
@ -2843,6 +2734,7 @@ static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ro
rib->instance = 0; rib->instance = 0;
rib->distance = si->distance; rib->distance = si->distance;
rib->metric = 0; rib->metric = 0;
rib->vrf_id = si->vrf_id;
rib->table = zebrad.rtm_table_default; rib->table = zebrad.rtm_table_default;
rib->nexthop_num = 0; rib->nexthop_num = 0;
rib->tag = si->tag; rib->tag = si->tag;
@ -2926,7 +2818,7 @@ static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_
struct prefix nh_p; struct prefix nh_p;
/* Lookup table. */ /* Lookup table. */
table = vrf_table (afi, safi, 0); table = zebra_vrf_table (afi, safi, si->vrf_id);
if (! table) if (! table)
return; return;
@ -3026,7 +2918,7 @@ static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_
/* Add static route into static route configuration. */ /* Add static route into static route configuration. */
int int
static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, 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; u_char type = 0;
struct route_node *rn; struct route_node *rn;
@ -3034,10 +2926,9 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
struct static_route *pp; struct static_route *pp;
struct static_route *cp; struct static_route *cp;
struct static_route *update = NULL; struct static_route *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 = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
if (! stable) if (! stable)
return -1; return -1;
@ -3080,6 +2971,7 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
si->distance = distance; si->distance = distance;
si->flags = flags; si->flags = flags;
si->tag = tag; si->tag = tag;
si->vrf_id = vrf_id;
if (gate) if (gate)
si->addr.ipv4 = *gate; si->addr.ipv4 = *gate;
@ -3122,7 +3014,7 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
/* Delete static route from static route configuration. */ /* Delete static route from static route configuration. */
int int
static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, 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; u_char type = 0;
struct route_node *rn; struct route_node *rn;
@ -3130,7 +3022,7 @@ static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
struct route_table *stable; struct route_table *stable;
/* Lookup table. */ /* 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) if (! stable)
return -1; return -1;
@ -3208,8 +3100,8 @@ rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
int int
rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, 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, struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id,
u_int32_t metric, u_char distance, safi_t safi) u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi)
{ {
struct rib *rib; struct rib *rib;
struct rib *same = NULL; struct rib *same = NULL;
@ -3220,11 +3112,11 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
/* Lookup table. */ /* Lookup table. */
if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) 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_id);
} }
else else
{ {
table = vrf_other_route_table(AFI_IP6, table_id, 0); table = zebra_vrf_other_route_table(AFI_IP6, table_id, vrf_id);
} }
if (! table) if (! table)
return 0; return 0;
@ -3280,6 +3172,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
rib->flags = flags; rib->flags = flags;
rib->metric = metric; rib->metric = metric;
rib->table = table_id; rib->table = table_id;
rib->vrf_id = vrf_id;
rib->nexthop_num = 0; rib->nexthop_num = 0;
rib->uptime = time (NULL); rib->uptime = time (NULL);
@ -3340,7 +3233,7 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi,
if (!rib) if (!rib)
return 0; return 0;
table = vrf_table (AFI_IP, safi, 0); table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT);
if (!table) if (!table)
return 0; return 0;
/* Make it sure prefixlen is applied to the prefix. */ /* Make it sure prefixlen is applied to the prefix. */
@ -3356,11 +3249,11 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi,
/* Lookup table. */ /* Lookup table. */
if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) 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 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) if (! table)
@ -3443,7 +3336,8 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi,
/* XXX factor with rib_delete_ipv6 */ /* XXX factor with rib_delete_ipv6 */
int int
rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, 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_table *table;
struct route_node *rn; struct route_node *rn;
@ -3461,11 +3355,11 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
/* Lookup table. */ /* Lookup table. */
if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) 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_id);
} }
else 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) if (! table)
return 0; return 0;
@ -3477,15 +3371,13 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
{ {
if (gate) if (gate)
zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib", zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN), prefix2str (p, buf1, sizeof(buf1)), vrf_id,
p->prefixlen,
inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN), inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
ifindex); ifindex);
else else
zlog_debug ("route %s/%d ifindex %d doesn't exist in rib", zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN), prefix2str (p, buf1, sizeof(buf1)), vrf_id,
p->prefixlen,
ifindex); ifindex);
} }
return ZEBRA_ERR_RTNOEXIST; return ZEBRA_ERR_RTNOEXIST;
@ -3571,16 +3463,15 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
{ {
if (gate) if (gate)
zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib", zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN), "doesn't exist in rib",
p->prefixlen, prefix2str (p, buf1, sizeof(buf1)), vrf_id,
inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN), inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
ifindex, ifindex,
type); type);
else else
zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib", zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN), prefix2str (p, buf1, sizeof(buf1)), vrf_id,
p->prefixlen,
ifindex, ifindex,
type); type);
} }
@ -3600,17 +3491,16 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
int int
static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
const char *ifname, u_char flags, u_short tag, 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 route_node *rn;
struct static_route *si; struct static_route *si;
struct static_route *pp; struct static_route *pp;
struct static_route *cp; struct static_route *cp;
struct static_route *update = NULL; struct static_route *update = NULL;
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 = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
if (! stable) if (! stable)
return -1; return -1;
@ -3653,6 +3543,7 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
si->distance = distance; si->distance = distance;
si->flags = flags; si->flags = flags;
si->tag = tag; si->tag = tag;
si->vrf_id = vrf_id;
switch (type) switch (type)
{ {
@ -3698,14 +3589,14 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
int int
static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
const char *ifname, u_short tag, u_char distance, const char *ifname, u_short tag, u_char distance,
u_int32_t vrf_id) vrf_id_t vrf_id)
{ {
struct route_node *rn; struct route_node *rn;
struct static_route *si; struct static_route *si;
struct route_table *stable; struct route_table *stable;
/* Lookup table. */ /* 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) if (! stable)
return -1; return -1;
@ -3751,13 +3642,13 @@ static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
/* RIB update function. */ /* RIB update function. */
void void
rib_update_static (void) rib_update_static (vrf_id_t vrf_id)
{ {
struct route_node *rn; struct route_node *rn;
struct route_table *table; struct route_table *table;
struct rib *rib, *next; struct rib *rib, *next;
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
if (table) if (table)
for (rn = route_top (table); rn; rn = route_next (rn)) for (rn = route_top (table); rn; rn = route_next (rn))
RNODE_FOREACH_RIB_SAFE (rn, rib, next) RNODE_FOREACH_RIB_SAFE (rn, rib, next)
@ -3767,7 +3658,7 @@ rib_update_static (void)
break; break;
} }
table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
if (table) if (table)
for (rn = route_top (table); rn; rn = route_next (rn)) for (rn = route_top (table); rn; rn = route_next (rn))
RNODE_FOREACH_RIB_SAFE (rn, rib, next) RNODE_FOREACH_RIB_SAFE (rn, rib, next)
@ -3780,18 +3671,18 @@ rib_update_static (void)
/* RIB update function. */ /* RIB update function. */
void void
rib_update (void) rib_update (vrf_id_t vrf_id)
{ {
struct route_node *rn; struct route_node *rn;
struct route_table *table; struct route_table *table;
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
if (table) if (table)
for (rn = route_top (table); rn; rn = route_next (rn)) for (rn = route_top (table); rn; rn = route_next (rn))
if (rnode_to_ribs (rn)) if (rnode_to_ribs (rn))
rib_queue_add (&zebrad, rn); rib_queue_add (&zebrad, rn);
table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
if (table) if (table)
for (rn = route_top (table); rn; rn = route_next (rn)) for (rn = route_top (table); rn; rn = route_next (rn))
if (rnode_to_ribs (rn)) if (rnode_to_ribs (rn))
@ -3824,8 +3715,15 @@ rib_weed_table (struct route_table *table)
void void
rib_weed_tables (void) rib_weed_tables (void)
{ {
rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0)); vrf_iter_t iter;
rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0)); 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. */ /* Delete self installed routes after zebra is relaunched. */
@ -3858,8 +3756,15 @@ rib_sweep_table (struct route_table *table)
void void
rib_sweep_route (void) rib_sweep_route (void)
{ {
rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0)); vrf_iter_t iter;
rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0)); 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'. */ /* Remove specific by protocol routes from 'table'. */
@ -3891,12 +3796,20 @@ rib_score_proto_table (u_char proto, u_short instance, struct route_table *table
unsigned long unsigned long
rib_score_proto (u_char proto, u_short instance) rib_score_proto (u_char proto, u_short instance)
{ {
return rib_score_proto_table (proto, instance, vrf_table (AFI_IP, SAFI_UNICAST, 0)) vrf_iter_t iter;
+rib_score_proto_table (proto, instance, vrf_table (AFI_IP6, SAFI_UNICAST, 0)); 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. */ /* Close RIB and clean up kernel routes. */
static void void
rib_close_table (struct route_table *table) rib_close_table (struct route_table *table)
{ {
struct route_node *rn; struct route_node *rn;
@ -3920,14 +3833,21 @@ rib_close_table (struct route_table *table)
void void
rib_close (void) rib_close (void)
{ {
struct listnode *node, *nnode; vrf_iter_t iter;
struct zebra_vrf *zvrf;
struct listnode *node;
struct interface *ifp; struct interface *ifp;
rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0)); for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0)); {
if ((zvrf = vrf_iter2info (iter)) != NULL)
for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp)) {
if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp); 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. */ /* Routing information base initialize. */
@ -3935,8 +3855,6 @@ void
rib_init (void) rib_init (void)
{ {
rib_queue_init (&zebrad); rib_queue_init (&zebrad);
/* VRF initialization. */
vrf_init ();
} }
/* /*
@ -3947,15 +3865,19 @@ rib_init (void)
* Returns TRUE if a vrf id was found, FALSE otherwise. * Returns TRUE if a vrf id was found, FALSE otherwise.
*/ */
static inline int 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 = zvrf->vrf_id;
{ return 1;
*next_id_p = id;
return 1;
}
} }
return 0; return 0;
@ -4003,7 +3925,7 @@ rib_tables_iter_next (rib_tables_iter_t *iter)
while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis)) 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, afi_safis[iter->afi_safi_ix].safi,
iter->vrf_id); iter->vrf_id);
if (table) if (table)
@ -4041,3 +3963,130 @@ rib_tables_iter_next (rib_tables_iter_t *iter)
return table; 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;
#ifdef HAVE_NETLINK
char nl_name[64];
#endif
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;
#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;
}
/* Lookup VRF by identifier. */
struct zebra_vrf *
zebra_vrf_lookup (vrf_id_t vrf_id)
{
return vrf_info_lookup (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]);
}

View File

@ -36,6 +36,7 @@
#include "routemap.h" #include "routemap.h"
#include "stream.h" #include "stream.h"
#include "nexthop.h" #include "nexthop.h"
#include "vrf.h"
#include "zebra/rib.h" #include "zebra/rib.h"
#include "zebra/rt.h" #include "zebra/rt.h"
@ -50,6 +51,16 @@ extern struct zebra_t zebrad;
static void free_state(struct rib *rib, struct route_node *rn); static void free_state(struct rib *rib, struct route_node *rn);
static void copy_state(struct rnh *rnh, struct rib *rib, static void copy_state(struct rnh *rnh, struct rib *rib,
struct route_node *rn); struct route_node *rn);
#define lookup_rnh_table(v, f) \
({ \
struct zebra_vrf *zvrf; \
struct route_table *t = NULL; \
zvrf = zebra_vrf_lookup(v); \
if (zvrf) \
t = zvrf->rnh_table[family2afi(f)]; \
t; \
})
static int compare_state(struct rib *r1, struct rib *r2); static int compare_state(struct rib *r1, struct rib *r2);
static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type); static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type);
static void print_rnh(struct route_node *rn, struct vty *vty); static void print_rnh(struct route_node *rn, struct vty *vty);
@ -57,21 +68,21 @@ static void print_rnh(struct route_node *rn, struct vty *vty);
int zebra_rnh_ip_default_route = 0; int zebra_rnh_ip_default_route = 0;
int zebra_rnh_ipv6_default_route = 0; int zebra_rnh_ipv6_default_route = 0;
static inline struct route_table *get_rnh_table(int vrfid, int family, static inline struct route_table *get_rnh_table(vrf_id_t vrfid, int family,
rnh_type_t type) rnh_type_t type)
{ {
struct vrf *vrf; struct zebra_vrf *zvrf;
struct route_table *t = NULL; struct route_table *t = NULL;
vrf = vrf_lookup(vrfid); zvrf = zebra_vrf_lookup(vrfid);
if (vrf) if (zvrf)
switch (type) switch (type)
{ {
case RNH_NEXTHOP_TYPE: case RNH_NEXTHOP_TYPE:
t = vrf->rnh_table[family2afi(family)]; t = zvrf->rnh_table[family2afi(family)];
break; break;
case RNH_IMPORT_CHECK_TYPE: case RNH_IMPORT_CHECK_TYPE:
t = vrf->import_check_table[family2afi(family)]; t = zvrf->import_check_table[family2afi(family)];
break; break;
} }
@ -85,7 +96,7 @@ char *rnh_str (struct rnh *rnh, char *buf, int size)
} }
struct rnh * struct rnh *
zebra_add_rnh (struct prefix *p, u_int32_t vrfid, rnh_type_t type) zebra_add_rnh (struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
{ {
struct route_table *table; struct route_table *table;
struct route_node *rn; struct route_node *rn;
@ -125,7 +136,7 @@ zebra_add_rnh (struct prefix *p, u_int32_t vrfid, rnh_type_t type)
} }
struct rnh * struct rnh *
zebra_lookup_rnh (struct prefix *p, u_int32_t vrfid, rnh_type_t type) zebra_lookup_rnh (struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
{ {
struct route_table *table; struct route_table *table;
struct route_node *rn; struct route_node *rn;
@ -262,7 +273,7 @@ zebra_evaluate_rnh_nexthops(int family, struct rib *rib, struct route_node *prn,
} }
int int
zebra_evaluate_rnh (int vrfid, int family, int force, rnh_type_t type, zebra_evaluate_rnh (vrf_id_t vrfid, int family, int force, rnh_type_t type,
struct prefix *p) struct prefix *p)
{ {
struct route_table *ptable; struct route_table *ptable;
@ -289,7 +300,7 @@ zebra_evaluate_rnh (int vrfid, int family, int force, rnh_type_t type,
return -1; return -1;
} }
ptable = vrf_table(family2afi(family), SAFI_UNICAST, vrfid); ptable = zebra_vrf_table(family2afi(family), SAFI_UNICAST, vrfid);
if (!ptable) if (!ptable)
{ {
zlog_debug("evaluate_rnh_table: prefix table not found\n"); zlog_debug("evaluate_rnh_table: prefix table not found\n");
@ -557,7 +568,7 @@ zebra_evaluate_rnh (int vrfid, int family, int force, rnh_type_t type,
} }
int int
zebra_dispatch_rnh_table (int vrfid, int family, struct zserv *client, zebra_dispatch_rnh_table (vrf_id_t vrfid, int family, struct zserv *client,
rnh_type_t type) rnh_type_t type)
{ {
struct route_table *ntable; struct route_table *ntable;
@ -591,7 +602,7 @@ zebra_dispatch_rnh_table (int vrfid, int family, struct zserv *client,
} }
void void
zebra_print_rnh_table (int vrfid, int af, struct vty *vty, rnh_type_t type) zebra_print_rnh_table (vrf_id_t vrfid, int af, struct vty *vty, rnh_type_t type)
{ {
struct route_table *table; struct route_table *table;
struct route_node *rn; struct route_node *rn;
@ -609,7 +620,7 @@ zebra_print_rnh_table (int vrfid, int af, struct vty *vty, rnh_type_t type)
} }
int int
zebra_cleanup_rnh_client (int vrfid, int family, struct zserv *client, zebra_cleanup_rnh_client (vrf_id_t vrfid, int family, struct zserv *client,
rnh_type_t type) rnh_type_t type)
{ {
struct route_table *ntable; struct route_table *ntable;

View File

@ -52,9 +52,9 @@ typedef enum
extern int zebra_rnh_ip_default_route; extern int zebra_rnh_ip_default_route;
extern int zebra_rnh_ipv6_default_route; extern int zebra_rnh_ipv6_default_route;
extern struct rnh *zebra_add_rnh(struct prefix *p, u_int32_t vrfid, extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid,
rnh_type_t type); rnh_type_t type);
extern struct rnh *zebra_lookup_rnh(struct prefix *p, u_int32_t vrfid, extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid,
rnh_type_t type); rnh_type_t type);
extern void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type); extern void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type);
extern void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, rnh_type_t type); extern void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, rnh_type_t type);
@ -62,11 +62,11 @@ extern void zebra_register_rnh_static_nh(struct prefix *, struct route_node *);
extern void zebra_deregister_rnh_static_nh(struct prefix *, struct route_node *); extern void zebra_deregister_rnh_static_nh(struct prefix *, struct route_node *);
extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client, extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client,
rnh_type_t type); rnh_type_t type);
extern int zebra_evaluate_rnh(int vrfid, int family, int force, rnh_type_t type, extern int zebra_evaluate_rnh(vrf_id_t vrfid, int family, int force, rnh_type_t type,
struct prefix *p); struct prefix *p);
extern int zebra_dispatch_rnh_table(int vrfid, int family, struct zserv *cl, rnh_type_t); extern int zebra_dispatch_rnh_table(vrf_id_t vrfid, int family, struct zserv *cl, rnh_type_t);
extern void zebra_print_rnh_table(int vrfid, int family, struct vty *vty, rnh_type_t); extern void zebra_print_rnh_table(vrf_id_t vrfid, int family, struct vty *vty, rnh_type_t);
extern char *rnh_str(struct rnh *rnh, char *buf, int size); extern char *rnh_str(struct rnh *rnh, char *buf, int size);
extern int zebra_cleanup_rnh_client(int vrf, int family, struct zserv *client, extern int zebra_cleanup_rnh_client(vrf_id_t vrf, int family, struct zserv *client,
rnh_type_t type); rnh_type_t type);
#endif /*_ZEBRA_RNH_H */ #endif /*_ZEBRA_RNH_H */

View File

@ -6,11 +6,11 @@
int zebra_rnh_ip_default_route = 0; int zebra_rnh_ip_default_route = 0;
int zebra_rnh_ipv6_default_route = 0; int zebra_rnh_ipv6_default_route = 0;
int zebra_evaluate_rnh (int vrfid, int family, int force, rnh_type_t type, int zebra_evaluate_rnh (vrf_id_t vrfid, int family, int force, rnh_type_t type,
struct prefix *p) struct prefix *p)
{ return 0; } { return 0; }
void zebra_print_rnh_table (int vrfid, int family, struct vty *vty, void zebra_print_rnh_table (vrf_id_t vrfid, int family, struct vty *vty,
rnh_type_t type) rnh_type_t type)
{} {}

View File

@ -29,6 +29,7 @@
#include "filter.h" #include "filter.h"
#include "plist.h" #include "plist.h"
#include "nexthop.h" #include "nexthop.h"
#include "vrf.h"
#include "zebra/zserv.h" #include "zebra/zserv.h"
#include "zebra/debug.h" #include "zebra/debug.h"
@ -45,6 +46,7 @@ extern struct zebra_t zebrad;
struct nh_rmap_obj struct nh_rmap_obj
{ {
struct nexthop *nexthop; struct nexthop *nexthop;
vrf_id_t vrf_id;
u_int32_t source_protocol; u_int32_t source_protocol;
int metric; int metric;
u_short tag; u_short tag;
@ -255,12 +257,12 @@ route_match_interface (void *rule, struct prefix *prefix,
{ {
if (strcasecmp(ifname, "any") == 0) if (strcasecmp(ifname, "any") == 0)
return RMAP_MATCH; return RMAP_MATCH;
ifindex = ifname2ifindex(ifname);
if (ifindex == 0)
return RMAP_NOMATCH;
nh_data = object; nh_data = object;
if (!nh_data || !nh_data->nexthop) if (!nh_data || !nh_data->nexthop)
return RMAP_NOMATCH; return RMAP_NOMATCH;
ifindex = ifname2ifindex_vrf (ifname, nh_data->vrf_id);
if (ifindex == 0)
return RMAP_NOMATCH;
if (nh_data->nexthop->ifindex == ifindex) if (nh_data->nexthop->ifindex == ifindex)
return RMAP_MATCH; return RMAP_MATCH;
} }
@ -657,6 +659,7 @@ DEFUN (set_src,
struct interface *pif = NULL; struct interface *pif = NULL;
int family; int family;
struct prefix p; struct prefix p;
vrf_iter_t iter;
if (inet_pton(AF_INET, argv[0], &src.ipv4) != 1) if (inet_pton(AF_INET, argv[0], &src.ipv4) != 1)
{ {
@ -683,10 +686,18 @@ DEFUN (set_src,
return CMD_WARNING; return CMD_WARNING;
} }
if (family == AF_INET) for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
pif = if_lookup_exact_address ((void *)&src.ipv4, AF_INET); {
else if (family == AF_INET6) if (family == AF_INET)
pif = if_lookup_exact_address ((void *)&src.ipv6, AF_INET6); pif = if_lookup_exact_address_vrf ((void *)&src.ipv4, AF_INET,
vrf_iter2id (iter));
else if (family == AF_INET6)
pif = if_lookup_exact_address_vrf ((void *)&src.ipv6, AF_INET6,
vrf_iter2id (iter));
if (pif != NULL)
break;
}
if (!pif) if (!pif)
{ {
@ -767,7 +778,7 @@ DEFUN (ip_protocol,
if (IS_ZEBRA_DEBUG_RIB) if (IS_ZEBRA_DEBUG_RIB)
zlog_debug ("%s: calling rib_update", __func__); zlog_debug ("%s: calling rib_update", __func__);
rib_update(); rib_update(VRF_DEFAULT);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -804,7 +815,7 @@ DEFUN (no_ip_protocol,
if (IS_ZEBRA_DEBUG_RIB) if (IS_ZEBRA_DEBUG_RIB)
zlog_debug ("%s: calling rib_update", __func__); zlog_debug ("%s: calling rib_update", __func__);
rib_update(); rib_update(VRF_DEFAULT);
} }
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -879,7 +890,7 @@ DEFUN (ipv6_protocol,
if (IS_ZEBRA_DEBUG_RIB) if (IS_ZEBRA_DEBUG_RIB)
zlog_debug ("%s: calling rib_update", __func__); zlog_debug ("%s: calling rib_update", __func__);
rib_update(); rib_update(VRF_DEFAULT);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -916,7 +927,7 @@ DEFUN (no_ipv6_protocol,
if (IS_ZEBRA_DEBUG_RIB) if (IS_ZEBRA_DEBUG_RIB)
zlog_debug ("%s: calling rib_update", __func__); zlog_debug ("%s: calling rib_update", __func__);
rib_update(); rib_update(VRF_DEFAULT);
} }
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -1590,7 +1601,7 @@ zebra_route_map_update_timer (struct thread *thread)
if (IS_ZEBRA_DEBUG_RIB) if (IS_ZEBRA_DEBUG_RIB)
zlog_debug ("%s: calling rib_update", __func__); 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_INET, 1, RNH_NEXTHOP_TYPE, NULL);
zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
@ -1621,13 +1632,14 @@ zebra_route_map_write_delay_timer (struct vty *vty)
route_map_result_t route_map_result_t
zebra_route_map_check (int family, int rib_type, struct prefix *p, 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; struct route_map *rmap = NULL;
route_map_result_t ret = RMAP_MATCH; route_map_result_t ret = RMAP_MATCH;
struct nh_rmap_obj nh_obj; struct nh_rmap_obj nh_obj;
nh_obj.nexthop = nexthop; nh_obj.nexthop = nexthop;
nh_obj.vrf_id = vrf_id;
nh_obj.source_protocol = rib_type; nh_obj.source_protocol = rib_type;
nh_obj.metric = 0; nh_obj.metric = 0;
nh_obj.tag = tag; nh_obj.tag = tag;
@ -1652,6 +1664,7 @@ zebra_nht_route_map_check (int family, int client_proto, struct prefix *p,
struct nh_rmap_obj nh_obj; struct nh_rmap_obj nh_obj;
nh_obj.nexthop = nexthop; nh_obj.nexthop = nexthop;
nh_obj.vrf_id = rib->vrf_id;
nh_obj.source_protocol = rib->type; nh_obj.source_protocol = rib->type;
nh_obj.metric = rib->metric; nh_obj.metric = rib->metric;
nh_obj.tag = rib->tag; nh_obj.tag = rib->tag;

View File

@ -19,6 +19,10 @@
* 02111-1307, USA. * 02111-1307, USA.
*/ */
/*
* Currently SNMP is only running properly for MIBs in the default VRF.
*/
#include <zebra.h> #include <zebra.h>
#ifdef HAVE_SNMP #ifdef HAVE_SNMP
@ -31,6 +35,7 @@
#include "command.h" #include "command.h"
#include "smux.h" #include "smux.h"
#include "table.h" #include "table.h"
#include "vrf.h"
#include "zebra/rib.h" #include "zebra/rib.h"
#include "zebra/zserv.h" #include "zebra/zserv.h"
@ -143,7 +148,7 @@ ipFwNumber (struct variable *v, oid objid[], size_t *objid_len,
if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED) if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
return NULL; return NULL;
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
if (! table) if (! table)
return NULL; return NULL;
@ -168,7 +173,7 @@ ipCidrNumber (struct variable *v, oid objid[], size_t *objid_len,
if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED) if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
return NULL; return NULL;
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
if (! table) if (! table)
return 0; return 0;
@ -330,7 +335,7 @@ get_fwtable_route_node(struct variable *v, oid objid[], size_t *objid_len,
if (exact && (*objid_len != (unsigned) v->namelen + 10)) if (exact && (*objid_len != (unsigned) v->namelen + 10))
return; return;
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
if (! table) if (! table)
return; return;

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,7 @@
#include "network.h" #include "network.h"
#include "buffer.h" #include "buffer.h"
#include "nexthop.h" #include "nexthop.h"
#include "vrf.h"
#include "zebra/zserv.h" #include "zebra/zserv.h"
#include "zebra/router-id.h" #include "zebra/router-id.h"
@ -643,7 +644,7 @@ zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr)
struct nexthop *nexthop; struct nexthop *nexthop;
/* Lookup nexthop. */ /* Lookup nexthop. */
rib = rib_match_ipv6 (addr); rib = rib_match_ipv6 (addr, VRF_DEFAULT);
/* Get output stream. */ /* Get output stream. */
s = client->obuf; s = client->obuf;
@ -710,7 +711,7 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr)
struct nexthop *nexthop; struct nexthop *nexthop;
/* Lookup nexthop. */ /* Lookup nexthop. */
rib = rib_match_ipv4 (addr); rib = rib_match_ipv4 (addr, VRF_DEFAULT);
/* Get output stream. */ /* Get output stream. */
s = client->obuf; s = client->obuf;
@ -892,7 +893,7 @@ zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p)
struct nexthop *nexthop; struct nexthop *nexthop;
/* Lookup nexthop. */ /* Lookup nexthop. */
rib = rib_lookup_ipv4 (p); rib = rib_lookup_ipv4 (p, VRF_DEFAULT);
/* Get output stream. */ /* Get output stream. */
s = client->obuf; s = client->obuf;
@ -947,7 +948,8 @@ zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p)
/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */ /* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */
int int
zsend_router_id_update (struct zserv *client, struct prefix *p) zsend_router_id_update (struct zserv *client, struct prefix *p,
vrf_id_t vrf_id)
{ {
struct stream *s; struct stream *s;
int blen; int blen;
@ -1076,6 +1078,9 @@ zread_ipv4_add (struct zserv *client, u_short length)
p.prefixlen = stream_getc (s); p.prefixlen = stream_getc (s);
stream_get (&p.prefix, s, PSIZE (p.prefixlen)); stream_get (&p.prefix, s, PSIZE (p.prefixlen));
/* VRF ID */
rib->vrf_id = VRF_DEFAULT;
/* Nexthop parse. */ /* Nexthop parse. */
if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP)) if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP))
{ {
@ -1231,7 +1236,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)
api.tag = 0; api.tag = 0;
rib_delete_ipv4 (api.type, api.instance, api.flags, &p, nexthop_p, ifindex, 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++; client->v4_route_del_cnt++;
return 0; return 0;
} }
@ -1505,6 +1510,7 @@ zread_ipv6_add (struct zserv *client, u_short length)
/* Table */ /* Table */
rib->table=zebrad.rtm_table_default; rib->table=zebrad.rtm_table_default;
rib->vrf_id = VRF_DEFAULT;
ret = rib_add_ipv6_multipath ((struct prefix *)&p, rib, safi, ifindex); ret = rib_add_ipv6_multipath ((struct prefix *)&p, rib, safi, ifindex);
/* Stats */ /* Stats */
if (ret > 0) if (ret > 0)
@ -1584,9 +1590,11 @@ zread_ipv6_delete (struct zserv *client, u_short length)
api.tag = 0; api.tag = 0;
if (IN6_IS_ADDR_UNSPECIFIED (&nexthop)) 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 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++; client->v6_route_del_cnt++;
return 0; return 0;
@ -1616,9 +1624,9 @@ zread_router_id_add (struct zserv *client, u_short length)
/* Router-id information is needed. */ /* Router-id information is needed. */
client->ridinfo = 1; client->ridinfo = 1;
router_id_get (&p); router_id_get (&p, VRF_DEFAULT);
return zsend_router_id_update (client,&p); return zsend_router_id_update (client, &p, VRF_DEFAULT);
} }
/* Unregister zebra server router-id information. */ /* Unregister zebra server router-id information. */

View File

@ -134,9 +134,10 @@ extern void zebra_if_init (void);
extern void zebra_zserv_socket_init (char *path); extern void zebra_zserv_socket_init (char *path);
extern void hostinfo_get (void); extern void hostinfo_get (void);
extern void rib_init (void); extern void rib_init (void);
extern void interface_list (void); extern void interface_list (struct zebra_vrf *);
extern void kernel_init (void); extern void route_read (struct zebra_vrf *);
extern void route_read (void); extern void kernel_init (struct zebra_vrf *);
extern void kernel_terminate (struct zebra_vrf *);
extern void zebra_route_map_init (void); extern void zebra_route_map_init (void);
extern void zebra_snmp_init (void); extern void zebra_snmp_init (void);
extern void zebra_vty_init (void); extern void zebra_vty_init (void);
@ -151,7 +152,9 @@ extern void nbr_connected_delete_ipv6 (struct interface *, struct in6_addr *, u_
extern int zsend_interface_update (int, struct zserv *, struct interface *); extern int zsend_interface_update (int, struct zserv *, struct interface *);
extern int zsend_redistribute_route (int, struct zserv *, struct prefix *, extern int zsend_redistribute_route (int, struct zserv *, struct prefix *,
struct rib *); struct rib *);
extern int zsend_router_id_update(struct zserv *, struct prefix *); extern int zsend_router_id_update (struct zserv *, struct prefix *,
vrf_id_t);
extern pid_t pid; extern pid_t pid;
extern void zserv_create_header(struct stream *s, uint16_t cmd); extern void zserv_create_header(struct stream *s, uint16_t cmd);
@ -162,6 +165,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, extern route_map_result_t zebra_route_map_check (int family, int rib_type,
struct prefix *p, struct prefix *p,
struct nexthop *nexthop, struct nexthop *nexthop,
vrf_id_t vrf_id,
u_short tag); u_short tag);
extern route_map_result_t zebra_nht_route_map_check (int family, extern route_map_result_t zebra_nht_route_map_check (int family,
int client_proto, int client_proto,