From 88b8ed8decb5aa767979a73dcdabe71c7f515323 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 28 Oct 2015 01:54:48 +0000 Subject: [PATCH 01/27] BGP: peer-group restrictions should be relaxed, update-groups determine outbound policy anyway Signed-off-by: Daniel Walton Reviewed-by: Vivek Venkataraman Ticket: CM-7933 --- bgpd/bgp_route.c | 13 ++- bgpd/bgp_updgrp.c | 3 - bgpd/bgp_updgrp.h | 1 + bgpd/bgp_vty.c | 72 +++++++------ bgpd/bgpd.c | 260 ++++++++++++++++------------------------------ bgpd/bgpd.h | 45 ++++---- 6 files changed, 162 insertions(+), 232 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index fafb29943f..59dd04a933 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1136,12 +1136,16 @@ bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi, struct peer *peer, struct attr *attr) { 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 - 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); // 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)) { /* 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 || CHECK_FLAG (peer->af_flags[afi][safi], diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c index f07e886eb0..a280b55c11 100644 --- a/bgpd/bgp_updgrp.c +++ b/bgpd/bgp_updgrp.c @@ -1719,9 +1719,6 @@ update_group_adjust_soloness (struct peer *peer, int set) struct peer_group *group; 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)) { peer_lonesoul_or_not (peer, set); diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h index bf48e12a5d..542517f62e 100644 --- a/bgpd/bgp_updgrp.h +++ b/bgpd/bgp_updgrp.h @@ -48,6 +48,7 @@ PEER_FLAG_REMOVE_PRIVATE_AS | \ PEER_FLAG_REMOVE_PRIVATE_AS_ALL | \ PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE | \ + PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE | \ PEER_FLAG_AS_OVERRIDE) #define PEER_UPDGRP_CAP_FLAGS (PEER_CAP_AS4_RCV) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index bd124aa783..38f3eb971e 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -210,15 +210,9 @@ bgp_vty_return (struct vty *vty, int ret) 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: str = "Peer-group has been shutdown. Activate the peer-group first"; 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: str = "Can't set override-capability and strict-capability-match at the same time"; break; @@ -3399,8 +3393,7 @@ DEFUN (neighbor_nexthop_self_force, { return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty), bgp_node_safi (vty), - (PEER_FLAG_FORCE_NEXTHOP_SELF | - PEER_FLAG_NEXTHOP_SELF)); + PEER_FLAG_FORCE_NEXTHOP_SELF); } DEFUN (no_neighbor_nexthop_self, @@ -3413,11 +3406,10 @@ DEFUN (no_neighbor_nexthop_self, { return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty), bgp_node_safi (vty), - (PEER_FLAG_NEXTHOP_SELF | - PEER_FLAG_FORCE_NEXTHOP_SELF)); + PEER_FLAG_NEXTHOP_SELF); } -ALIAS (no_neighbor_nexthop_self, +DEFUN (no_neighbor_nexthop_self_force, no_neighbor_nexthop_self_force_cmd, NO_NEIGHBOR_CMD2 "next-hop-self force", NO_STR @@ -3425,6 +3417,11 @@ ALIAS (no_neighbor_nexthop_self, NEIGHBOR_ADDR_STR2 "Disable the next hop calculation for this neighbor\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 */ DEFUN (neighbor_as_override, @@ -3460,10 +3457,6 @@ DEFUN (neighbor_remove_private_as, NEIGHBOR_ADDR_STR2 "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), bgp_node_safi (vty), PEER_FLAG_REMOVE_PRIVATE_AS); @@ -3477,12 +3470,8 @@ DEFUN (neighbor_remove_private_as_all, "Remove private ASNs in outbound updates\n" "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), bgp_node_safi (vty), - PEER_FLAG_REMOVE_PRIVATE_AS| PEER_FLAG_REMOVE_PRIVATE_AS_ALL); } @@ -3494,12 +3483,8 @@ DEFUN (neighbor_remove_private_as_replace_as, "Remove private ASNs 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), bgp_node_safi (vty), - PEER_FLAG_REMOVE_PRIVATE_AS| PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE); } @@ -3514,9 +3499,7 @@ DEFUN (neighbor_remove_private_as_all_replace_as, { return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty), bgp_node_safi (vty), - PEER_FLAG_REMOVE_PRIVATE_AS| - PEER_FLAG_REMOVE_PRIVATE_AS_ALL| - PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE); + PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE); } DEFUN (no_neighbor_remove_private_as, @@ -3529,12 +3512,10 @@ DEFUN (no_neighbor_remove_private_as, { return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty), bgp_node_safi (vty), - PEER_FLAG_REMOVE_PRIVATE_AS| - PEER_FLAG_REMOVE_PRIVATE_AS_ALL| - PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE); + PEER_FLAG_REMOVE_PRIVATE_AS); } -ALIAS (no_neighbor_remove_private_as, +DEFUN (no_neighbor_remove_private_as_all, no_neighbor_remove_private_as_all_cmd, NO_NEIGHBOR_CMD2 "remove-private-AS all", NO_STR @@ -3542,8 +3523,13 @@ ALIAS (no_neighbor_remove_private_as, NEIGHBOR_ADDR_STR2 "Remove private ASNs in outbound updates\n" "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_CMD2 "remove-private-AS replace-AS", NO_STR @@ -3551,8 +3537,13 @@ ALIAS (no_neighbor_remove_private_as, NEIGHBOR_ADDR_STR2 "Remove private ASNs 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_CMD2 "remove-private-AS all replace-AS", NO_STR @@ -3561,6 +3552,11 @@ ALIAS (no_neighbor_remove_private_as, "Remove private ASNs in outbound updates\n" "Apply to all AS numbers" "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. */ @@ -9153,8 +9149,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)) 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"); + 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)) json_object_boolean_true_add(json_addr, "privateAsNumsRemovedInUpdatesToNbr"); @@ -9336,8 +9336,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)) 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); + 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)) vty_out (vty, " Private AS numbers removed in updates to this neighbor%s", VTY_NEWLINE); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index ef0ba846a0..bb6e4bddc0 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -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 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. */ static void peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi) @@ -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_FORCE_NEXTHOP_SELF, 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 } }; @@ -3570,10 +3600,6 @@ peer_flag_modify (struct peer *peer, u_int32_t flag, int set) if (! found) 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 peer-group configuration. */ 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) return BGP_ERR_PEER_GROUP_SHUTDOWN; - else - return BGP_ERR_PEER_GROUP_HAS_THE_FLAG; } /* Flag conflict check. */ @@ -3646,14 +3670,6 @@ peer_flag_unset (struct peer *peer, u_int32_t flag) 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 peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag, int set) @@ -3677,10 +3693,6 @@ peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag, 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 && peer_sort (peer) != BGP_PEER_IBGP) @@ -3696,12 +3708,6 @@ peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag, && peer_sort (peer) == BGP_PEER_IBGP) 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. */ if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) { @@ -4166,10 +4172,6 @@ peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi, 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) || (rmap && ! peer->default_rmap[afi][safi].name) || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0)) @@ -4228,10 +4230,6 @@ peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi) 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)) { UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE); @@ -4339,10 +4337,6 @@ peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime) struct peer_group *group; 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. */ if (keepalive > 65535) return BGP_ERR_INVALID_VALUE; @@ -4380,9 +4374,6 @@ peer_timers_unset (struct peer *peer) struct peer_group *group; struct listnode *node, *nnode; - if (peer_group_active (peer)) - return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER; - /* Clear configuration. */ UNSET_FLAG (peer->config, PEER_CONFIG_TIMER); peer->keepalive = 0; @@ -4409,9 +4400,6 @@ peer_timers_connect_set (struct peer *peer, u_int32_t connect) struct peer_group *group; struct listnode *node, *nnode; - if (peer_group_active (peer)) - return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER; - if (connect > 65535) return BGP_ERR_INVALID_VALUE; @@ -4442,9 +4430,6 @@ peer_timers_connect_unset (struct peer *peer) struct peer_group *group; struct listnode *node, *nnode; - if (peer_group_active (peer)) - return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER; - /* Clear configuration. */ UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT); peer->connect = 0; @@ -4472,9 +4457,6 @@ peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv) struct peer_group *group; struct listnode *node, *nnode; - if (peer_group_active (peer)) - return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER; - if (routeadv > 600) return BGP_ERR_INVALID_VALUE; @@ -4510,9 +4492,6 @@ peer_advertise_interval_unset (struct peer *peer) struct peer_group *group; struct listnode *node, *nnode; - if (peer_group_active (peer)) - return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER; - UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV); peer->routeadv = 0; @@ -4640,9 +4619,6 @@ peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as) if (bgp->as == 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) return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS; @@ -4710,9 +4686,6 @@ peer_local_as_unset (struct peer *peer) struct peer_group *group; struct listnode *node, *nnode; - if (peer_group_active (peer)) - return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER; - if (! peer->change_local_as) return 0; @@ -4822,11 +4795,6 @@ peer_password_unset (struct peer *peer) 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)) bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); else @@ -4909,9 +4877,6 @@ peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct, if (direct != FILTER_IN && direct != FILTER_OUT) 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]; if (filter->plist[direct].name) @@ -4962,9 +4927,6 @@ peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) if (direct != FILTER_IN && direct != FILTER_OUT) 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]; /* apply peer-group filter */ @@ -5086,9 +5048,6 @@ peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct, if (direct != FILTER_IN && direct != FILTER_OUT) 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]; if (filter->dlist[direct].name) @@ -5138,9 +5097,6 @@ peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) if (direct != FILTER_IN && direct != FILTER_OUT) 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]; /* apply peer-group filter */ @@ -5265,9 +5221,6 @@ peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct, if (direct != FILTER_IN && direct != FILTER_OUT) 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]; if (filter->aslist[direct].name) @@ -5314,9 +5267,6 @@ peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct) if (direct != FILTER_IN && direct != FILTER_OUT) 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]; /* apply peer-group filter */ @@ -5452,10 +5402,6 @@ peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct, direct != RMAP_IMPORT && direct != RMAP_EXPORT) 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]; if (filter->map[direct].name) @@ -5505,10 +5451,6 @@ peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) direct != RMAP_IMPORT && direct != RMAP_EXPORT) 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]; /* apply peer-group filter */ @@ -5570,9 +5512,6 @@ peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi, 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]; if (filter->usmap.name) @@ -5615,9 +5554,6 @@ peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi) 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]; if (filter->usmap.name) @@ -6549,16 +6485,15 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE); /* ORF capability. */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM) - || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) - if (! peer->af_group[afi][safi]) + if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) || + peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM)) { vty_out (vty, " neighbor %s capability orf prefix-list", addr); - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM) - && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) + if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) && + peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM)) 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"); else vty_out (vty, " receive"); @@ -6566,85 +6501,77 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, } /* Route reflector client. */ - if (peer_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, - VTY_NEWLINE); + if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)) + vty_out (vty, " neighbor %s route-reflector-client%s", addr, VTY_NEWLINE); - /* Nexthop self. */ - if (peer_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", - addr, VTY_NEWLINE); - else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF) - && ! peer->af_group[afi][safi]) + /* next-hop-self force */ + if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_FORCE_NEXTHOP_SELF)) + vty_out (vty, " neighbor %s next-hop-self force%s", addr, VTY_NEWLINE); + + /* next-hop-self */ + if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE); /* remove-private-AS */ - if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS) && !peer->af_group[afi][safi]) - { - if (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_REPLACE)) - vty_out (vty, " neighbor %s remove-private-AS all replace-AS%s", addr, VTY_NEWLINE); + if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) + vty_out (vty, " neighbor %s remove-private-AS all replace-AS%s", addr, VTY_NEWLINE); - else if (peer_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); + 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); - else if (peer_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); + 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); - else - vty_out (vty, " neighbor %s remove-private-AS%s", addr, VTY_NEWLINE); - } + 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); /* as-override */ - if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE) && - !peer->af_group[afi][safi]) + if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) vty_out (vty, " neighbor %s as-override%s", addr, VTY_NEWLINE); /* 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 (peer_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, " neighbor %s send-community both%s", addr, VTY_NEWLINE); - else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) - vty_out (vty, " neighbor %s send-community extended%s", - addr, VTY_NEWLINE); - else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)) - vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE); - } - else - { - if (! peer_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", - addr, VTY_NEWLINE); - else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) - 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)) - vty_out (vty, " no neighbor %s send-community%s", - addr, VTY_NEWLINE); - } + if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) + && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) + vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE); + else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) + vty_out (vty, " neighbor %s send-community extended%s", + addr, VTY_NEWLINE); + else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)) + vty_out (vty, " neighbor %s send-community%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) && + !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)) + vty_out (vty, " 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)) + 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) && + peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)) + vty_out (vty, " no neighbor %s send-community%s", addr, VTY_NEWLINE); } /* Default information */ - if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE) - && ! peer->af_group[afi][safi]) + if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE) || + (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); 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); } /* Soft reconfiguration inbound. */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) - if (! peer->af_group[afi][safi] || - ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) + if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr, VTY_NEWLINE); @@ -6667,13 +6594,11 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, } /* Route server client. */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) - && ! peer->af_group[afi][safi]) + if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_RSERVER_CLIENT)) vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE); /* Nexthop-local unchanged. */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) - && ! peer->af_group[afi][safi]) + if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE); /* Allow AS in. */ @@ -6693,22 +6618,21 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, bgp_config_write_filter (vty, peer, afi, safi); /* 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_MED_UNCHANGED)) - && ! peer->af_group[afi][safi]) { - 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_MED_UNCHANGED)) + if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) + && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) + && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED)) vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE); 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)) ? + peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ? " as-path" : "", - (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ? + peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) ? " next-hop" : "", - (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ? + peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED) ? " med" : "", VTY_NEWLINE); } } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 05dfecb4da..fc58f4fcc3 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -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_REPLACE (1 << 19) /* remove-private-as replace-as */ #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 */ char *password; @@ -1069,29 +1070,27 @@ enum bgp_clear_type #define BGP_ERR_MULTIPLE_INSTANCE_NOT_SET -14 #define BGP_ERR_AS_MISMATCH -15 #define BGP_ERR_PEER_INACTIVE -16 -#define BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER -17 -#define BGP_ERR_PEER_GROUP_HAS_THE_FLAG -18 -#define BGP_ERR_PEER_FLAG_CONFLICT -19 -#define BGP_ERR_PEER_GROUP_SHUTDOWN -20 -#define BGP_ERR_PEER_FILTER_CONFLICT -21 -#define BGP_ERR_NOT_INTERNAL_PEER -22 -#define BGP_ERR_REMOVE_PRIVATE_AS -23 -#define BGP_ERR_AF_UNCONFIGURED -24 -#define BGP_ERR_SOFT_RECONFIG_UNCONFIGURED -25 -#define BGP_ERR_INSTANCE_MISMATCH -26 -#define BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP -27 -#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS -28 -#define BGP_ERR_TCPSIG_FAILED -29 -#define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK -30 -#define BGP_ERR_NO_IBGP_WITH_TTLHACK -31 -#define BGP_ERR_NO_INTERFACE_CONFIG -32 -#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS -33 -#define BGP_ERR_AS_OVERRIDE -34 -#define BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT -35 -#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS -36 -#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND -37 -#define BGP_ERR_INVALID_FOR_DYNAMIC_PEER -38 -#define BGP_ERR_MAX -39 +#define BGP_ERR_PEER_FLAG_CONFLICT -17 +#define BGP_ERR_PEER_GROUP_SHUTDOWN -18 +#define BGP_ERR_PEER_FILTER_CONFLICT -19 +#define BGP_ERR_NOT_INTERNAL_PEER -20 +#define BGP_ERR_REMOVE_PRIVATE_AS -21 +#define BGP_ERR_AF_UNCONFIGURED -22 +#define BGP_ERR_SOFT_RECONFIG_UNCONFIGURED -23 +#define BGP_ERR_INSTANCE_MISMATCH -24 +#define BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP -25 +#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS -26 +#define BGP_ERR_TCPSIG_FAILED -27 +#define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK -28 +#define BGP_ERR_NO_IBGP_WITH_TTLHACK -29 +#define BGP_ERR_NO_INTERFACE_CONFIG -30 +#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS -31 +#define BGP_ERR_AS_OVERRIDE -32 +#define BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT -33 +#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS -34 +#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND -35 +#define BGP_ERR_INVALID_FOR_DYNAMIC_PEER -36 +#define BGP_ERR_MAX -37 /* * Enumeration of different policy kinds a peer can be configured with. From a6e0d253a2d0f38146c3551ea1fd93524a53de7e Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 28 Oct 2015 19:12:24 +0000 Subject: [PATCH 02/27] BGP: route-map scale - use a hash to store the route-maps - reduce the number of route_map_lookup_by_name() calls in BGP Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-7407 --- bgpd/bgp_routemap.c | 101 ++++++++++++++++++++++---------------------- lib/routemap.c | 89 +++++++++++++++++++++++++++++++------- 2 files changed, 124 insertions(+), 66 deletions(-) diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index bf3f8c35f0..a3eb24b3e3 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -2666,8 +2666,9 @@ bgp_route_set_delete (struct vty *vty, struct route_map_index *index, * modifications. */ static void -bgp_route_map_process_peer (const char *rmap_name, struct peer *peer, - int afi, int safi, int route_update) +bgp_route_map_process_peer (const char *rmap_name, struct route_map *map, + struct peer *peer, int afi, int safi, + int route_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 && (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) { - filter->map[RMAP_IN].map = - route_map_lookup_by_name (filter->map[RMAP_IN].name); + filter->map[RMAP_IN].map = map; 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 && (strcmp(rmap_name, filter->map[RMAP_IMPORT].name) == 0)) { - filter->map[RMAP_IMPORT].map = - route_map_lookup_by_name (filter->map[RMAP_IMPORT].name); + filter->map[RMAP_IMPORT].map = map; update = 1; } if (filter->map[RMAP_EXPORT].name && (strcmp(rmap_name, filter->map[RMAP_EXPORT].name) == 0)) { - filter->map[RMAP_EXPORT].map = - route_map_lookup_by_name (filter->map[RMAP_EXPORT].name); - + filter->map[RMAP_EXPORT].map = map; update = 1; } @@ -2769,21 +2766,20 @@ bgp_route_map_process_peer (const char *rmap_name, struct peer *peer, */ if (filter->map[RMAP_OUT].name && (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0)) - filter->map[RMAP_OUT].map = - route_map_lookup_by_name (filter->map[RMAP_OUT].name); + filter->map[RMAP_OUT].map = map; if (filter->usmap.name && (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 && (strcmp (rmap_name, peer->default_rmap[afi][safi].name) == 0)) - peer->default_rmap[afi][safi].map = - route_map_lookup_by_name (peer->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].map = map; } 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 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) && (strcmp(rmap_name, filter->map[direct].name) == 0)) - filter->map[direct].map = - route_map_lookup_by_name (filter->map[direct].name); + filter->map[direct].map = map; } if (filter->usmap.name && (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 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 *bgp = (struct bgp *)arg; struct listnode *node, *nnode; + struct route_map *map; char buf[INET6_ADDRSTRLEN]; if (!bgp) return (-1); + map = route_map_lookup_by_name (rmap_name); + 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; /* 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); /* 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 (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + /* For table route-map updates. */ if (bgp->table_map[afi][safi].name && (strcmp(rmap_name, bgp->table_map[afi][safi].name) == 0)) { - bgp->table_map[afi][safi].map = - route_map_lookup_by_name (bgp->table_map[afi][safi].name); + bgp->table_map[afi][safi].map = map; + if (BGP_DEBUG (zebra, ZEBRA)) zlog_debug("Processing route_map %s update on " "table map", rmap_name); if (route_update) bgp_zebra_announce_table(bgp, afi, safi); } - } - /* For network route-map updates. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - for (bn = bgp_table_top (bgp->route[afi][safi]); bn; - bn = bgp_route_next (bn)) - if ((bgp_static = bn->info) != NULL) - { - if (bgp_static->rmap.name && - (strcmp(rmap_name, bgp_static->rmap.name) == 0)) - { - bgp_static->rmap.map = - route_map_lookup_by_name (bgp_static->rmap.name); - if (route_update) - if (!bgp_static->backdoor) - { - if (bgp_debug_zebra(&bn->p)) - zlog_debug("Processing route_map %s update on " - "static route %s", rmap_name, - inet_ntop (bn->p.family, &bn->p.u.prefix, - buf, INET6_ADDRSTRLEN)); - bgp_static_update (bgp, &bn->p, bgp_static, afi, safi); - } - } - } + /* For network route-map updates. */ + for (bn = bgp_table_top (bgp->route[afi][safi]); bn; bn = bgp_route_next (bn)) + if ((bgp_static = bn->info) != NULL) + { + if (bgp_static->rmap.name && + (strcmp(rmap_name, bgp_static->rmap.name) == 0)) + { + bgp_static->rmap.map = map; + + if (route_update) + if (!bgp_static->backdoor) + { + if (bgp_debug_zebra(&bn->p)) + zlog_debug("Processing route_map %s update on " + "static route %s", rmap_name, + 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 (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 && (strcmp(rmap_name, red->rmap.name) == 0)) { - red->rmap.map = - route_map_lookup_by_name (red->rmap.name); + red->rmap.map = map; if (route_update) { diff --git a/lib/routemap.c b/lib/routemap.c index 8e5064b00b..e760dacf7d 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -66,6 +66,38 @@ struct route_map_list /* Master list of route map. */ 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 { @@ -127,7 +159,10 @@ route_map_add (const char *name) map = route_map_new (name); list = &route_map_master; - + + /* Add map to the hash */ + hash_get(route_map_master_hash, map, hash_alloc_intern); + map->next = NULL; map->prev = list->tail; if (list->tail) @@ -172,6 +207,7 @@ route_map_free_map (struct route_map *map) else list->head = map->next; + hash_release(route_map_master_hash, map); XFREE (MTYPE_ROUTE_MAP_NAME, map->name); XFREE (MTYPE_ROUTE_MAP, map); } @@ -211,14 +247,17 @@ struct route_map * route_map_lookup_by_name (const char *name) { struct route_map *map; + struct route_map tmp_map; if (!name) return NULL; - for (map = route_map_master.head; map; map = map->next) - if ((strcmp (map->name, name) == 0) && (!map->deleted)) - return map; - return NULL; + // map.deleted is 0 via memset + memset(&tmp_map, 0, sizeof(struct route_map)); + tmp_map.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); + map = hash_lookup(route_map_master_hash, &tmp_map); + XFREE(MTYPE_ROUTE_MAP_NAME, tmp_map.name); + return map; } int @@ -226,17 +265,30 @@ route_map_mark_updated (const char *name, int del_later) { struct route_map *map; int ret = -1; + struct route_map tmp_map; - /* We need to do this walk manually instead of calling lookup_by_name() - * because the lookup function doesn't return route maps marked as - * deleted. + if (!name) + return (ret); + + 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 (strcmp (map->name, name) == 0) - { - map->to_be_processed = 1; - ret = 0; - } + if (!map) + { + memset(&tmp_map, 0, sizeof(struct route_map)); + tmp_map.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); + 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); } @@ -386,8 +438,12 @@ vty_show_route_map (struct vty *vty, const char *name) } else { - vty_out (vty, "%%route-map %s not found%s", name, VTY_NEWLINE); - return CMD_WARNING; + if (zlog_default) + 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 @@ -1049,6 +1105,7 @@ route_map_init (void) /* Make vector for match and set. */ route_match_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 From 6896f650180700bafc543af21701be8b79eeee61 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 28 Oct 2015 19:59:30 -0400 Subject: [PATCH 03/27] lib: Memory reporting fails over 2GB Ticket: CM-8015 Reviewed by: CCR-3717 Testing: See bug The old style mallinfo() function uses an 'int' to report memory usage data to the program. Unfortunately modern architectures can chew through 2gb of memory like a buzz saw hitting some warm butter, especially in the case of a memory leak or memory fragmentation. When a daemon uses more than 2gb of memory, just indicate it's gotten large and we don't know anymore. Pre-change behavior: Robot-1# show memory System allocator statistics: Total heap allocated: 16777216 TiB Holding block headers: 1288 KiB Used small blocks: 0 bytes Used ordinary blocks: 535 MiB Free small blocks: 768 bytes Free ordinary blocks: 16777216 TiB Ordinary blocks: 266107 Small blocks: 24 Holding blocks: 2 Post-change behavior: Robot-1# show memory System allocator statistics: Total heap allocated: 1572 KiB Holding block headers: > 2GB Used small blocks: 0 bytes Used ordinary blocks: 1443 KiB Free small blocks: 32 bytes Free ordinary blocks: 129 KiB Ordinary blocks: 2 Small blocks: 1 Holding blocks: 2 Signed-off-by: Donald Sharp --- lib/memory.c | 43 +++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/lib/memory.c b/lib/memory.c index a9149e10ff..172ddfc49c 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -437,41 +437,28 @@ memory_init (void) const char * mtype_memstr (char *buf, size_t len, unsigned long bytes) { - unsigned int t, g, m, k; - + unsigned int m, k; + /* easy cases */ if (!bytes) return "0 bytes"; if (bytes == 1) return "1 byte"; - - if (sizeof (unsigned long) >= 8) - /* Hacked to make it not warn on ILP32 machines - * Shift will always be 40 at runtime. See below too */ - t = bytes >> (sizeof (unsigned long) >= 8 ? 40 : 0); - else - t = 0; - g = bytes >> 30; + + /* + * When we pass the 2gb barrier mallinfo() can no longer report + * correct data so it just does something odd... + * Reporting like Terrabytes of data. Which makes users... + * edgy.. yes edgy that's the term for it. + * So let's just give up gracefully + */ + if (bytes > 0x7fffffff) + return "> 2GB"; + m = bytes >> 20; k = bytes >> 10; - - if (t > 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 (m > 10) { if (bytes & (1 << 19)) m++; From b2b83ff67a91d24e7cd9871663f341b14c0834a2 Mon Sep 17 00:00:00 2001 From: vivek Date: Thu, 29 Oct 2015 09:34:47 -0700 Subject: [PATCH 04/27] BGP: Display the interface name used to resolve a nexthop. Display the interface name used to resolve a nexthop instead of just the ifIdx. This is already done for many cases, but was missing for one scenario. Signed-off-by: Vivek Venkataraman Reviewed-by: Donald Sharp Reviewed-by: Daniel Walton Ticket: CM-6888 Reviewed By: CCR-3705 Testing Done: Manual verification This is an import of patch bgpd-show-ifname-for-nht.patch from 2.5-br. --- bgpd/bgp_nexthop.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index ed7512cad2..4b3d14af58 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -477,7 +477,8 @@ show_ip_bgp_nexthop_table (struct vty *vty, int detail) VTY_NEWLINE); break; case NEXTHOP_TYPE_IFINDEX: - vty_out (vty, " ifidx %u%s", nexthop->ifindex, + vty_out (vty, " if %s%s", + ifindex2ifname(nexthop->ifindex), VTY_NEWLINE); break; default: From 20eb8864bbaf19771502b6c1ed3f1e43186f97eb Mon Sep 17 00:00:00 2001 From: vivek Date: Thu, 29 Oct 2015 09:41:23 -0700 Subject: [PATCH 05/27] BGP: Check for duplicate and overlapping listen ranges When configuring listen ranges for allowing dynamic BGP neighbors, ensure that there are no duplicate or overlapping ones. This is necessary because at the time of handling an incoming connection, the first range that matches the source of the connection (and hence, its peer-group parameters) will be used. Signed-off-by: Vivek Venkataraman Reviewed-by: Donald Sharp Reviewed-by: Atul Patel Ticket: CM-5153 Reviewed By: CCR-3714 Testing Done: Manual verification --- bgpd/bgp_vty.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 38f3eb971e..bbacc22492 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -57,6 +57,9 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 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. */ afi_t bgp_node_afi (struct vty *vty) @@ -2347,6 +2350,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, bgp_listen_range_cmd, LISTEN_RANGE_CMD "peer-group WORD" , @@ -2357,7 +2392,7 @@ DEFUN (bgp_listen_range, { struct bgp *bgp; struct prefix range; - struct peer_group *group; + struct peer_group *group, *existing_group; afi_t afi; int ret; @@ -2386,6 +2421,27 @@ DEFUN (bgp_listen_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]); if (! group) From b212c9dfd1abd25551fb90b01e34e42bd7c55076 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 29 Oct 2015 10:27:44 -0700 Subject: [PATCH 06/27] Quagga: Man pages have wrong paths Ticket: CM-8027 Testing: See bug The man pages have the wrong paths listed. Signed-off-by: Donald Sharp --- doc/bgpd.8 | 4 ++-- doc/isisd.8 | 4 ++-- doc/ospf6d.8 | 4 ++-- doc/ospfd.8 | 4 ++-- doc/ripd.8 | 4 ++-- doc/ripngd.8 | 4 ++-- doc/vtysh.1 | 4 ++-- doc/zebra.8 | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/doc/bgpd.8 b/doc/bgpd.8 index 8daaefa27b..67143c2c59 100644 --- a/doc/bgpd.8 +++ b/doc/bgpd.8 @@ -78,12 +78,12 @@ When the program terminates, retain routes added by \fBbgpd\fR. Print the version and exit. .SH FILES .TP -.BI /usr/local/sbin/bgpd +.BI /usr/lib/quagga/bgpd The default location of the .B bgpd binary. .TP -.BI /usr/local/etc/bgpd.conf +.BI /etc/quagga/bgpd.conf The default location of the .B bgpd config file. diff --git a/doc/isisd.8 b/doc/isisd.8 index 84e6cf5544..83ac99d57a 100644 --- a/doc/isisd.8 +++ b/doc/isisd.8 @@ -67,12 +67,12 @@ Specify the user to run as. Default is \fIquagga\fR. Print the version and exit. .SH FILES .TP -.BI /usr/local/sbin/isisd +.BI /usr/lib/quagga/isisd The default location of the .B isisd binary. .TP -.BI /usr/local/etc/isisd.conf +.BI /etc/quagga/isisd.conf The default location of the .B isisd config file. diff --git a/doc/ospf6d.8 b/doc/ospf6d.8 index 0643226345..630b20afdd 100644 --- a/doc/ospf6d.8 +++ b/doc/ospf6d.8 @@ -68,12 +68,12 @@ Specify the user to run as. Default is \fIquagga\fR. Print the version and exit. .SH FILES .TP -.BI /usr/local/sbin/ospf6d +.BI /usr/lib/quagga/ospf6d The default location of the .B ospf6d binary. .TP -.BI /usr/local/etc/ospf6d.conf +.BI /etc/quagga/ospf6d.conf The default location of the .B ospf6d config file. diff --git a/doc/ospfd.8 b/doc/ospfd.8 index 8c819cf658..ba8848affa 100644 --- a/doc/ospfd.8 +++ b/doc/ospfd.8 @@ -70,12 +70,12 @@ Enable OSPF apiserver. Default is disabled. Print the version and exit. .SH FILES .TP -.BI /usr/local/sbin/ospfd +.BI /usr/lib/quagga/ospfd The default location of the .B ospfd binary. .TP -.BI /usr/local/etc/ospfd.conf +.BI /etc/quagga/ospfd.conf The default location of the .B ospfd config file. diff --git a/doc/ripd.8 b/doc/ripd.8 index 8fa9bf23f4..f042af228b 100644 --- a/doc/ripd.8 +++ b/doc/ripd.8 @@ -71,12 +71,12 @@ When the program terminates, retain routes added by \fBripd\fR. Print the version and exit. .SH FILES .TP -.BI /usr/local/sbin/ripd +.BI /usr/lib/quagga/ripd The default location of the .B ripd binary. .TP -.BI /usr/local/etc/ripd.conf +.BI /etc/quagga/ripd.conf The default location of the .B ripd config file. diff --git a/doc/ripngd.8 b/doc/ripngd.8 index 6e63dc20eb..e4504fde46 100644 --- a/doc/ripngd.8 +++ b/doc/ripngd.8 @@ -71,12 +71,12 @@ When the program terminates, retain routes added by \fBripd\fR. Print the version and exit. .SH FILES .TP -.BI /usr/local/sbin/ripngd +.BI /usr/lib/quagga/ripngd The default location of the .B ripngd binary. .TP -.BI /usr/local/etc/ripngd.conf +.BI /etc/quagga/ripngd.conf The default location of the .B ripngd config file. diff --git a/doc/vtysh.1 b/doc/vtysh.1 index de4913e51f..ff4c2b4f84 100644 --- a/doc/vtysh.1 +++ b/doc/vtysh.1 @@ -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. .SH FILES .TP -.BI /usr/local/etc/vtysh.conf +.BI /etc/quagga/vtysh.conf The default location of the .B vtysh config file. .TP -.BI /usr/local/etc/Quagga.conf +.BI /etc/quagga/Quagga.conf The default location of the integrated Quagga routing engine config file if integrated config file is in use (not default). .SH WARNING diff --git a/doc/zebra.8 b/doc/zebra.8 index a40909a699..cb431da0aa 100644 --- a/doc/zebra.8 +++ b/doc/zebra.8 @@ -90,12 +90,12 @@ Note that this affects Linux only. Print the version and exit. .SH FILES .TP -.BI /usr/local/sbin/zebra +.BI /usr/lib/quagga/zebra The default location of the .B zebra binary. .TP -.BI /usr/local/etc/zebra.conf +.BI /etc/quagga/zebra.conf The default location of the .B zebra config file. From d289687f8b341363597c2f20276181341b4872c4 Mon Sep 17 00:00:00 2001 From: vivek Date: Thu, 29 Oct 2015 10:30:45 -0700 Subject: [PATCH 07/27] BGP: Do appropriate cleanup on receipt of redistribute update When there is a change to a redistributed route, either an attribute such as the metric or the route type itself has changed, protocol clients receive an update of the route instead of a delete and add as a result of an earlier optimization. The update needs to be handled as an implicit delete for any existing redistributed route, especially to handle change in route type. Signed-off-by: Vivek Venkataraman Reviewed-by: Donald Sharp Reviewed-by: Daniel Walton Ticket: CM-7578 Reviewed By: CCR-3718 Testing Done: Manual verification Related-to: CM-6768 --- bgpd/bgp_zebra.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index c7b0b4364e..052c2efacb 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -438,6 +438,7 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) struct in_addr nexthop; struct prefix_ipv4 p; unsigned int ifindex; + int i; s = zclient->ibuf; nexthop.s_addr = 0; @@ -497,6 +498,20 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) api.metric, 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, 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 prefix_ipv6 p; unsigned int ifindex; + int i; s = zclient->ibuf; 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.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, api.metric, api.type, api.instance, api.tag); } From 70737f3064ffee4ec4cf4b7d7813b9793ebbf973 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 21 Oct 2015 17:40:39 -0700 Subject: [PATCH 08/27] Debian: Track dependencies so that rebuilds can work right Not the debian way, I know. But cause the debian build to create and follow dependencies. Signed-off-by: Donald Sharp --- debian/rules | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index 6360a6c2ce..4642dbfeb3 100755 --- a/debian/rules +++ b/debian/rules @@ -65,7 +65,8 @@ override_dh_auto_configure: --enable-rtadv \ --enable-werror \ --enable-gcc-rdynamic \ - --with-libpam; \ + --with-libpam \ + --enable-dependency-tracking; \ fi if ! diff -b -IHAVE_SNMP -IHAVE_NETSNMP -IUCD_COMPAT -IGETIFADDR debian/my/config.h.reference config.h; then \ echo; \ From 400b1fad1d79b59c3f2866caaee42a80d4fa39e6 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Thu, 29 Oct 2015 20:33:30 +0000 Subject: [PATCH 09/27] Deactivate BGP peer via "no neighbor x.x.x.x activate" removes other config Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-6281 --- bgpd/bgp_vty.c | 3 - bgpd/bgpd.c | 362 +++++++++++++++++++++++++++++++------------------ bgpd/bgpd.h | 43 +++--- 3 files changed, 252 insertions(+), 156 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index bbacc22492..17b3b2fdbc 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -210,9 +210,6 @@ bgp_vty_return (struct vty *vty, int ret) case BGP_ERR_INVALID_FLAG: str = "Invalid flag"; break; - case BGP_ERR_PEER_INACTIVE: - str = "Activate the neighbor for the address family first"; - break; case BGP_ERR_PEER_GROUP_SHUTDOWN: str = "Peer-group has been shutdown. Activate the peer-group first"; break; diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index bb6e4bddc0..2d831acdd2 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1723,7 +1723,7 @@ peer_deactivate (struct peer *peer, afi_t afi, safi_t safi) /* De-activate the address family configuration. */ peer->afc[afi][safi] = 0; - peer_af_flag_reset (peer, afi, safi); + if (peer_af_delete(peer, afi, safi) != 0) { zlog_err("couldn't delete af structure for peer %s", peer->host); @@ -3689,16 +3689,12 @@ peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag, if (! found) return BGP_ERR_INVALID_FLAG; - /* Adress family must be activated. */ - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - - /* Spcecial check for reflector client. */ + /* Special check for reflector client. */ if (flag & PEER_FLAG_REFLECTOR_CLIENT && peer_sort (peer) != BGP_PEER_IBGP) 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 && peer_sort (peer) == BGP_PEER_IBGP) return BGP_ERR_REMOVE_PRIVATE_AS; @@ -4168,10 +4164,6 @@ peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi, struct peer_group *group; struct listnode *node, *nnode; - /* Adress family must be activated. */ - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE) || (rmap && ! peer->default_rmap[afi][safi].name) || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0)) @@ -4226,10 +4218,6 @@ peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi) struct peer_group *group; struct listnode *node, *nnode; - /* Adress family must be activated. */ - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) { UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE); @@ -4871,9 +4859,6 @@ peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct, struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (direct != FILTER_IN && direct != FILTER_OUT) return BGP_ERR_INVALID_VALUE; @@ -4921,9 +4906,6 @@ peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (direct != FILTER_IN && direct != FILTER_OUT) return BGP_ERR_INVALID_VALUE; @@ -5042,9 +5024,6 @@ peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct, struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (direct != FILTER_IN && direct != FILTER_OUT) return BGP_ERR_INVALID_VALUE; @@ -5091,9 +5070,6 @@ peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (direct != FILTER_IN && direct != FILTER_OUT) return BGP_ERR_INVALID_VALUE; @@ -5215,9 +5191,6 @@ peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct, struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (direct != FILTER_IN && direct != FILTER_OUT) return BGP_ERR_INVALID_VALUE; @@ -5261,9 +5234,6 @@ peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct) struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (direct != FILTER_IN && direct != FILTER_OUT) return BGP_ERR_INVALID_VALUE; @@ -5395,9 +5365,6 @@ peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct, struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (direct != RMAP_IN && direct != RMAP_OUT && direct != RMAP_IMPORT && direct != RMAP_EXPORT) return BGP_ERR_INVALID_VALUE; @@ -5444,9 +5411,6 @@ peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - if (direct != RMAP_IN && direct != RMAP_OUT && direct != RMAP_IMPORT && direct != RMAP_EXPORT) return BGP_ERR_INVALID_VALUE; @@ -5509,9 +5473,6 @@ peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi, struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - filter = &peer->filter[afi][safi]; if (filter->usmap.name) @@ -5551,9 +5512,6 @@ peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi) struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - filter = &peer->filter[afi][safi]; if (filter->usmap.name) @@ -5592,9 +5550,6 @@ peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi, struct peer_group *group; 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); peer->pmax[afi][safi] = max; peer->pmax_threshold[afi][safi] = threshold; @@ -5640,9 +5595,6 @@ peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi) struct peer_group *group; struct listnode *node, *nnode; - if (! peer->afc[afi][safi]) - return BGP_ERR_PEER_INACTIVE; - /* apply peer-group config */ if (peer->af_group[afi][safi]) { @@ -6077,9 +6029,35 @@ peer_uptime (time_t uptime2, char *buf, size_t len, u_char use_json, json_object 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 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 *gfilter = NULL; @@ -6096,55 +6074,93 @@ bgp_config_write_filter (struct vty *vty, struct peer *peer, if (filter->dlist[in].name) if (! gfilter || ! gfilter->dlist[in].name || 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) - 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. */ if (filter->plist[in].name) if (! gfilter || ! gfilter->plist[in].name || 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) - 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. */ if (filter->map[RMAP_IN].name) if (! gfilter || ! gfilter->map[RMAP_IN].name || 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) - 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) - 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 (! gfilter || ! gfilter->map[RMAP_EXPORT].name - || strcmp (filter->map[RMAP_EXPORT].name, - gfilter->map[RMAP_EXPORT].name) != 0) - vty_out (vty, " neighbor %s route-map %s export%s", addr, - filter->map[RMAP_EXPORT].name, VTY_NEWLINE); + || strcmp (filter->map[RMAP_EXPORT].name, gfilter->map[RMAP_EXPORT].name) != 0) + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s route-map %s export%s", + addr, filter->map[RMAP_EXPORT].name, VTY_NEWLINE); + } /* unsuppress-map */ 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. */ if (filter->aslist[in].name) if (! gfilter || ! gfilter->aslist[in].name || 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) - 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. */ @@ -6382,6 +6398,7 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, } if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) && + peer->connect != BGP_DEFAULT_CONNECT_RETRY && ! peer_group_active (peer)) { vty_out (vty, " neighbor %s timers connect %d%s", addr, @@ -6454,11 +6471,11 @@ bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, } } - /* BGP peer configuration display function. */ static void 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; char *addr; @@ -6479,16 +6496,26 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, ****** Per AF to the neighbor ****** ************************************/ 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 - 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. */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) || peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM)) { - 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 (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM)) @@ -6502,44 +6529,87 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, /* Route reflector client. */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)) - vty_out (vty, " neighbor %s route-reflector-client%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s route-reflector-client%s", + addr, VTY_NEWLINE); + } /* next-hop-self force */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_FORCE_NEXTHOP_SELF)) - vty_out (vty, " neighbor %s next-hop-self force%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s next-hop-self force%s", + addr, VTY_NEWLINE); + } /* next-hop-self */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) - vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s next-hop-self%s", + addr, VTY_NEWLINE); + } /* remove-private-AS */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) - vty_out (vty, " neighbor %s remove-private-AS all replace-AS%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s remove-private-AS all replace-AS%s", + addr, VTY_NEWLINE); + } 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 (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 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 */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) - 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. */ 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)) - vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s send-community both%s", + addr, VTY_NEWLINE); + } else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) - vty_out (vty, " neighbor %s send-community extended%s", - addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s send-community extended%s", + addr, VTY_NEWLINE); + } else if (peergroup_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%s", + addr, VTY_NEWLINE); + } } else { @@ -6547,13 +6617,25 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, 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)) - vty_out (vty, " no neighbor %s send-community both%s", addr, VTY_NEWLINE); + { + 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)) - vty_out (vty, " no neighbor %s send-community extended%s", addr, VTY_NEWLINE); + { + 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)) - vty_out (vty, " no neighbor %s send-community%s", addr, VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " no neighbor %s send-community%s", + addr, VTY_NEWLINE); + } } /* Default information */ @@ -6564,7 +6646,8 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, (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) vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name); vty_out (vty, "%s", VTY_NEWLINE); @@ -6572,8 +6655,11 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, /* Soft reconfiguration inbound. */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) - vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr, - VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s soft-reconfiguration inbound%s", + addr, VTY_NEWLINE); + } /* maximum-prefix. */ if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) @@ -6583,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 (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) vty_out (vty, " %d", peer->pmax_threshold[afi][safi]); if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) @@ -6595,11 +6683,19 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, /* Route server client. */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_RSERVER_CLIENT)) - 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. */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) - 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. */ if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN)) @@ -6608,14 +6704,21 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi]) { if (peer->allowas_in[afi][safi] == 3) - vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE); - else - vty_out (vty, " neighbor %s allowas-in %d%s", addr, - peer->allowas_in[afi][safi], VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s allowas-in%s", + 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. */ - bgp_config_write_filter (vty, peer, afi, safi); + bgp_config_write_filter (vty, peer, afi, safi, write); /* atribute-unchanged. */ if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED) @@ -6625,15 +6728,22 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_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 - vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr, - peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ? - " as-path" : "", - peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) ? - " next-hop" : "", - peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED) ? - " med" : "", VTY_NEWLINE); + { + afi_header_vty_out (vty, afi, safi, write, + " neighbor %s attribute-unchanged%s%s%s%s", addr, + peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ? + " as-path" : "", + peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) ? + " next-hop" : "", + peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED) ? + " med" : "", VTY_NEWLINE); + } } } @@ -6684,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); for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - { - 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); - } - } + bgp_config_write_peer_af (vty, bgp, group->conf, afi, safi, &write); + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) { /* Skip dynamic neighbors. */ if (peer_dynamic_neighbor (peer)) continue; - if (peer->afc[afi][safi]) - { - if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)) - { - bgp_config_write_family_header (vty, afi, safi, &write); - bgp_config_write_peer_af (vty, bgp, peer, afi, safi); - } - } + /* Do not display doppelganger peers */ + if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)) + bgp_config_write_peer_af (vty, bgp, peer, afi, safi, &write); } bgp_config_write_maxpaths (vty, bgp, afi, safi, &write); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index fc58f4fcc3..41bc5ea81c 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1069,28 +1069,27 @@ enum bgp_clear_type #define BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT -13 #define BGP_ERR_MULTIPLE_INSTANCE_NOT_SET -14 #define BGP_ERR_AS_MISMATCH -15 -#define BGP_ERR_PEER_INACTIVE -16 -#define BGP_ERR_PEER_FLAG_CONFLICT -17 -#define BGP_ERR_PEER_GROUP_SHUTDOWN -18 -#define BGP_ERR_PEER_FILTER_CONFLICT -19 -#define BGP_ERR_NOT_INTERNAL_PEER -20 -#define BGP_ERR_REMOVE_PRIVATE_AS -21 -#define BGP_ERR_AF_UNCONFIGURED -22 -#define BGP_ERR_SOFT_RECONFIG_UNCONFIGURED -23 -#define BGP_ERR_INSTANCE_MISMATCH -24 -#define BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP -25 -#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS -26 -#define BGP_ERR_TCPSIG_FAILED -27 -#define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK -28 -#define BGP_ERR_NO_IBGP_WITH_TTLHACK -29 -#define BGP_ERR_NO_INTERFACE_CONFIG -30 -#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS -31 -#define BGP_ERR_AS_OVERRIDE -32 -#define BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT -33 -#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS -34 -#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND -35 -#define BGP_ERR_INVALID_FOR_DYNAMIC_PEER -36 -#define BGP_ERR_MAX -37 +#define BGP_ERR_PEER_FLAG_CONFLICT -16 +#define BGP_ERR_PEER_GROUP_SHUTDOWN -17 +#define BGP_ERR_PEER_FILTER_CONFLICT -18 +#define BGP_ERR_NOT_INTERNAL_PEER -19 +#define BGP_ERR_REMOVE_PRIVATE_AS -20 +#define BGP_ERR_AF_UNCONFIGURED -21 +#define BGP_ERR_SOFT_RECONFIG_UNCONFIGURED -22 +#define BGP_ERR_INSTANCE_MISMATCH -23 +#define BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP -24 +#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS -25 +#define BGP_ERR_TCPSIG_FAILED -26 +#define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK -27 +#define BGP_ERR_NO_IBGP_WITH_TTLHACK -28 +#define BGP_ERR_NO_INTERFACE_CONFIG -29 +#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS -30 +#define BGP_ERR_AS_OVERRIDE -31 +#define BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT -32 +#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS -33 +#define BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND -34 +#define BGP_ERR_INVALID_FOR_DYNAMIC_PEER -35 +#define BGP_ERR_MAX -36 /* * Enumeration of different policy kinds a peer can be configured with. From b72ede27fd39c2e97dbf31715464573c30de557f Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:39:56 +0200 Subject: [PATCH 10/27] lib, zebra: move "struct vrf" to be a lib module Previously "struct vrf" is defined locally in zebra. Now it is moved to be a lib module. This is the first step to support multi-VRF in quagga. The implementation is splitted into small patches for the purpose of easy review. * lib: "struct vrf" with basic members is defined in vrf.c. The member "void *info" is for user data. Some basic functions are defined in vrf.c for adding/deleting/ looking up a VRF, scanning the VRF table and initializing the VRF module. The type "vrf_id_t" is defined specificly for VRF ID. * zebra: The previous "struct vrf" is re-defined as "struct zebra_vrf"; and previous "vrf" variables are renamed to "zvrf". The previous "struct vrf" related functions are removed from zbera_rib.c. New functions are defined to maintain the new "struct zebra_vrf". The names vrf_xxx are reserved for the functions in VRF module. So: - the previous vrf_table() are renamed to zebra_vrf_table(); - the previous vrf_static_table() are renamed to zebra_vrf_static_table(). The main logic is not changed. BTW: Add a statement to zebra_snmp.c telling that the SNMP is running only for the MIBs in the default VRF. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter Conflicts: lib/Makefile.am zebra/zebra_rib.c zebra/zebra_vty.c Conflicts: lib/Makefile.am lib/memtypes.c zebra/rib.h zebra/zebra_rib.c zebra/zebra_rnh.c zebra/zebra_rnh.h zebra/zebra_vty.c --- lib/Makefile.am | 4 +- lib/memtypes.c | 5 +- lib/vrf.c | 268 ++++++++++++++++++++++++++++ lib/vrf.h | 96 ++++++++++ lib/zebra.h | 3 + zebra/main.c | 27 ++- zebra/redistribute.c | 11 +- zebra/rib.h | 27 +-- zebra/test_main.c | 25 +++ zebra/zebra_fpm.c | 2 +- zebra/zebra_fpm_netlink.c | 2 +- zebra/zebra_rib.c | 365 ++++++++++++++++++++------------------ zebra/zebra_rnh.c | 37 ++-- zebra/zebra_rnh.h | 12 +- zebra/zebra_snmp.c | 11 +- zebra/zebra_vty.c | 45 ++--- 16 files changed, 694 insertions(+), 246 deletions(-) create mode 100644 lib/vrf.c create mode 100644 lib/vrf.h diff --git a/lib/Makefile.am b/lib/Makefile.am index 19ae8f96df..49a721f7f9 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -14,7 +14,7 @@ libzebra_la_SOURCES = \ 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 \ 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 @@ -30,7 +30,7 @@ pkginclude_HEADERS = \ 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 \ 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 = \ regex.c regex-gnu.h \ diff --git a/lib/memtypes.c b/lib/memtypes.c index 5b0c12040a..dafd471dd2 100644 --- a/lib/memtypes.c +++ b/lib/memtypes.c @@ -73,14 +73,15 @@ struct memory_list memory_list_lib[] = { MTYPE_PQUEUE_DATA, "Priority queue data" }, { MTYPE_HOST, "Host config" }, { MTYPE_BFD_INFO, "BFD info" }, + { MTYPE_VRF, "VRF" }, + { MTYPE_VRF_NAME, "VRF name" }, { -1, NULL }, }; struct memory_list memory_list_zebra[] = { { MTYPE_RTADV_PREFIX, "Router Advertisement Prefix" }, - { MTYPE_VRF, "VRF" }, - { MTYPE_VRF_NAME, "VRF name" }, + { MTYPE_ZEBRA_VRF, "ZEBRA VRF" }, { MTYPE_NEXTHOP, "Nexthop" }, { MTYPE_RIB, "RIB" }, { MTYPE_RIB_QUEUE, "RIB process work queue" }, diff --git a/lib/vrf.c b/lib/vrf.c new file mode 100644 index 0000000000..3ccbb99617 --- /dev/null +++ b/lib/vrf.c @@ -0,0 +1,268 @@ +/* + * 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 + +#include "vrf.h" +#include "prefix.h" +#include "table.h" +#include "log.h" +#include "memory.h" + +struct vrf +{ + /* Identifier, same as the vector index */ + vrf_id_t vrf_id; + /* Name */ + char *name; + + /* 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 **); +} vrf_master = {0,}; + +/* VRF table */ +struct route_table *vrf_table = NULL; + +/* 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; + + 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_master.vrf_delete_hook) + (*vrf_master.vrf_delete_hook) (vrf->vrf_id, &vrf->info); + + 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; +} + +/* 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; + 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; +} + +/* 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; +} + +/* 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, "Default-IP-Routing-Table"); +} + +/* 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; +} + diff --git a/lib/vrf.h b/lib/vrf.h new file mode 100644 index 0000000000..7e05099433 --- /dev/null +++ b/lib/vrf.h @@ -0,0 +1,96 @@ +/* + * 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 + +/* The default VRF ID */ +#define VRF_DEFAULT 0 + +/* + * VRF hooks + */ + +#define VRF_NEW_HOOK 0 /* a new VRF is just created */ +#define VRF_DELETE_HOOK 1 /* a VRF is to be deleted */ + +/* + * 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 (); + * 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); + +/* + * 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); + +/* + * VRF initializer/destructor + */ +/* Please add hooks before calling vrf_init(). */ +extern void vrf_init (void); +extern void vrf_terminate (void); + +#endif /*_ZEBRA_VRF_H*/ + diff --git a/lib/zebra.h b/lib/zebra.h index 0a1dd7f46c..a3ac78cbce 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -556,6 +556,9 @@ typedef u_int8_t safi_t; typedef u_int16_t zebra_size_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. */ struct fifo { diff --git a/zebra/main.c b/zebra/main.c index 45fe38052b..92a0c0b31b 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -32,6 +32,7 @@ #include "plist.h" #include "privs.h" #include "sigevent.h" +#include "vrf.h" #include "zebra/rib.h" #include "zebra/zserv.h" @@ -213,6 +214,29 @@ 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; +} + +/* Zebra VRF initialization. */ +static void +zebra_vrf_init (void) +{ + vrf_add_hook (VRF_NEW_HOOK, zebra_vrf_new); + vrf_init (); +} + /* Main startup routine. */ int main (int argc, char **argv) @@ -354,7 +378,8 @@ main (int argc, char **argv) /* For debug purpose. */ /* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */ - /* Make kernel routing socket. */ + /* Initialize VRF module, and make kernel routing socket. */ + zebra_vrf_init (); kernel_init (); interface_list (); route_read (); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 5a2a0668b7..4b4db1dcee 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -30,6 +30,7 @@ #include "zclient.h" #include "linklist.h" #include "log.h" +#include "vrf.h" #include "zebra/rib.h" #include "zebra/zserv.h" @@ -96,7 +97,7 @@ zebra_redistribute_default (struct zserv *client) p.family = AF_INET; /* Lookup table. */ - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (table) { rn = route_node_lookup (table, (struct prefix *)&p); @@ -116,7 +117,7 @@ zebra_redistribute_default (struct zserv *client) p6.family = AF_INET6; /* Lookup table. */ - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (table) { 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_node *rn; - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB (rn, newrib) @@ -155,7 +156,7 @@ zebra_redistribute (struct zserv *client, int type, u_short instance) } #ifdef HAVE_IPV6 - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB (rn, newrib) @@ -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) 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) { return 0; diff --git a/zebra/rib.h b/zebra/rib.h index fa37f7d8c3..8c82a7eec3 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -278,10 +278,10 @@ struct static_ipv6 : (((recursing) = 0),((tnexthop) = (tnexthop)->next))) /* Routing table instance. */ -struct vrf +struct zebra_vrf { - /* Identifier. This is same as routing table vector index. */ - u_int32_t id; + /* Identifier. */ + vrf_id_t vrf_id; /* Routing table name. */ char *name; @@ -318,9 +318,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; safi_t safi; @@ -339,7 +339,7 @@ typedef enum */ typedef struct rib_tables_iter_t_ { - uint32_t vrf_id; + vrf_id_t vrf_id; int afi_safi_ix; rib_tables_iter_state_t state; @@ -386,11 +386,12 @@ rib_bogus_ipv6 (int type, struct prefix_ipv6 *p, struct in6_addr *gate, unsigned int ifindex, int table); #endif /* HAVE_IPV6 */ -extern struct vrf *vrf_lookup (u_int32_t); -extern struct route_table *vrf_table (afi_t afi, safi_t safi, u_int32_t id); -extern struct route_table *vrf_static_table (afi_t afi, safi_t safi, u_int32_t id); -extern struct route_table *vrf_other_route_table (afi_t afi, u_int32_t table_id, - u_int32_t vrf_id); +extern struct zebra_vrf *zebra_vrf_lookup (vrf_id_t vrf_id); +extern struct zebra_vrf *zebra_vrf_alloc (vrf_id_t); +extern struct route_table *zebra_vrf_table (afi_t, safi_t, vrf_id_t); +extern struct route_table *zebra_vrf_static_table (afi_t, safi_t, vrf_id_t); +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_main_routing_table(u_int32_t table_id); extern int zebra_check_addr (struct prefix *p); @@ -539,10 +540,10 @@ rib_dest_table (rib_dest_t *dest) /* * rib_dest_vrf */ -static inline struct vrf * +static inline struct zebra_vrf * 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; } /* diff --git a/zebra/test_main.c b/zebra/test_main.c index d0a210bcbe..f4a8ca2bad 100644 --- a/zebra/test_main.c +++ b/zebra/test_main.c @@ -29,6 +29,7 @@ #include "log.h" #include "privs.h" #include "sigevent.h" +#include "vrf.h" #include "zebra/rib.h" #include "zebra/zserv.h" @@ -201,6 +202,29 @@ 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; +} + +/* Zebra VRF initialization. */ +static void +zebra_vrf_init (void) +{ + vrf_add_hook (VRF_NEW_HOOK, zebra_vrf_new); + vrf_init (); +} + /* Main startup routine. */ int main (int argc, char **argv) @@ -302,6 +326,7 @@ main (int argc, char **argv) access_list_init (); /* Make kernel routing socket. */ + zebra_vrf_init (); kernel_init (); route_read (); zebra_vty_init(); diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index e02d174559..54a13654c6 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -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 * at this point. */ - if (info->vrf->id != 0) + if (info->zvrf->vrf_id != 0) return 0; if (info->safi != SAFI_UNICAST) diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index 1de75be4b0..1eec867041 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -246,7 +246,7 @@ netlink_route_info_fill (netlink_route_info_t *ri, int cmd, ri->af = rib_dest_af (dest); 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; /* diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index a69dead1a6..b15cbd3cdb 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -35,6 +35,7 @@ #include "prefix.h" #include "routemap.h" #include "nexthop.h" +#include "vrf.h" #include "zebra/rib.h" #include "zebra/rt.h" @@ -79,136 +80,31 @@ static const struct }; /* Vector for routing table. */ -static vector vrf_vector; +static vector zebra_vrf_vector; /* - * vrf_table_create + * nexthop_type_to_str */ -static void -vrf_table_create (struct vrf *vrf, afi_t afi, safi_t safi) +const char * +nexthop_type_to_str (enum nexthop_types_t nh_type) { - rib_table_info_t *info; - struct route_table *table; + static const char *desc[] = { + "none", + "Directly connected", + "Interface route", + "IPv4 nexthop", + "IPv4 nexthop with ifindex", + "IPv4 nexthop with ifname", + "IPv6 nexthop", + "IPv6 nexthop with ifindex", + "IPv6 nexthop with ifname", + "Null0 nexthop", + }; - assert (!vrf->table[afi][safi]); + if (nh_type >= ZEBRA_NUM_OF (desc)) + return ""; - table = route_table_init (); - vrf->table[afi][safi] = table; - - info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info)); - info->vrf = vrf; - info->afi = afi; - info->safi = safi; - table->info = info; -} - -/* Allocate new VRF. */ -static struct vrf * -vrf_alloc (const char *name) -{ - struct vrf *vrf; - - vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf)); - - /* Put name. */ - if (name) - vrf->name = XSTRDUP (MTYPE_VRF_NAME, name); - - /* Allocate routing table and static table. */ - vrf_table_create (vrf, AFI_IP, SAFI_UNICAST); - vrf_table_create (vrf, AFI_IP6, SAFI_UNICAST); - vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init (); - vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init (); - vrf_table_create (vrf, AFI_IP, SAFI_MULTICAST); - vrf_table_create (vrf, AFI_IP6, SAFI_MULTICAST); - vrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init (); - vrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init (); - - vrf->rnh_table[AFI_IP] = route_table_init(); - vrf->rnh_table[AFI_IP6] = route_table_init(); - - vrf->import_check_table[AFI_IP] = route_table_init(); - vrf->import_check_table[AFI_IP6] = route_table_init(); - - return vrf; -} - -/* Lookup VRF by identifier. */ -struct vrf * -vrf_lookup (u_int32_t id) -{ - return vector_lookup (vrf_vector, id); -} - -/* Initialize VRF. */ -static void -vrf_init (void) -{ - 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]); + return desc[nh_type]; } int @@ -587,7 +483,7 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, p.prefix = nexthop->gate.ipv4; /* Lookup table. */ - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return 0; @@ -796,7 +692,7 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, p.prefix = nexthop->gate.ipv6; /* Lookup table. */ - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! table) return 0; @@ -960,7 +856,7 @@ rib_match_ipv4 (struct in_addr addr) int recursing; /* Lookup table. */ - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return 0; @@ -1021,7 +917,7 @@ rib_lookup_ipv4 (struct prefix_ipv4 *p) int recursing; /* Lookup table. */ - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return 0; @@ -1078,7 +974,7 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate) int nexthops_active; /* Lookup table. */ - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return ZEBRA_RIB_LOOKUP_ERROR; @@ -1144,7 +1040,7 @@ rib_match_ipv6 (struct in6_addr *addr) int recursing; /* Lookup table. */ - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! table) return 0; @@ -2266,11 +2162,11 @@ rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = vrf_table (AFI_IP, safi, 0); + table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT); } else { - table = vrf_other_route_table (AFI_IP, table_id, 0); + table = zebra_vrf_other_route_table (AFI_IP, table_id, VRF_DEFAULT); } if (! table) return 0; @@ -2442,10 +2338,10 @@ void rib_lookup_and_dump (struct prefix_ipv4 * p) char prefix_buf[INET_ADDRSTRLEN]; /* Lookup table. */ - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) { - zlog_err ("%s: vrf_table() returned NULL", __func__); + zlog_err ("%s: zebra_vrf_table() returned NULL", __func__); return; } @@ -2491,9 +2387,9 @@ void rib_lookup_and_pushup (struct prefix_ipv4 * p) struct rib *rib; unsigned changed = 0; - if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0))) + if (NULL == (table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT))) { - zlog_err ("%s: vrf_table() returned NULL", __func__); + zlog_err ("%s: zebra_vrf_table() returned NULL", __func__); return; } @@ -2543,11 +2439,11 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) /* Lookup table. */ if ((rib->table == zebrad.rtm_table_default) || (rib->table == RT_TABLE_MAIN)) { - table = vrf_table (AFI_IP, safi, 0); + table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT); } else { - table = vrf_other_route_table (AFI_IP, rib->table, 0); + table = zebra_vrf_other_route_table (AFI_IP, rib->table, VRF_DEFAULT); } if (! table) return 0; @@ -2633,11 +2529,11 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = vrf_table (AFI_IP, safi, 0); + table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT); } else { - table = vrf_other_route_table(AFI_IP, table_id, 0); + table = zebra_vrf_other_route_table(AFI_IP, table_id, VRF_DEFAULT); } if (! table) return 0; @@ -2795,7 +2691,7 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si) struct prefix nh_p; /* Lookup table. */ - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return; @@ -2903,7 +2799,7 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si) struct prefix nh_p; /* Lookup table. */ - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return; @@ -2991,7 +2887,7 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, struct route_table *stable; /* Lookup table. */ - stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id); + stable = zebra_vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! stable) return -1; @@ -3084,7 +2980,7 @@ static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, struct route_table *stable; /* Lookup table. */ - stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id); + stable = zebra_vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! stable) return -1; @@ -3175,11 +3071,11 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = vrf_table (AFI_IP6, safi, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); } else { - table = vrf_other_route_table(AFI_IP6, table_id, 0); + table = zebra_vrf_other_route_table(AFI_IP6, table_id, VRF_DEFAULT); } if (! table) return 0; @@ -3295,7 +3191,7 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi, if (!rib) return 0; - table = vrf_table (AFI_IP, safi, 0); + table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT); if (!table) return 0; /* Make it sure prefixlen is applied to the prefix. */ @@ -3311,11 +3207,11 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = vrf_table (AFI_IP6, safi, 0); + table = zebra_vrf_table (AFI_IP6, safi, VRF_DEFAULT); } else { - table = vrf_other_route_table(AFI_IP6, table_id, 0); + table = zebra_vrf_other_route_table(AFI_IP6, table_id, VRF_DEFAULT); } if (! table) @@ -3416,11 +3312,11 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = vrf_table (AFI_IP6, safi, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); } else { - table = vrf_other_route_table(AFI_IP6, table_id, 0); + table = zebra_vrf_other_route_table(AFI_IP6, table_id, VRF_DEFAULT); } if (! table) return 0; @@ -3561,7 +3457,7 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si) struct prefix nh_p; /* Lookup table. */ - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! table) return; @@ -3671,7 +3567,7 @@ static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si) struct prefix nh_p; /* Lookup table. */ - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! table) return; @@ -3757,7 +3653,7 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, struct route_table *stable; /* Lookup table. */ - stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id); + stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! stable) return -1; @@ -3845,7 +3741,7 @@ static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, struct route_table *stable; /* Lookup table. */ - stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id); + stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! stable) return -1; @@ -3898,7 +3794,7 @@ rib_update_static (void) struct route_table *table; struct rib *rib, *next; - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB_SAFE (rn, rib, next) @@ -3908,7 +3804,7 @@ rib_update_static (void) break; } - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB_SAFE (rn, rib, next) @@ -3926,13 +3822,13 @@ rib_update (void) struct route_node *rn; struct route_table *table; - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) if (rnode_to_ribs (rn)) rib_queue_add (&zebrad, rn); - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) if (rnode_to_ribs (rn)) @@ -3965,8 +3861,8 @@ rib_weed_table (struct route_table *table) void rib_weed_tables (void) { - rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0)); - rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0)); + rib_weed_table (zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)); + rib_weed_table (zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT)); } /* Delete self installed routes after zebra is relaunched. */ @@ -3999,8 +3895,8 @@ rib_sweep_table (struct route_table *table) void rib_sweep_route (void) { - rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0)); - rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0)); + rib_sweep_table (zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)); + rib_sweep_table (zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT)); } /* Remove specific by protocol routes from 'table'. */ @@ -4032,8 +3928,8 @@ rib_score_proto_table (u_char proto, u_short instance, struct route_table *table unsigned long rib_score_proto (u_char proto, u_short instance) { - return rib_score_proto_table (proto, instance, vrf_table (AFI_IP, SAFI_UNICAST, 0)) - +rib_score_proto_table (proto, instance, vrf_table (AFI_IP6, SAFI_UNICAST, 0)); + return rib_score_proto_table (proto, instance, zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)) + +rib_score_proto_table (proto, instance, zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT)); } /* Close RIB and clean up kernel routes. */ @@ -4064,8 +3960,8 @@ rib_close (void) struct listnode *node, *nnode; struct interface *ifp; - rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0)); - rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0)); + rib_close_table (zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)); + rib_close_table (zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT)); for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp)) if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp); @@ -4076,8 +3972,6 @@ void rib_init (void) { rib_queue_init (&zebrad); - /* VRF initialization. */ - vrf_init (); } /* @@ -4088,15 +3982,19 @@ rib_init (void) * Returns TRUE if a vrf id was found, FALSE otherwise. */ static inline int -vrf_id_get_next (uint32_t id, uint32_t *next_id_p) +vrf_id_get_next (vrf_id_t vrf_id, vrf_id_t *next_id_p) { - while (++id < vector_active (vrf_vector)) + vrf_iter_t iter = vrf_iterator (vrf_id); + struct zebra_vrf *zvrf = vrf_iter2info (iter); + + /* The same one ? Then find out the next. */ + if (zvrf && (zvrf->vrf_id == vrf_id)) + zvrf = vrf_iter2info (vrf_next (iter)); + + if (zvrf) { - if (vrf_lookup (id)) - { - *next_id_p = id; - return 1; - } + *next_id_p = zvrf->vrf_id; + return 1; } return 0; @@ -4144,7 +4042,7 @@ rib_tables_iter_next (rib_tables_iter_t *iter) while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis)) { - table = vrf_table (afi_safis[iter->afi_safi_ix].afi, + table = zebra_vrf_table (afi_safis[iter->afi_safi_ix].afi, afi_safis[iter->afi_safi_ix].safi, iter->vrf_id); if (table) @@ -4182,3 +4080,116 @@ rib_tables_iter_next (rib_tables_iter_t *iter) return table; } + +/* + * Create a routing table for the specific AFI/SAFI in the given VRF. + */ +static void +zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi) +{ + rib_table_info_t *info; + struct route_table *table; + + assert (!zvrf->table[afi][safi]); + + table = route_table_init (); + zvrf->table[afi][safi] = table; + + info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info)); + info->zvrf = zvrf; + info->afi = afi; + info->safi = safi; + table->info = info; +} + +/* Allocate new zebra VRF. */ +struct zebra_vrf * +zebra_vrf_alloc (vrf_id_t vrf_id) +{ + struct zebra_vrf *zvrf; + + zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf)); + + /* Allocate routing table and static table. */ + zebra_vrf_table_create (zvrf, AFI_IP, SAFI_UNICAST); + zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_UNICAST); + zvrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init (); + zvrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init (); + zebra_vrf_table_create (zvrf, AFI_IP, SAFI_MULTICAST); + zebra_vrf_table_create (zvrf, AFI_IP6, SAFI_MULTICAST); + zvrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init (); + zvrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init (); + + zvrf->rnh_table[AFI_IP] = route_table_init(); + zvrf->rnh_table[AFI_IP6] = route_table_init(); + + zvrf->import_check_table[AFI_IP] = route_table_init(); + zvrf->import_check_table[AFI_IP6] = route_table_init(); + + /* Set VRF ID */ + zvrf->vrf_id = vrf_id; + + return zvrf; +} + +/* Lookup VRF by identifier. */ +struct zebra_vrf * +zebra_vrf_lookup (vrf_id_t vrf_id) +{ + return vector_lookup (zebra_vrf_vector, vrf_id); +} + +/* Lookup the routing table in an enabled VRF. */ +struct route_table * +zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id) +{ + struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id); + + if (!zvrf) + return NULL; + + if (afi >= AFI_MAX || safi >= SAFI_MAX) + return NULL; + + return zvrf->table[afi][safi]; +} + +/* Lookup the static routing table in a VRF. */ +struct route_table * +zebra_vrf_static_table (afi_t afi, safi_t safi, vrf_id_t vrf_id) +{ + struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id); + + if (!zvrf) + return NULL; + + if (afi >= AFI_MAX || safi >= SAFI_MAX) + return NULL; + + return zvrf->stable[afi][safi]; +} + +struct route_table * +zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, vrf_id_t vrf_id) +{ + struct zebra_vrf *zvrf; + + zvrf = vrf_info_lookup (vrf_id); + if (! zvrf) + return NULL; + + if(afi >= AFI_MAX) + return NULL; + + if (table_id >= ZEBRA_KERNEL_TABLE_MAX) + return NULL; + + if (zvrf->other_table[afi][table_id] == NULL) + { + zvrf->other_table[afi][table_id] = route_table_init(); + } + + return (zvrf->other_table[afi][table_id]); +} + + diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index eea7759589..09d2947c4e 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -36,6 +36,7 @@ #include "routemap.h" #include "stream.h" #include "nexthop.h" +#include "vrf.h" #include "zebra/rib.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 copy_state(struct rnh *rnh, struct rib *rib, 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 send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type); 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_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) { - struct vrf *vrf; + struct zebra_vrf *zvrf; struct route_table *t = NULL; - vrf = vrf_lookup(vrfid); - if (vrf) + zvrf = zebra_vrf_lookup(vrfid); + if (zvrf) switch (type) { case RNH_NEXTHOP_TYPE: - t = vrf->rnh_table[family2afi(family)]; + t = zvrf->rnh_table[family2afi(family)]; break; case RNH_IMPORT_CHECK_TYPE: - t = vrf->import_check_table[family2afi(family)]; + t = zvrf->import_check_table[family2afi(family)]; break; } @@ -85,7 +96,7 @@ char *rnh_str (struct rnh *rnh, char *buf, int size) } 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_node *rn; @@ -125,7 +136,7 @@ zebra_add_rnh (struct prefix *p, u_int32_t vrfid, rnh_type_t type) } 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_node *rn; @@ -262,7 +273,7 @@ zebra_evaluate_rnh_nexthops(int family, struct rib *rib, struct route_node *prn, } 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 route_table *ptable; @@ -289,7 +300,7 @@ zebra_evaluate_rnh (int vrfid, int family, int force, rnh_type_t type, return -1; } - ptable = vrf_table(family2afi(family), SAFI_UNICAST, vrfid); + ptable = zebra_vrf_table(family2afi(family), SAFI_UNICAST, vrfid); if (!ptable) { 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 -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) { struct route_table *ntable; @@ -591,7 +602,7 @@ zebra_dispatch_rnh_table (int vrfid, int family, struct zserv *client, } 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_node *rn; @@ -609,7 +620,7 @@ zebra_print_rnh_table (int vrfid, int af, struct vty *vty, rnh_type_t type) } 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) { struct route_table *ntable; diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index 494be8366c..6deb878084 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -52,9 +52,9 @@ typedef enum extern int zebra_rnh_ip_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); -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); 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); @@ -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_remove_rnh_client(struct rnh *rnh, struct zserv *client, 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); -extern int zebra_dispatch_rnh_table(int 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 int zebra_dispatch_rnh_table(vrf_id_t vrfid, int family, struct zserv *cl, 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 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); #endif /*_ZEBRA_RNH_H */ diff --git a/zebra/zebra_snmp.c b/zebra/zebra_snmp.c index f0d3e7e582..3d005aa55a 100644 --- a/zebra/zebra_snmp.c +++ b/zebra/zebra_snmp.c @@ -19,6 +19,10 @@ * 02111-1307, USA. */ +/* + * Currently SNMP is only running properly for MIBs in the default VRF. + */ + #include #ifdef HAVE_SNMP @@ -31,6 +35,7 @@ #include "command.h" #include "smux.h" #include "table.h" +#include "vrf.h" #include "zebra/rib.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) return NULL; - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) 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) return NULL; - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) 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)) return; - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index a797b88391..9728a28c0e 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -28,6 +28,7 @@ #include "table.h" #include "rib.h" #include "nexthop.h" +#include "vrf.h" #include "zebra/zserv.h" #include "zebra/zebra_rnh.h" @@ -1184,7 +1185,7 @@ DEFUN (show_ip_route, struct rib *rib; int first = 1; - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -1305,7 +1306,7 @@ DEFUN (show_ip_route_tag, if (argv[0]) tag = atoi(argv[0]); - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -1349,7 +1350,7 @@ DEFUN (show_ip_route_prefix_longer, return CMD_WARNING; } - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -1382,7 +1383,7 @@ DEFUN (show_ip_route_supernets, u_int32_t addr; int first = 1; - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -1428,7 +1429,7 @@ DEFUN (show_ip_route_protocol, return CMD_WARNING; } - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -1464,7 +1465,7 @@ DEFUN (show_ip_route_ospf_instance, VTY_GET_INTEGER ("Instance", instance, argv[0]); - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -1503,7 +1504,7 @@ DEFUN (show_ip_route_addr, return CMD_WARNING; } - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -1541,7 +1542,7 @@ DEFUN (show_ip_route_prefix, return CMD_WARNING; } - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -1712,7 +1713,7 @@ DEFUN (show_ip_route_summary, { struct route_table *table; - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -1733,7 +1734,7 @@ DEFUN (show_ip_route_summary_prefix, { struct route_table *table; - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -1754,7 +1755,7 @@ static_config_ipv4 (struct vty *vty) write = 0; /* Lookup table. */ - stable = vrf_static_table (AFI_IP, SAFI_UNICAST, 0); + stable = zebra_vrf_static_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); if (! stable) return -1; @@ -1816,7 +1817,7 @@ DEFUN (show_ip_mroute, struct rib *rib; int first = 1; - table = vrf_table (AFI_IP, SAFI_MULTICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_MULTICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -2613,7 +2614,7 @@ DEFUN (show_ipv6_route, struct rib *rib; int first = 1; - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -2649,7 +2650,7 @@ DEFUN (show_ipv6_route_tag, if (argv[0]) tag = atoi(argv[0]); - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -2686,7 +2687,7 @@ DEFUN (show_ipv6_route_prefix_longer, int ret; int first = 1; - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -2733,7 +2734,7 @@ DEFUN (show_ipv6_route_protocol, return CMD_WARNING; } - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -2772,7 +2773,7 @@ DEFUN (show_ipv6_route_addr, return CMD_WARNING; } - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -2810,7 +2811,7 @@ DEFUN (show_ipv6_route_prefix, return CMD_WARNING; } - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -2839,7 +2840,7 @@ DEFUN (show_ipv6_route_summary, { struct route_table *table; - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -2860,7 +2861,7 @@ DEFUN (show_ipv6_route_summary_prefix, { struct route_table *table; - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -2886,7 +2887,7 @@ DEFUN (show_ipv6_mroute, struct rib *rib; int first = 1; - table = vrf_table (AFI_IP6, SAFI_MULTICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_MULTICAST, VRF_DEFAULT); if (! table) return CMD_SUCCESS; @@ -2917,7 +2918,7 @@ static_config_ipv6 (struct vty *vty) write = 0; /* Lookup table. */ - stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, 0); + stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); if (! stable) return -1; From 3968dbf8ef4966fb3f9d38640ea9c5a9f13419cf Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:39:57 +0200 Subject: [PATCH 11/27] lib, zebra: add "vrf_id" into the "struct interface" Later, an interface will belong to a specific VRF. Now we add a property "vrf_id" to the "struct interface", and keep it as the default value 0. This property is shown when displaying interfaces information. It is also added in some logs. This is just the preparation to move the interace list into the "struct vrf". The main logic is not changed. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter Conflicts: lib/if.c zebra/interface.c --- lib/if.c | 8 ++++---- lib/if.h | 2 ++ zebra/interface.c | 22 +++++++++++++--------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/lib/if.c b/lib/if.c index 3003e4c2f4..a9ab680296 100644 --- a/lib/if.c +++ b/lib/if.c @@ -521,12 +521,12 @@ if_flag_dump (unsigned long flag) static void 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 "mtu6 %d " #endif /* HAVE_IPV6 */ "%s", - ifp->name, ifp->ifindex, ifp->metric, ifp->mtu, + ifp->name, ifp->vrf_id, ifp->ifindex, ifp->metric, ifp->mtu, #ifdef HAVE_IPV6 ifp->mtu6, #endif /* HAVE_IPV6 */ @@ -773,8 +773,8 @@ connected_log (struct connected *connected, char *str) ifp = connected->ifp; p = connected->address; - snprintf (logbuf, BUFSIZ, "%s interface %s %s %s/%d ", - str, ifp->name, prefix_family_str (p), + snprintf (logbuf, BUFSIZ, "%s interface %s vrf %u %s %s/%d ", + str, ifp->name, ifp->vrf_id, prefix_family_str (p), inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen); diff --git a/lib/if.h b/lib/if.h index 6d4ca2f77e..f29e514e96 100644 --- a/lib/if.h +++ b/lib/if.h @@ -145,6 +145,8 @@ struct interface #ifdef HAVE_NET_RT_IFLIST struct if_data stats; #endif /* HAVE_NET_RT_IFLIST */ + + vrf_id_t vrf_id; }; /* Connected address structure. */ diff --git a/zebra/interface.c b/zebra/interface.c index 9d4a2f89d2..248f77d8f5 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -388,21 +388,23 @@ if_add_update (struct interface *ifp) if (if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) { if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("interface %s index %d is shutdown. Won't wake it up.", - ifp->name, ifp->ifindex); + zlog_debug ("interface %s vrf %u index %d is shutdown. " + "Won't wake it up.", + ifp->name, ifp->vrf_id, ifp->ifindex); return; } if_addr_wakeup (ifp); if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("interface %s index %d becomes active.", - ifp->name, ifp->ifindex); + zlog_debug ("interface %s vrf %u index %d becomes active.", + ifp->name, ifp->vrf_id, ifp->ifindex); } else { 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 +421,8 @@ if_delete_update (struct interface *ifp) if (if_is_up(ifp)) { - zlog_err ("interface %s index %d is still up while being deleted.", - ifp->name, ifp->ifindex); + zlog_err ("interface %s vrf %u index %d is still up while being deleted.", + ifp->name, ifp->vrf_id, ifp->ifindex); return; } @@ -428,8 +430,8 @@ if_delete_update (struct interface *ifp) UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE); if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("interface %s index %d is now inactive.", - ifp->name, ifp->ifindex); + zlog_debug ("interface %s vrf %u index %d is now inactive.", + ifp->name, ifp->vrf_id, ifp->ifindex); /* Delete connected routes from the kernel. */ if (ifp->connected) @@ -846,6 +848,8 @@ if_dump_vty (struct vty *vty, struct interface *ifp) zebra_ptm_show_status(vty, ifp); + vty_out (vty, " vrf: %u%s", ifp->vrf_id, VTY_NEWLINE); + if (ifp->desc) vty_out (vty, " Description: %s%s", ifp->desc, VTY_NEWLINE); From 6a69b354a6656f138a5f11e4542dc84f748f2bea Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:39:58 +0200 Subject: [PATCH 12/27] *: call if_init()/if_terminate() from vrf_init()/vrf_terminate() Later, an interface will belong to a specific VRF, and the interface initialization will be a part of the VRF initialization. So now call if_init() from vrf_init(), and if_terminate() from vrf_terminate(). Daemons have the according changes: - if if_init() was called or "iflist" was initialized, now call vrf_init() instead; - if if_terminate() was called or "iflist" was destroyed, now call vrf_terminate() instead. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter Conflicts: bgpd/bgp_main.c pimd/pim_iface.c pimd/pim_iface.h pimd/pim_main.c pimd/pimd.c --- bgpd/bgp_main.c | 8 ++++---- bgpd/bgp_zebra.c | 3 --- isisd/isis_circuit.c | 1 - isisd/isis_main.c | 2 ++ lib/vrf.c | 5 +++++ ospf6d/ospf6_main.c | 5 +++-- ospfd/ospf_interface.c | 1 - ospfd/ospf_main.c | 2 ++ ripd/rip_interface.c | 1 - ripd/rip_main.c | 2 ++ ripngd/ripng_interface.c | 2 +- ripngd/ripng_main.c | 2 ++ zebra/interface.c | 1 - zebra/test_main.c | 1 - 14 files changed, 21 insertions(+), 15 deletions(-) diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 49712fcf99..bf154db046 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -37,6 +37,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "plist.h" #include "stream.h" #include "queue.h" +#include "vrf.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_attr.h" @@ -238,17 +239,14 @@ bgp_exit (int status) /* reverse bgp_zebra_init/if_init */ if (retain_mode) 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 connected *c; for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c)) bgp_connected_delete (c); - - if_delete (ifp); } - list_free (iflist); /* reverse bgp_attr_init */ bgp_attr_finish (); @@ -280,6 +278,7 @@ bgp_exit (int status) /* reverse community_list_init */ community_list_terminate (bgp_clist); + vrf_terminate (); cmd_terminate (); vty_terminate (); if (zclient) @@ -412,6 +411,7 @@ main (int argc, char **argv) cmd_init (1); vty_init (bm->master); memory_init (); + vrf_init (); /* BGP related initialization. */ bgp_init (); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 052c2efacb..501af234a2 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1738,9 +1738,6 @@ bgp_zebra_init (struct thread_master *master) zclient->nexthop_update = bgp_read_nexthop_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_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE); } diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 4f7e2ce9ce..470a86e39d 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -2739,7 +2739,6 @@ void isis_circuit_init () { /* Initialize Zebra interface data structure */ - if_init (); if_add_hook (IF_NEW_HOOK, isis_if_new_hook); if_add_hook (IF_DELETE_HOOK, isis_if_delete_hook); diff --git a/isisd/isis_main.c b/isisd/isis_main.c index 75463b33bb..a19399c5a2 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -35,6 +35,7 @@ #include "sigevent.h" #include "filter.h" #include "zclient.h" +#include "vrf.h" #include "isisd/dict.h" #include "include-netbsd/iso.h" @@ -335,6 +336,7 @@ main (int argc, char **argv, char **envp) vty_init (master); memory_init (); access_list_init(); + vrf_init (); isis_init (); isis_circuit_init (); isis_spf_cmds_init (); diff --git a/lib/vrf.c b/lib/vrf.c index 3ccbb99617..51f9e3795b 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -22,6 +22,7 @@ #include +#include "if.h" #include "vrf.h" #include "prefix.h" #include "table.h" @@ -249,6 +250,8 @@ vrf_init (void) /* Set the default VRF name. */ default_vrf->name = XSTRDUP (MTYPE_VRF_NAME, "Default-IP-Routing-Table"); + + if_init (); } /* Terminate VRF module. */ @@ -264,5 +267,7 @@ vrf_terminate (void) route_table_finish (vrf_table); vrf_table = NULL; + + if_terminate (); } diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c index 75e409357c..af48d1fe4c 100644 --- a/ospf6d/ospf6_main.c +++ b/ospf6d/ospf6_main.c @@ -36,6 +36,7 @@ #include "privs.h" #include "sigevent.h" #include "zclient.h" +#include "vrf.h" #include "ospf6d.h" #include "ospf6_top.h" @@ -151,7 +152,7 @@ ospf6_exit (int status) ospf6_asbr_terminate (); ospf6_lsa_terminate (); - if_terminate (); + vrf_terminate (); vty_terminate (); cmd_terminate (); @@ -322,7 +323,7 @@ main (int argc, char *argv[], char *envp[]) cmd_init (1); vty_init (master); memory_init (); - if_init (); + vrf_init (); access_list_init (); prefix_list_init (); diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index b10f4fb4f7..c0b4e7abea 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -1269,7 +1269,6 @@ void ospf_if_init () { /* Initialize Zebra interface data structure. */ - if_init (); om->iflist = iflist; if_add_hook (IF_NEW_HOOK, ospf_if_new_hook); if_add_hook (IF_DELETE_HOOK, ospf_if_delete_hook); diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index e1f5a9a9bb..4e67b20bba 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -39,6 +39,7 @@ #include "privs.h" #include "sigevent.h" #include "zclient.h" +#include "vrf.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -300,6 +301,7 @@ main (int argc, char **argv) debug_init (); vty_init (master); memory_init (); + vrf_init (); access_list_init (); prefix_list_init (); diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 9a5bffe92b..b12ce5ee10 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -2077,7 +2077,6 @@ void rip_if_init (void) { /* Default initial size of interface vector. */ - if_init(); if_add_hook (IF_NEW_HOOK, rip_interface_new_hook); if_add_hook (IF_DELETE_HOOK, rip_interface_delete_hook); diff --git a/ripd/rip_main.c b/ripd/rip_main.c index 0db5634840..a5ea36a1f1 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -33,6 +33,7 @@ #include "privs.h" #include "sigevent.h" #include "zclient.h" +#include "vrf.h" #include "ripd/ripd.h" @@ -280,6 +281,7 @@ main (int argc, char **argv) vty_init (master); memory_init (); keychain_init (); + vrf_init (); /* RIP related initialization. */ rip_init (); diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index 9517c924c6..3f9f025975 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -35,6 +35,7 @@ #include "table.h" #include "thread.h" #include "privs.h" +#include "vrf.h" #include "ripngd/ripngd.h" #include "ripngd/ripng_debug.h" @@ -1200,7 +1201,6 @@ void ripng_if_init () { /* Interface initialize. */ - iflist = list_new (); if_add_hook (IF_NEW_HOOK, ripng_if_new_hook); if_add_hook (IF_DELETE_HOOK, ripng_if_delete_hook); diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c index 01590d96d1..c05da0c9ef 100644 --- a/ripngd/ripng_main.c +++ b/ripngd/ripng_main.c @@ -34,6 +34,7 @@ #include "if.h" #include "privs.h" #include "sigevent.h" +#include "vrf.h" #include "ripngd/ripngd.h" @@ -276,6 +277,7 @@ main (int argc, char **argv) cmd_init (1); vty_init (master); memory_init (); + vrf_init (); /* RIPngd inits. */ ripng_init (); diff --git a/zebra/interface.c b/zebra/interface.c index 248f77d8f5..d7dbb241d1 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1766,7 +1766,6 @@ void zebra_if_init (void) { /* Initialize interface and new hook. */ - if_init (); if_add_hook (IF_NEW_HOOK, if_zebra_new_hook); if_add_hook (IF_DELETE_HOOK, if_zebra_delete_hook); diff --git a/zebra/test_main.c b/zebra/test_main.c index f4a8ca2bad..0013506b9b 100644 --- a/zebra/test_main.c +++ b/zebra/test_main.c @@ -316,7 +316,6 @@ main (int argc, char **argv) cmd_init (1); vty_init (zebrad.master); memory_init (); - if_init(); zebra_debug_init (); zebra_if_init (); test_cmd_init (); From 8736158a2b4b43e841b9a7dcfcc11da0ed30bf23 Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:39:59 +0200 Subject: [PATCH 13/27] lib: move the interface list into "struct vrf" An interface belongs to a specific VRF. So move the interface list into the "struct vrf". * vrf.c/vrf.h: - add a new member "struct list *iflist" to the the "struct vrf"; - call if_init() in vrf_new(); - call if_terminate() in vrf_delete(); - add utilities to access the interface list and VRF ID in the specified VRF. * if.c/if.h: - the global "iflist" now only exists for the default VRF; - the global "if_master" is initialized on the definition; - in if_create(), the interface is added into the list in the specified VRF; if the VRF does not exist, create one; - add parameters to if_init()/if_terminate() so that the interface list in the VRF can be initialized/destroyed; - in if_dump_all() scan the interfaces in all the VRFs; - add a command "show address vrf N" to show addresses in a specified VRF; - add a command "show address vrf all" to show addresses in all VRFs; - new APIs ifxxx_vrf() are added to access an interface in a specified VRF. The old interface APIs (the global variable "iflist" and the API functions) are not changed to keep the backward compatibility. The new APIs are used in the daemons which support multiple VRFs (till now only zebra). Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter Conflicts: lib/if.c --- lib/if.c | 230 ++++++++++++++++++++++++++++++++++++++++++------------ lib/if.h | 33 +++++++- lib/vrf.c | 36 ++++++++- lib/vrf.h | 22 ++++++ 4 files changed, 261 insertions(+), 60 deletions(-) diff --git a/lib/if.c b/lib/if.c index a9ab680296..634c79ac4c 100644 --- a/lib/if.c +++ b/lib/if.c @@ -27,6 +27,7 @@ #include "vector.h" #include "vty.h" #include "command.h" +#include "vrf.h" #include "if.h" #include "sockunion.h" #include "prefix.h" @@ -36,7 +37,7 @@ #include "str.h" #include "log.h" -/* Master list of interfaces. */ +/* List of interfaces in only the default VRF */ struct list *iflist; int ptm_enable = 0; @@ -45,7 +46,7 @@ struct if_master { int (*if_new_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 * 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. */ 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 list *intf_list = vrf_iflist_get (vrf_id); ifp = XCALLOC (MTYPE_IF, sizeof (struct interface)); 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. */ strncpy (ifp->name, name, namelen); ifp->name[namelen] = '\0'; - if (if_lookup_by_name(ifp->name) == NULL) - listnode_add_sort (iflist, ifp); + ifp->vrf_id = vrf_id; + if (if_lookup_by_name_vrf (ifp->name, vrf_id) == NULL) + listnode_add_sort (intf_list, ifp); else 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->del = (void (*) (void *)) connected_free; @@ -145,6 +148,12 @@ if_create (const char *name, int namelen) return ifp; } +struct interface * +if_create (const char *name, int namelen) +{ + return if_create_vrf (name, namelen, VRF_DEFAULT); +} + /* Delete interface structure. */ void if_delete_retain (struct interface *ifp) @@ -163,7 +172,7 @@ if_delete_retain (struct interface *ifp) void if_delete (struct interface *ifp) { - listnode_delete (iflist, ifp); + listnode_delete (vrf_iflist (ifp->vrf_id), ifp); if_delete_retain(ifp); @@ -191,12 +200,12 @@ if_add_hook (int type, int (*func)(struct interface *ifp)) /* Interface existance check by index. */ 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 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) return ifp; @@ -204,33 +213,51 @@ if_lookup_by_index (unsigned int index) return NULL; } +struct interface * +if_lookup_by_index (unsigned int index) +{ + return if_lookup_by_index_vrf (index, VRF_DEFAULT); +} + const char * -ifindex2ifname (unsigned int index) +ifindex2ifname_vrf (unsigned int index, vrf_id_t vrf_id) { 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"; } +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 ifname2ifindex (const char *name) { - struct interface *ifp; - - return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp->ifindex - : IFINDEX_INTERNAL; + return ifname2ifindex_vrf (name, VRF_DEFAULT); } /* Interface existance check by interface name. */ 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 interface *ifp; 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) return ifp; @@ -239,7 +266,13 @@ if_lookup_by_name (const char *name) } 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 interface *ifp; @@ -247,7 +280,7 @@ if_lookup_by_name_len(const char *name, size_t namelen) if (namelen > INTERFACE_NAMSIZ) 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')) return ifp; @@ -255,9 +288,15 @@ if_lookup_by_name_len(const char *name, size_t namelen) 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. */ 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 *cnode; @@ -265,7 +304,7 @@ if_lookup_exact_address (void *src, int family) struct prefix *p; 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)) { @@ -289,9 +328,15 @@ if_lookup_exact_address (void *src, int family) 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. */ 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 prefix addr; @@ -316,7 +361,7 @@ if_lookup_address (void *matchaddr, int family) 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)) { @@ -332,6 +377,12 @@ if_lookup_address (void *matchaddr, int family) 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. */ struct connected * 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 */ 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 *cnode; struct interface *ifp; 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)) { @@ -384,24 +435,42 @@ if_lookup_prefix (struct prefix *prefix) 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 one. */ 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; - return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp : - if_create(name, strlen(name)); + return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp : + if_create_vrf (name, strlen(name), vrf_id); } 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; - return ((ifp = if_lookup_by_name_len(name, namelen)) != NULL) ? ifp : - if_create(name, namelen); + return ((ifp = if_lookup_by_name_len_vrf (name, namelen, vrf_id)) != NULL) ? \ + 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 ? */ @@ -537,11 +606,15 @@ if_dump (const struct interface *ifp) void if_dump_all (void) { + struct list *intf_list; struct listnode *node; void *p; + vrf_iter_t iter; - for (ALL_LIST_ELEMENTS_RO (iflist, node, p)) - if_dump (p); + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + if ((intf_list = vrf_iter2iflist (iter)) != NULL) + for (ALL_LIST_ELEMENTS_RO (intf_list, node, p)) + if_dump (p); } DEFUN (interface_desc, @@ -601,12 +674,12 @@ DEFUN (no_interface_desc, * - no idea, just get the name in its entirety. */ 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; 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; /* 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 */ if (seppos < nlen) - return if_get_by_name_len (name, seppos); + return if_get_by_name_len_vrf (name, seppos, vrf_id); else - return if_get_by_name_len (name, nlen); + return if_get_by_name_len_vrf (name, nlen, vrf_id); } #endif /* SUNOS_5 */ @@ -629,6 +702,7 @@ DEFUN (interface, { struct interface *ifp; size_t sl; + vrf_id_t vrf_id = VRF_DEFAULT; if ((sl = strlen(argv[0])) > INTERFACE_NAMSIZ) { @@ -639,9 +713,9 @@ DEFUN (interface, } #ifdef SUNOS_5 - ifp = if_sunwzebra_get (argv[0], sl); + ifp = if_sunwzebra_get (argv[0], sl, vrf_id); #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 */ vty->index = ifp; @@ -659,8 +733,9 @@ DEFUN_NOSH (no_interface, { // deleting interface struct interface *ifp; + vrf_id_t vrf_id = VRF_DEFAULT; - ifp = if_lookup_by_name (argv[0]); + ifp = if_lookup_by_name_vrf (argv[0], vrf_id); if (ifp == NULL) { @@ -692,8 +767,12 @@ DEFUN (show_address, struct interface *ifp; struct connected *ifc; 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)) { @@ -707,6 +786,52 @@ DEFUN (show_address, 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. */ struct connected * connected_new (void) @@ -1004,35 +1129,36 @@ ifaddr_ipv4_lookup (struct in_addr *addr, unsigned int ifindex) /* Initialize interface list. */ void -if_init (void) +if_init (vrf_id_t vrf_id, struct list **intf_list) { - iflist = list_new (); + *intf_list = list_new (); #if 0 ifaddr_ipv4_table = route_table_init (); #endif /* ifaddr_ipv4_table */ - if (iflist) { - iflist->cmp = (int (*)(void *, void *))if_cmp_func; - return; - } + (*intf_list)->cmp = (int (*)(void *, void *))if_cmp_func; - memset (&if_master, 0, sizeof if_master); + if (vrf_id == VRF_DEFAULT) + iflist = *intf_list; } void -if_terminate (void) +if_terminate (vrf_id_t vrf_id, struct list **intf_list) { for (;;) { struct interface *ifp; - ifp = listnode_head (iflist); + ifp = listnode_head (*intf_list); if (ifp == NULL) break; if_delete (ifp); } - list_delete (iflist); - iflist = NULL; + list_delete (*intf_list); + *intf_list = NULL; + + if (vrf_id == VRF_DEFAULT) + iflist = NULL; } diff --git a/lib/if.h b/lib/if.h index f29e514e96..57a2a959da 100644 --- a/lib/if.h +++ b/lib/if.h @@ -273,17 +273,38 @@ extern struct interface *if_lookup_address (void *matchaddr, int family); extern struct interface *if_lookup_prefix (struct prefix *prefix); 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 by a '\0' character: */ extern struct interface *if_lookup_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 of the ifname string (not counting any optional trailing '\0' character). In most cases, strnlen should be used to calculate the namelen value. */ extern struct interface *if_lookup_by_name_len(const char *ifname, - size_t namelen); -extern struct interface *if_get_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_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 @@ -304,8 +325,8 @@ extern int if_is_broadcast (struct interface *); extern int if_is_pointopoint (struct interface *); extern int if_is_multicast (struct interface *); extern void if_add_hook (int, int (*)(struct interface *)); -extern void if_init (void); -extern void if_terminate (void); +extern void if_init (vrf_id_t, struct list **); +extern void if_terminate (vrf_id_t, struct list **); extern void if_dump_all (void); extern const char *if_flag_dump(unsigned long); @@ -313,11 +334,13 @@ extern const char *if_flag_dump(unsigned long); ifindex2ifname uses internal interface info, whereas if_indextoname must make a system call. */ 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; ifname2ifindex uses internal interface info, whereas if_nametoindex must make a system call. */ extern unsigned int ifname2ifindex(const char *ifname); +extern unsigned int ifname2ifindex_vrf(const char *ifname, vrf_id_t vrf_id); /* Connected address functions. */ extern struct connected *connected_new (void); @@ -350,5 +373,7 @@ extern struct cmd_element no_interface_cmd; extern struct cmd_element interface_pseudo_cmd; extern struct cmd_element no_interface_pseudo_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 */ diff --git a/lib/vrf.c b/lib/vrf.c index 51f9e3795b..ea14fd3c68 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -36,6 +36,9 @@ struct vrf /* Name */ char *name; + /* Master list of interfaces belonging to this VRF */ + struct list *iflist; + /* User data */ void *info; }; @@ -80,6 +83,9 @@ vrf_get (vrf_id_t vrf_id) 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) @@ -97,6 +103,8 @@ vrf_delete (struct vrf *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); @@ -215,6 +223,14 @@ vrf_iter2info (vrf_iter_t 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) @@ -231,6 +247,22 @@ vrf_info_lookup (vrf_id_t 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) @@ -250,8 +282,6 @@ vrf_init (void) /* Set the default VRF name. */ default_vrf->name = XSTRDUP (MTYPE_VRF_NAME, "Default-IP-Routing-Table"); - - if_init (); } /* Terminate VRF module. */ @@ -267,7 +297,5 @@ vrf_terminate (void) route_table_finish (vrf_table); vrf_table = NULL; - - if_terminate (); } diff --git a/lib/vrf.h b/lib/vrf.h index 7e05099433..d7b799875b 100644 --- a/lib/vrf.h +++ b/lib/vrf.h @@ -23,9 +23,21 @@ #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 */ @@ -75,6 +87,7 @@ extern vrf_iter_t vrf_iterator (vrf_id_t); */ 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 @@ -85,6 +98,15 @@ 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 */ From cd2a8a42e10a81f84b8c4dd061f1125b06b06bc5 Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:40:00 +0200 Subject: [PATCH 14/27] lib, zebra, vtysh: configure an interface in non-default VRF Introduce a new command "interface IFNAME vrf N" to configure an interface in the non-default VRF. Till now, only zebra uses this command. Other daemons will install the command when they support multiple VRFs. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter Conflicts: zebra/interface.c --- lib/if.c | 21 +++++++++++++++++++++ lib/if.h | 2 ++ vtysh/extract.pl.in | 1 + vtysh/vtysh.c | 19 +++++++++++++++++++ zebra/interface.c | 23 +++++++++++++++++++---- 5 files changed, 62 insertions(+), 4 deletions(-) diff --git a/lib/if.c b/lib/if.c index 634c79ac4c..b192d48e20 100644 --- a/lib/if.c +++ b/lib/if.c @@ -712,6 +712,9 @@ DEFUN (interface, return CMD_WARNING; } + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + #ifdef SUNOS_5 ifp = if_sunwzebra_get (argv[0], sl, vrf_id); #else @@ -724,6 +727,13 @@ DEFUN (interface, 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, no_interface_cmd, "no interface IFNAME", @@ -735,6 +745,9 @@ DEFUN_NOSH (no_interface, struct interface *ifp; vrf_id_t vrf_id = VRF_DEFAULT; + 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) @@ -755,6 +768,14 @@ DEFUN_NOSH (no_interface, 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. */ DEFUN (show_address, show_address_cmd, diff --git a/lib/if.h b/lib/if.h index 57a2a959da..05803d01ad 100644 --- a/lib/if.h +++ b/lib/if.h @@ -370,6 +370,8 @@ extern struct cmd_element interface_desc_cmd; extern struct cmd_element no_interface_desc_cmd; extern struct cmd_element 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 no_interface_pseudo_cmd; extern struct cmd_element show_address_cmd; diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index 2249b4092a..56e7115925 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -31,6 +31,7 @@ print <"'} = "ignore"; $ignore{'"ip vrf NAME"'} = "ignore"; $ignore{'"router rip"'} = "ignore"; $ignore{'"router ripng"'} = "ignore"; diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 54e3e4f6c6..58014c2e0d 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -39,6 +39,7 @@ #include "vtysh/vtysh.h" #include "log.h" #include "bgpd/bgp_vty.h" +#include "vrf.h" /* Struct VTY. */ struct vty *vty; @@ -1498,6 +1499,14 @@ DEFUNSH (VTYSH_INTERFACE, 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. */ DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D, 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" "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 * and isisd. */ 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 (CONFIG_NODE, &vtysh_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_daemon_cmd); install_element (ENABLE_NODE, &vtysh_copy_runningconfig_startupconfig_cmd); diff --git a/zebra/interface.c b/zebra/interface.c index d7dbb241d1..763f826d81 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -32,6 +32,7 @@ #include "connected.h" #include "log.h" #include "zclient.h" +#include "vrf.h" #include "zebra/interface.h" #include "zebra/rtadv.h" @@ -1033,6 +1034,13 @@ DEFUN_NOSH (zebra_interface, 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 = { INTERFACE_NODE, @@ -1689,10 +1697,12 @@ if_config_write (struct vty *vty) { struct listnode *node; struct interface *ifp; + vrf_iter_t iter; 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 listnode *addrnode; @@ -1700,9 +1710,12 @@ if_config_write (struct vty *vty) struct prefix *p; if_data = ifp->info; - - vty_out (vty, "interface %s%s", ifp->name, - VTY_NEWLINE); + + if (ifp->vrf_id == VRF_DEFAULT) + 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) { @@ -1776,7 +1789,9 @@ zebra_if_init (void) install_element (ENABLE_NODE, &show_interface_cmd); install_element (ENABLE_NODE, &show_interface_desc_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_vrf_cmd); install_default (INTERFACE_NODE); install_element (INTERFACE_NODE, &interface_desc_cmd); install_element (INTERFACE_NODE, &no_interface_desc_cmd); From 8b87bdf4165979e072b3417dbf82300d18ca7d96 Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:40:01 +0200 Subject: [PATCH 15/27] zebra: show interfaces in a specified VRF or all VRFs The following commands only show interfaces in the default VRF: show interface show interface IFNAME show interface description New options are introduced to show interfaces in a specified VRF: show interface vrf N show interface IFNAME vrf N show interface description vrf N or all VRFs: show interface vrf all show interface IFNAME vrf all show interface description vrf all Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter --- zebra/interface.c | 211 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 187 insertions(+), 24 deletions(-) diff --git a/zebra/interface.c b/zebra/interface.c index 763f826d81..2ae2b0bf51 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1048,16 +1048,16 @@ struct cmd_node interface_node = 1 }; -/* Show all or specified interface to vty. */ +/* Show all interfaces to vty. */ DEFUN (show_interface, show_interface_cmd, - "show interface [IFNAME]", + "show interface", SHOW_STR - "Interface status and configuration\n" - "Inteface name\n") + "Interface status and configuration\n") { struct listnode *node; 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. */ @@ -1067,39 +1067,144 @@ DEFUN (show_interface, show_interface_cmd, ifstat_update_sysctl (); #endif /* HAVE_NET_RT_IFLIST */ - /* Specified interface print. */ - if (argc != 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; - } + if (argc > 0) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); /* 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); return CMD_SUCCESS; } -DEFUN (show_interface_desc, - show_interface_desc_cmd, - "show interface description", +ALIAS (show_interface, + show_interface_vrf_cmd, + "show interface " VRF_CMD_STR, SHOW_STR "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 interface *ifp; 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; @@ -1130,6 +1235,52 @@ DEFUN (show_interface_desc, vty_out (vty, "%s", ifp->desc); 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; } @@ -1786,8 +1937,20 @@ zebra_if_init (void) install_node (&interface_node, if_config_write); 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_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_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_vrf_cmd); install_element (CONFIG_NODE, &no_interface_cmd); From 78104b9bad14a3185178cedc0dd41d1b1c5db493 Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:40:02 +0200 Subject: [PATCH 16/27] zebra: let FIB stand for its respective VRF A new member "vrf_id" is added to "struct rib", reflecting the VRF which it belongs to. A new parameter "vrf_id" is added to the relative functions where need, except those: - which already have the parameter "vrf_id"; or - which have a parameter in type of "struct rib"; or - which have a parameter in type of "struct interface". All incoming routes are set to default VRF. In fact, all routes in FIB are kept in default VRF. And the logic is not changed. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN [DL: conflicts fixed + compile warning fix] Signed-off-by: David Lamparter Conflicts: zebra/connected.c zebra/kernel_socket.c zebra/rib.h zebra/rt_netlink.c zebra/zebra_rib.c zebra/zserv.c Conflicts: zebra/connected.c zebra/interface.c zebra/kernel_socket.c zebra/rib.h zebra/rt_netlink.c zebra/rtread_getmsg.c zebra/zebra_rib.c zebra/zebra_vty.c zebra/zserv.c --- lib/prefix.c | 7 +- lib/prefix.h | 2 +- zebra/connected.c | 29 +++--- zebra/interface.c | 4 +- zebra/kernel_socket.c | 17 ++-- zebra/rib.h | 37 ++++---- zebra/rt_netlink.c | 20 +++-- zebra/rtread_getmsg.c | 3 +- zebra/zebra_rib.c | 199 ++++++++++++++++++++++++------------------ zebra/zebra_vty.c | 16 ++-- zebra/zserv.c | 19 ++-- 11 files changed, 202 insertions(+), 151 deletions(-) diff --git a/lib/prefix.c b/lib/prefix.c index 739764842d..43331d1552 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -766,14 +766,15 @@ str2prefix (const char *str, struct prefix *p) return 0; } -int -prefix2str (const struct prefix *p, char *str, int size) +const char * +prefix2str (union prefix46constptr pu, char *str, int size) { + const struct prefix *p = pu.p; char buf[BUFSIZ]; inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ); snprintf (str, size, "%s/%d", buf, p->prefixlen); - return 0; + return str; } struct prefix * diff --git a/lib/prefix.h b/lib/prefix.h index cc4bbe280d..7fef37e3ff 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -179,7 +179,7 @@ extern void prefix_free (struct prefix *); extern const char *prefix_family_str (const struct prefix *); extern int prefix_blen (const struct prefix *); extern int str2prefix (const char *, struct prefix *); -extern int prefix2str (const struct prefix *, char *, int); +extern const char *prefix2str (union prefix46constptr, char *, int); extern int prefix_match (const struct prefix *, const struct prefix *); extern int prefix_same (const struct prefix *, const struct prefix *); extern int prefix_cmp (const struct prefix *, const struct prefix *); diff --git a/zebra/connected.c b/zebra/connected.c index 2ec6911d77..0d2407a3e0 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -209,15 +209,15 @@ connected_up_ipv4 (struct interface *ifp, struct connected *ifc) return; rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex, - RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST); + ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST); rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex, - RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST); + ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST); if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update", __func__); - rib_update (); + rib_update (ifp->vrf_id); } /* Add connected IPv4 route to the interface. */ @@ -327,14 +327,16 @@ connected_down_ipv4 (struct interface *ifp, struct connected *ifc) return; /* Same logic as for connected_up_ipv4(): push the changes into the head. */ - rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST); + rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, 0, + SAFI_UNICAST); - rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, 0, SAFI_MULTICAST); + rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, 0, + SAFI_MULTICAST); if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update_static", __func__); - rib_update_static (); + rib_update_static (ifp->vrf_id); } void @@ -397,7 +399,7 @@ connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update_static", __func__); - rib_update_static(); + rib_update_static(ifp->vrf_id); } #ifdef HAVE_IPV6 @@ -420,13 +422,13 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc) return; #endif - rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, RT_TABLE_MAIN, - ifp->metric, 0, SAFI_UNICAST); + rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, + RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST); if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update", __func__); - rib_update (); + rib_update (ifp->vrf_id); } /* Add connected IPv6 route to the interface. */ @@ -509,12 +511,13 @@ connected_down_ipv6 (struct interface *ifp, struct connected *ifc) if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix)) return; - rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST); + rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, + ifp->vrf_id, 0, SAFI_UNICAST); if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update_static", __func__); - rib_update_static (); + rib_update_static (ifp->vrf_id); } void @@ -538,6 +541,6 @@ connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address, if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update_static", __func__); - rib_update_static(); + rib_update_static(ifp->vrf_id); } #endif /* HAVE_IPV6 */ diff --git a/zebra/interface.c b/zebra/interface.c index 2ae2b0bf51..a3d297d327 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -644,7 +644,7 @@ if_up (struct interface *ifp) ifp->name); /* Examine all static routes. */ - rib_update (); + rib_update (ifp->vrf_id); } /* Interface goes down. We have to manage different behavior of based @@ -681,7 +681,7 @@ if_down (struct interface *ifp) zlog_debug ("%s: calling rib_update_static on interface %s down", __func__, ifp->name); - rib_update_static (); + rib_update_static (ifp->vrf_id); if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp); diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 03f3eaeb6a..a1002a4d86 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -32,6 +32,7 @@ #include "table.h" #include "rib.h" #include "privs.h" +#include "vrf.h" #include "zebra/interface.h" #include "zebra/zserv.h" @@ -870,8 +871,8 @@ rtm_read (struct rt_msghdr *rtm) int ret; if (! IS_ZEBRA_DEBUG_RIB) return; - ret = rib_lookup_ipv4_route (&p, &gate); - inet_ntop (AF_INET, &p.prefix, buf, INET_ADDRSTRLEN); + ret = rib_lookup_ipv4_route (&p, &gate, VRF_DEFAULT); + prefix2str (&p, buf, sizeof(buf)); switch (rtm->rtm_type) { case RTM_ADD: @@ -935,16 +936,16 @@ rtm_read (struct rt_msghdr *rtm) */ if (rtm->rtm_type == RTM_CHANGE) rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, - NULL, 0, 0, SAFI_UNICAST); + NULL, 0, VRF_DEFAULT, SAFI_UNICAST); if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin.sin_addr, NULL, 0, 0, 0, 0, SAFI_UNICAST); + &p, &gate.sin.sin_addr, NULL, 0, VRF_DEFAULT, 0, 0, SAFI_UNICAST); else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0 zebra_flags, - &p, &gate.sin.sin_addr, 0, 0, SAFI_UNICAST); + &p, &gate.sin.sin_addr, 0, VRF_DEFAULT, SAFI_UNICAST); } #ifdef HAVE_IPV6 if (dest.sa.sa_family == AF_INET6) @@ -977,16 +978,16 @@ rtm_read (struct rt_msghdr *rtm) */ if (rtm->rtm_type == RTM_CHANGE) rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, - NULL, 0, 0, SAFI_UNICAST); + NULL, 0, VRF_DEFAULT, SAFI_UNICAST); if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin6.sin6_addr, ifindex, 0, 0, 0, SAFI_UNICAST); + &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, 0, 0, SAFI_UNICAST); else rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &gate.sin6.sin6_addr, ifindex, 0, SAFI_UNICAST); + &p, &gate.sin6.sin6_addr, ifindex, VRF_DEFAULT, SAFI_UNICAST); } #endif /* HAVE_IPV6 */ } diff --git a/zebra/rib.h b/zebra/rib.h index 8c82a7eec3..6908e9d816 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -52,6 +52,9 @@ struct rib /* Source protocol instance */ u_short instance; + /* VRF identifier. */ + vrf_id_t vrf_id; + /* Which routing table */ uint32_t table; @@ -367,7 +370,8 @@ extern void rib_lookup_and_pushup (struct prefix_ipv4 *); #define rib_dump(prefix ,rib) _rib_dump(__func__, prefix, rib) extern void _rib_dump (const char *, union prefix46constptr, const struct rib *); -extern int rib_lookup_ipv4_route (struct prefix_ipv4 *, union sockunion *); +extern int rib_lookup_ipv4_route (struct prefix_ipv4 *, union sockunion *, + vrf_id_t); #define ZEBRA_RIB_LOOKUP_ERROR -1 #define ZEBRA_RIB_FOUND_EXACT 0 #define ZEBRA_RIB_FOUND_NOGATE 1 @@ -401,21 +405,21 @@ extern int zebra_check_addr (struct prefix *p); * also implicitly withdraw equal prefix of same type. */ extern int rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, struct in_addr *gate, struct in_addr *src, - unsigned int ifindex, u_int32_t vrf_id, + unsigned int ifindex, vrf_id_t vrf_id, u_int32_t table_id, u_int32_t, u_char, safi_t); extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *, safi_t); extern int rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, struct in_addr *gate, unsigned int ifindex, - u_int32_t, safi_t safi); + vrf_id_t, u_int32_t, safi_t safi); -extern struct rib *rib_match_ipv4 (struct in_addr); +extern struct rib *rib_match_ipv4 (struct in_addr, vrf_id_t); -extern struct rib *rib_lookup_ipv4 (struct prefix_ipv4 *); +extern struct rib *rib_lookup_ipv4 (struct prefix_ipv4 *, vrf_id_t); -extern void rib_update (void); -extern void rib_update_static (void); +extern void rib_update (vrf_id_t); +extern void rib_update_static (vrf_id_t); extern void rib_weed_tables (void); extern void rib_sweep_route (void); extern void rib_close (void); @@ -427,32 +431,33 @@ extern void rib_queue_add (struct zebra_t *zebra, struct route_node *rn); extern int static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, - u_char flags, u_short tag, u_char distance, u_int32_t vrf_id); + u_char flags, u_short tag, u_char distance, vrf_id_t vrf_id); extern int static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, - u_short tag, u_char distance, u_int32_t vrf_id); + u_short tag, u_char distance, vrf_id_t vrf_id); #ifdef HAVE_IPV6 extern int rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, - u_int32_t metric, u_char distance, safi_t safi); + struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, + u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi); extern int rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi); + struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, + u_int32_t table_id, safi_t safi); -extern struct rib *rib_lookup_ipv6 (struct in6_addr *); +extern struct rib *rib_lookup_ipv6 (struct in6_addr *, vrf_id_t); -extern struct rib *rib_match_ipv6 (struct in6_addr *); +extern struct rib *rib_match_ipv6 (struct in6_addr *, vrf_id_t); extern struct route_table *rib_table_ipv6; extern int static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, const char *ifname, u_char flags, u_short tag, - u_char distance, u_int32_t vrf_id); + u_char distance, vrf_id_t vrf_id); extern int rib_add_ipv6_multipath (struct prefix *, struct rib *, safi_t, @@ -461,7 +466,7 @@ rib_add_ipv6_multipath (struct prefix *, struct rib *, safi_t, extern int static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, const char *ifname, u_short tag, u_char distance, - u_int32_t vrf_id); + vrf_id_t vrf_id); #endif /* HAVE_IPV6 */ diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 4c16df61a1..e312801e55 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -37,6 +37,7 @@ #include "thread.h" #include "privs.h" #include "nexthop.h" +#include "vrf.h" #include "zebra/zserv.h" #include "zebra/rt.h" @@ -755,7 +756,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) if (!tb[RTA_MULTIPATH]) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, src, index, - table, metric, 0, SAFI_UNICAST); + VRF_DEFAULT, table, metric, 0, SAFI_UNICAST); else { /* This is a multipath route */ @@ -771,6 +772,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) rib->distance = 0; rib->flags = flags; rib->metric = metric; + rib->vrf_id = VRF_DEFAULT; rib->table = table; rib->nexthop_num = 0; rib->uptime = time (NULL); @@ -821,8 +823,8 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) memcpy (&p.prefix, dest, 16); p.prefixlen = rtm->rtm_dst_len; - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, index, table, - metric, 0, SAFI_UNICAST); + rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, index, VRF_DEFAULT, + table, metric, 0, SAFI_UNICAST); } #endif /* HAVE_IPV6 */ @@ -958,8 +960,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (h->nlmsg_type == RTM_NEWROUTE) { if (!tb[RTA_MULTIPATH]) - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, src, index, table, - metric, 0, SAFI_UNICAST); + rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, src, index, VRF_DEFAULT, + table, metric, 0, SAFI_UNICAST); else { /* This is a multipath route */ @@ -975,6 +977,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) rib->distance = 0; rib->flags = 0; rib->metric = metric; + rib->vrf_id = VRF_DEFAULT; rib->table = table; rib->nexthop_num = 0; rib->uptime = time (NULL); @@ -1020,7 +1023,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) } else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, - table, SAFI_UNICAST); + VRF_DEFAULT, table, SAFI_UNICAST); } #ifdef HAVE_IPV6 @@ -1046,10 +1049,11 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) } if (h->nlmsg_type == RTM_NEWROUTE) - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, index, table, metric, 0, SAFI_UNICAST); + rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, index, VRF_DEFAULT, + table, metric, 0, SAFI_UNICAST); else rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, - table, SAFI_UNICAST); + VRF_DEFAULT, table, SAFI_UNICAST); } #endif /* HAVE_IPV6 */ diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index 17d75b283a..f9bfb338a0 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -25,6 +25,7 @@ #include "prefix.h" #include "log.h" #include "if.h" +#include "vrf.h" #include "zebra/rib.h" #include "zebra/zserv.h" @@ -90,7 +91,7 @@ handle_route_entry (mib2_ipRouteEntry_t *routeEntry) gateway.s_addr = routeEntry->ipRouteNextHop; rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &prefix, - &gateway, NULL, 0, 0, 0, 0, SAFI_UNICAST); + &gateway, NULL, 0, VRF_DEFAULT, 0, 0, 0, SAFI_UNICAST); } void diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index b15cbd3cdb..79aa989814 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -483,7 +483,7 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, p.prefix = nexthop->gate.ipv4; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, rib->vrf_id); if (! table) return 0; @@ -692,7 +692,7 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, p.prefix = nexthop->gate.ipv6; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, rib->vrf_id); if (! table) return 0; @@ -846,7 +846,7 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, #endif /* HAVE_IPV6 */ struct rib * -rib_match_ipv4 (struct in_addr addr) +rib_match_ipv4 (struct in_addr addr, vrf_id_t vrf_id) { struct prefix_ipv4 p; struct route_table *table; @@ -856,7 +856,7 @@ rib_match_ipv4 (struct in_addr addr) int recursing; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) return 0; @@ -908,7 +908,7 @@ rib_match_ipv4 (struct in_addr addr) } struct rib * -rib_lookup_ipv4 (struct prefix_ipv4 *p) +rib_lookup_ipv4 (struct prefix_ipv4 *p, vrf_id_t vrf_id) { struct route_table *table; struct route_node *rn; @@ -917,7 +917,7 @@ rib_lookup_ipv4 (struct prefix_ipv4 *p) int recursing; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) return 0; @@ -964,7 +964,8 @@ rib_lookup_ipv4 (struct prefix_ipv4 *p) * 3: no matches found */ int -rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate) +rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate, + vrf_id_t vrf_id) { struct route_table *table; struct route_node *rn; @@ -974,7 +975,7 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate) int nexthops_active; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) return ZEBRA_RIB_LOOKUP_ERROR; @@ -1030,7 +1031,7 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate) #ifdef HAVE_IPV6 struct rib * -rib_match_ipv6 (struct in6_addr *addr) +rib_match_ipv6 (struct in6_addr *addr, vrf_id_t vrf_id) { struct prefix_ipv6 p; struct route_table *table; @@ -1040,7 +1041,7 @@ rib_match_ipv6 (struct in6_addr *addr) int recursing; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) return 0; @@ -1124,7 +1125,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, switch (nexthop->type) { case NEXTHOP_TYPE_IFINDEX: - ifp = if_lookup_by_index (nexthop->ifindex); + ifp = if_lookup_by_index_vrf (nexthop->ifindex, rib->vrf_id); if (ifp && if_is_operative(ifp)) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); else @@ -1133,7 +1134,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, case NEXTHOP_TYPE_IPV6_IFNAME: family = AFI_IP6; case NEXTHOP_TYPE_IFNAME: - ifp = if_lookup_by_name (nexthop->ifname); + ifp = if_lookup_by_name_vrf (nexthop->ifname, rib->vrf_id); if (ifp && if_is_operative(ifp)) { if (set) @@ -1169,7 +1170,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, family = AFI_IP6; if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6)) { - ifp = if_lookup_by_index (nexthop->ifindex); + ifp = if_lookup_by_index_vrf (nexthop->ifindex, rib->vrf_id); if (ifp && if_is_operative(ifp)) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); else @@ -2150,7 +2151,7 @@ rib_delnode (struct route_node *rn, struct rib *rib) int rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, struct in_addr *gate, struct in_addr *src, - unsigned int ifindex, u_int32_t table_id, + unsigned int ifindex, vrf_id_t vrf_id, u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi) { struct rib *rib; @@ -2162,11 +2163,11 @@ rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, safi, vrf_id); } else { - table = zebra_vrf_other_route_table (AFI_IP, table_id, VRF_DEFAULT); + table = zebra_vrf_other_route_table (AFI_IP, table_id, vrf_id); } if (! table) return 0; @@ -2226,6 +2227,7 @@ rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, rib->flags = flags; rib->metric = metric; rib->table = table_id; + rib->vrf_id = vrf_id; rib->nexthop_num = 0; rib->uptime = time (NULL); @@ -2279,8 +2281,8 @@ void _rib_dump (const char * func, struct nexthop *nexthop, *tnexthop; int recursing; - inet_ntop (p->family, &p->u.prefix, straddr, INET6_ADDRSTRLEN); - zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr, p->prefixlen); + zlog_debug ("%s: dumping RIB entry %p for %s vrf %u", func, rib, + prefix2str(pp, straddr, sizeof(straddr)), rib->vrf_id); zlog_debug ( "%s: refcnt == %lu, uptime == %lu, type == %u, instance == %d, table == %d", @@ -2439,11 +2441,11 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) /* Lookup table. */ if ((rib->table == zebrad.rtm_table_default) || (rib->table == RT_TABLE_MAIN)) { - table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, safi, rib->vrf_id); } else { - table = zebra_vrf_other_route_table (AFI_IP, rib->table, VRF_DEFAULT); + table = zebra_vrf_other_route_table (AFI_IP, rib->table, rib->vrf_id); } if (! table) return 0; @@ -2513,7 +2515,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) /* XXX factor with rib_delete_ipv6 */ int rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, - struct in_addr *gate, unsigned int ifindex, + struct in_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, u_int32_t table_id, safi_t safi) { struct route_table *table; @@ -2529,11 +2531,11 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = zebra_vrf_table (AFI_IP, safi, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, safi, vrf_id); } else { - table = zebra_vrf_other_route_table(AFI_IP, table_id, VRF_DEFAULT); + table = zebra_vrf_other_route_table(AFI_IP, table_id, vrf_id); } if (! table) return 0; @@ -2544,15 +2546,13 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, if (IS_ZEBRA_DEBUG_KERNEL) { if (gate) - zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d", - inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u via %s ifindex %d", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, inet_ntoa (*gate), ifindex); else - zlog_debug ("rib_delete_ipv4(): route delete %s/%d ifindex %d", - inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u ifindex %d", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, ifindex); } @@ -2563,15 +2563,13 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, if (IS_ZEBRA_DEBUG_KERNEL) { if (gate) - zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib", - inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN), ifindex); else - zlog_debug ("route %s/%d ifindex %d doesn't exist in rib", - inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, ifindex); } return ZEBRA_ERR_RTNOEXIST; @@ -2656,16 +2654,15 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, if (IS_ZEBRA_DEBUG_KERNEL) { if (gate) - zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib", - inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("route %s vrf %u via %s ifindex %d type %d " + "doesn't exist in rib", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN), ifindex, type); else - zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib", - inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, ifindex, type); } @@ -2742,6 +2739,7 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si) rib->instance = 0; rib->distance = si->distance; rib->metric = 0; + rib->vrf_id = VRF_DEFAULT; rib->table = zebrad.rtm_table_default; rib->nexthop_num = 0; rib->tag = si->tag; @@ -2876,7 +2874,7 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si) /* Add static route into static route configuration. */ int static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, - u_char flags, u_short tag, u_char distance, u_int32_t vrf_id) + u_char flags, u_short tag, u_char distance, vrf_id_t vrf_id) { u_char type = 0; struct route_node *rn; @@ -2884,10 +2882,9 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, struct static_ipv4 *pp; struct static_ipv4 *cp; struct static_ipv4 *update = NULL; - struct route_table *stable; + struct zebra_vrf *zvrf = vrf_info_get (vrf_id); + struct route_table *stable = zvrf->stable[AFI_IP][SAFI_UNICAST]; - /* Lookup table. */ - stable = zebra_vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! stable) return -1; @@ -2972,7 +2969,7 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, /* Delete static route from static route configuration. */ int static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, - u_short tag, u_char distance, u_int32_t vrf_id) + u_short tag, u_char distance, vrf_id_t vrf_id) { u_char type = 0; struct route_node *rn; @@ -3059,8 +3056,8 @@ rib_bogus_ipv6 (int type, struct prefix_ipv6 *p, int rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, unsigned int ifindex, u_int32_t table_id, - u_int32_t metric, u_char distance, safi_t safi) + struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, + u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi) { struct rib *rib; struct rib *same = NULL; @@ -3071,11 +3068,11 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, safi, vrf_id); } else { - table = zebra_vrf_other_route_table(AFI_IP6, table_id, VRF_DEFAULT); + table = zebra_vrf_other_route_table(AFI_IP6, table_id, vrf_id); } if (! table) return 0; @@ -3131,6 +3128,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, rib->flags = flags; rib->metric = metric; rib->table = table_id; + rib->vrf_id = vrf_id; rib->nexthop_num = 0; rib->uptime = time (NULL); @@ -3294,7 +3292,8 @@ rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi, /* XXX factor with rib_delete_ipv6 */ int rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, - struct in6_addr *gate, unsigned int ifindex, u_int32_t table_id, safi_t safi) + struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id, + u_int32_t table_id, safi_t safi) { struct route_table *table; struct route_node *rn; @@ -3312,7 +3311,7 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, /* Lookup table. */ if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) { - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, safi, vrf_id); } else { @@ -3328,15 +3327,13 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, if (IS_ZEBRA_DEBUG_KERNEL) { if (gate) - zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib", - inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN), ifindex); else - zlog_debug ("route %s/%d ifindex %d doesn't exist in rib", - inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, ifindex); } return ZEBRA_ERR_RTNOEXIST; @@ -3422,16 +3419,15 @@ rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, if (IS_ZEBRA_DEBUG_KERNEL) { if (gate) - zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib", - inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("route %s vrf %u via %s ifindex %d type %d " + "doesn't exist in rib", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN), ifindex, type); else - zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib", - inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN), - p->prefixlen, + zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib", + prefix2str (p, buf1, sizeof(buf1)), vrf_id, ifindex, type); } @@ -3509,6 +3505,7 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si) rib->instance = 0; rib->distance = si->distance; rib->metric = 0; + rib->vrf_id = VRF_DEFAULT; rib->table = zebrad.rtm_table_default; rib->nexthop_num = 0; rib->tag = si->tag; @@ -3644,16 +3641,15 @@ static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si) int static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, const char *ifname, u_char flags, u_short tag, - u_char distance, u_int32_t vrf_id) + u_char distance, vrf_id_t vrf_id) { struct route_node *rn; struct static_ipv6 *si; struct static_ipv6 *pp; struct static_ipv6 *cp; - struct route_table *stable; + struct zebra_vrf *zvrf = vrf_info_get (vrf_id); + struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST]; - /* Lookup table. */ - stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! stable) return -1; @@ -3734,7 +3730,7 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, int static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, const char *ifname, u_short tag, u_char distance, - u_int32_t vrf_id) + vrf_id_t vrf_id) { struct route_node *rn; struct static_ipv6 *si; @@ -3788,13 +3784,13 @@ static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, /* RIB update function. */ void -rib_update_static (void) +rib_update_static (vrf_id_t vrf_id) { struct route_node *rn; struct route_table *table; struct rib *rib, *next; - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB_SAFE (rn, rib, next) @@ -3804,7 +3800,7 @@ rib_update_static (void) break; } - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB_SAFE (rn, rib, next) @@ -3817,18 +3813,18 @@ rib_update_static (void) /* RIB update function. */ void -rib_update (void) +rib_update (vrf_id_t vrf_id) { struct route_node *rn; struct route_table *table; - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) if (rnode_to_ribs (rn)) rib_queue_add (&zebrad, rn); - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) if (rnode_to_ribs (rn)) @@ -3861,8 +3857,15 @@ rib_weed_table (struct route_table *table) void rib_weed_tables (void) { - rib_weed_table (zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)); - rib_weed_table (zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT)); + vrf_iter_t iter; + struct zebra_vrf *zvrf; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + if ((zvrf = vrf_iter2info (iter)) != NULL) + { + rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]); + rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); + } } /* Delete self installed routes after zebra is relaunched. */ @@ -3895,8 +3898,15 @@ rib_sweep_table (struct route_table *table) void rib_sweep_route (void) { - rib_sweep_table (zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)); - rib_sweep_table (zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT)); + vrf_iter_t iter; + struct zebra_vrf *zvrf; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + if ((zvrf = vrf_iter2info (iter)) != NULL) + { + rib_sweep_table (zvrf->table[AFI_IP][SAFI_UNICAST]); + rib_sweep_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); + } } /* Remove specific by protocol routes from 'table'. */ @@ -3928,8 +3938,16 @@ rib_score_proto_table (u_char proto, u_short instance, struct route_table *table unsigned long rib_score_proto (u_char proto, u_short instance) { - return rib_score_proto_table (proto, instance, zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)) - +rib_score_proto_table (proto, instance, zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT)); + vrf_iter_t iter; + struct zebra_vrf *zvrf; + unsigned long cnt = 0; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + if ((zvrf = vrf_iter2info (iter)) != NULL) + cnt += rib_score_proto_table (proto, instance, zvrf->table[AFI_IP][SAFI_UNICAST]) + +rib_score_proto_table (proto, instance, zvrf->table[AFI_IP6][SAFI_UNICAST]); + + return cnt; } /* Close RIB and clean up kernel routes. */ @@ -3957,14 +3975,21 @@ rib_close_table (struct route_table *table) void rib_close (void) { - struct listnode *node, *nnode; + vrf_iter_t iter; + struct zebra_vrf *zvrf; + struct listnode *node; struct interface *ifp; - rib_close_table (zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT)); - rib_close_table (zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT)); - - for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp)) - if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp); + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) != NULL) + { + rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]); + rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); + } + for (ALL_LIST_ELEMENTS_RO (vrf_iter2iflist (iter), node, ifp)) + if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp); + } } /* Routing information base initialize. */ diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 9728a28c0e..1a50ab6990 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -961,7 +961,8 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn) case NEXTHOP_TYPE_IPV4_IFINDEX: vty_out (vty, " %s", inet_ntoa (nexthop->gate.ipv4)); if (nexthop->ifindex) - vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex)); + vty_out (vty, ", via %s", + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); break; #ifdef HAVE_IPV6 case NEXTHOP_TYPE_IPV6: @@ -972,12 +973,13 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn) if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME) vty_out (vty, ", %s", nexthop->ifname); else if (nexthop->ifindex) - vty_out (vty, ", via %s", ifindex2ifname (nexthop->ifindex)); + vty_out (vty, ", via %s", + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); break; #endif /* HAVE_IPV6 */ case NEXTHOP_TYPE_IFINDEX: vty_out (vty, " directly connected, %s", - ifindex2ifname (nexthop->ifindex)); + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); break; case NEXTHOP_TYPE_IFNAME: vty_out (vty, " directly connected, %s", nexthop->ifname); @@ -1073,7 +1075,8 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib) case NEXTHOP_TYPE_IPV4_IFINDEX: vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4)); if (nexthop->ifindex) - vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex)); + vty_out (vty, ", %s", + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); break; #ifdef HAVE_IPV6 case NEXTHOP_TYPE_IPV6: @@ -1084,13 +1087,14 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib) if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME) vty_out (vty, ", %s", nexthop->ifname); else if (nexthop->ifindex) - vty_out (vty, ", %s", ifindex2ifname (nexthop->ifindex)); + vty_out (vty, ", %s", + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); break; #endif /* HAVE_IPV6 */ case NEXTHOP_TYPE_IFINDEX: vty_out (vty, " is directly connected, %s", - ifindex2ifname (nexthop->ifindex)); + ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); break; case NEXTHOP_TYPE_IFNAME: vty_out (vty, " is directly connected, %s", nexthop->ifname); diff --git a/zebra/zserv.c b/zebra/zserv.c index ba3c59aafb..052c797f8b 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -37,6 +37,7 @@ #include "network.h" #include "buffer.h" #include "nexthop.h" +#include "vrf.h" #include "zebra/zserv.h" #include "zebra/router-id.h" @@ -643,7 +644,7 @@ zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr) struct nexthop *nexthop; /* Lookup nexthop. */ - rib = rib_match_ipv6 (addr); + rib = rib_match_ipv6 (addr, VRF_DEFAULT); /* Get output stream. */ s = client->obuf; @@ -710,7 +711,7 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr) struct nexthop *nexthop; /* Lookup nexthop. */ - rib = rib_match_ipv4 (addr); + rib = rib_match_ipv4 (addr, VRF_DEFAULT); /* Get output stream. */ s = client->obuf; @@ -892,7 +893,7 @@ zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p) struct nexthop *nexthop; /* Lookup nexthop. */ - rib = rib_lookup_ipv4 (p); + rib = rib_lookup_ipv4 (p, VRF_DEFAULT); /* Get output stream. */ s = client->obuf; @@ -1076,6 +1077,9 @@ zread_ipv4_add (struct zserv *client, u_short length) p.prefixlen = stream_getc (s); stream_get (&p.prefix, s, PSIZE (p.prefixlen)); + /* VRF ID */ + rib->vrf_id = VRF_DEFAULT; + /* Nexthop parse. */ if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP)) { @@ -1231,7 +1235,7 @@ zread_ipv4_delete (struct zserv *client, u_short length) api.tag = 0; rib_delete_ipv4 (api.type, api.instance, api.flags, &p, nexthop_p, ifindex, - client->rtm_table, api.safi); + VRF_DEFAULT, client->rtm_table, api.safi); client->v4_route_del_cnt++; return 0; } @@ -1505,6 +1509,7 @@ zread_ipv6_add (struct zserv *client, u_short length) /* Table */ rib->table=zebrad.rtm_table_default; + rib->vrf_id = VRF_DEFAULT; ret = rib_add_ipv6_multipath ((struct prefix *)&p, rib, safi, ifindex); /* Stats */ if (ret > 0) @@ -1584,9 +1589,11 @@ zread_ipv6_delete (struct zserv *client, u_short length) api.tag = 0; if (IN6_IS_ADDR_UNSPECIFIED (&nexthop)) - rib_delete_ipv6 (api.type, api.instance, api.flags, &p, NULL, ifindex, client->rtm_table, api.safi); + rib_delete_ipv6 (api.type, api.instance, api.flags, &p, NULL, ifindex, + VRF_DEFAULT, client->rtm_table, api.safi); else - rib_delete_ipv6 (api.type, api.instance, api.flags, &p, &nexthop, ifindex, client->rtm_table, api.safi); + rib_delete_ipv6 (api.type, api.instance, api.flags, &p, &nexthop, ifindex, + VRF_DEFAULT, client->rtm_table, api.safi); client->v6_route_del_cnt++; return 0; From af41b63a5e3ab98812edae2b7c1a2d9a3091e5e7 Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:40:03 +0200 Subject: [PATCH 17/27] zebra: show routes in a specified VRF or all VRFs The present "show ip[v6] [m]route [xxx]" and "show ip rpf [xxx]" commands now show routes only in the default VRF. A new option is introduced to show routes in a specified VRF: show ip[v6] [m]route [xxx] vrf N show ip rpf [xxx] vrf N and a new option is used to show routes through all VRFs: show ip[v6] [m]route [xxx] vrf all show ip rpf [xxx] vrf all Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN [DL: conflicts resolved] Signed-off-by: David Lamparter Conflicts: zebra/zebra_vty.c Conflicts: nhrpd/nhrp_interface.c zebra/zebra_rib.c zebra/zebra_rnh_null.c zebra/zebra_vty.c --- zebra/zebra_rnh_null.c | 4 +- zebra/zebra_vty.c | 1107 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 1029 insertions(+), 82 deletions(-) diff --git a/zebra/zebra_rnh_null.c b/zebra/zebra_rnh_null.c index 5bd00a3ecd..58fba418af 100644 --- a/zebra/zebra_rnh_null.c +++ b/zebra/zebra_rnh_null.c @@ -6,11 +6,11 @@ int zebra_rnh_ip_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) { 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) {} diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 1a50ab6990..a9fb278aab 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -94,9 +94,9 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, return CMD_WARNING; } if (add_cmd) - static_add_ipv4 (&p, NULL, NULL, ZEBRA_FLAG_BLACKHOLE, tag, distance, 0); + static_add_ipv4 (&p, NULL, NULL, ZEBRA_FLAG_BLACKHOLE, tag, distance, VRF_DEFAULT); else - static_delete_ipv4 (&p, NULL, NULL, tag, distance, 0); + static_delete_ipv4 (&p, NULL, NULL, tag, distance, VRF_DEFAULT); return CMD_SUCCESS; } @@ -120,9 +120,9 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, if (gate_str == NULL) { if (add_cmd) - static_add_ipv4 (&p, NULL, NULL, flag, tag, distance, 0); + static_add_ipv4 (&p, NULL, NULL, flag, tag, distance, VRF_DEFAULT); else - static_delete_ipv4 (&p, NULL, NULL, tag, distance, 0); + static_delete_ipv4 (&p, NULL, NULL, tag, distance, VRF_DEFAULT); return CMD_SUCCESS; } @@ -136,9 +136,9 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, ifname = gate_str; if (add_cmd) - static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, flag, tag, distance, 0); + static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, flag, tag, distance, VRF_DEFAULT); else - static_delete_ipv4 (&p, ifname ? NULL : &gate, ifname, tag, distance, 0); + static_delete_ipv4 (&p, ifname ? NULL : &gate, ifname, tag, distance, VRF_DEFAULT); return CMD_SUCCESS; } @@ -906,6 +906,7 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn) vty_out (vty, ", distance %u, metric %u", rib->distance, rib->metric); if (rib->tag) vty_out (vty, ", tag %d", rib->tag); + vty_out (vty, ", vrf %u", rib->vrf_id); if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) vty_out (vty, ", best"); if (rib->refcnt) @@ -1062,6 +1063,9 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib) && rib->type != ZEBRA_ROUTE_KERNEL) len += vty_out (vty, " [%d/%d]", rib->distance, rib->metric); + + if (rib->vrf_id != VRF_DEFAULT) + len += vty_out (vty, " [vrf %u]", rib->vrf_id); } else vty_out (vty, " %c%*c", @@ -1331,6 +1335,14 @@ DEFUN (show_ip_route_tag, return CMD_SUCCESS; } +ALIAS (show_ip_route, + show_ip_route_vrf_cmd, + "show ip route " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + VRF_CMD_HELP_STR) + DEFUN (show_ip_route_prefix_longer, show_ip_route_prefix_longer_cmd, "show ip route A.B.C.D/M longer-prefixes", @@ -1346,6 +1358,7 @@ DEFUN (show_ip_route_prefix_longer, struct prefix p; int ret; int first = 1; + vrf_id_t vrf_id = VRF_DEFAULT; ret = str2prefix (argv[0], &p); if (! ret) @@ -1353,8 +1366,11 @@ DEFUN (show_ip_route_prefix_longer, vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE); return CMD_WARNING; } - - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) return CMD_SUCCESS; @@ -1373,6 +1389,16 @@ DEFUN (show_ip_route_prefix_longer, return CMD_SUCCESS; } +ALIAS (show_ip_route_prefix_longer, + show_ip_route_prefix_longer_vrf_cmd, + "show ip route A.B.C.D/M longer-prefixes " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + "Show route matching the specified Network/Mask pair only\n" + VRF_CMD_HELP_STR) + DEFUN (show_ip_route_supernets, show_ip_route_supernets_cmd, "show ip route supernets-only", @@ -1384,10 +1410,14 @@ DEFUN (show_ip_route_supernets, struct route_table *table; struct route_node *rn; struct rib *rib; - u_int32_t addr; + u_int32_t addr; int first = 1; + vrf_id_t vrf_id = VRF_DEFAULT; - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (argc > 0) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) return CMD_SUCCESS; @@ -1399,7 +1429,7 @@ DEFUN (show_ip_route_supernets, if ((IN_CLASSC (addr) && rn->p.prefixlen < 24) || (IN_CLASSB (addr) && rn->p.prefixlen < 16) - || (IN_CLASSA (addr) && rn->p.prefixlen < 8)) + || (IN_CLASSA (addr) && rn->p.prefixlen < 8)) { if (first) { @@ -1412,6 +1442,15 @@ DEFUN (show_ip_route_supernets, return CMD_SUCCESS; } +ALIAS (show_ip_route_supernets, + show_ip_route_supernets_vrf_cmd, + "show ip route supernets-only " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "Show supernet entries only\n" + VRF_CMD_HELP_STR) + DEFUN (show_ip_route_protocol, show_ip_route_protocol_cmd, "show ip route " QUAGGA_IP_REDIST_STR_ZEBRA, @@ -1425,6 +1464,7 @@ DEFUN (show_ip_route_protocol, struct route_node *rn; struct rib *rib; int first = 1; + vrf_id_t vrf_id = VRF_DEFAULT; type = proto_redistnum (AFI_IP, argv[0]); if (type < 0) @@ -1432,8 +1472,11 @@ DEFUN (show_ip_route_protocol, vty_out (vty, "Unknown route type%s", VTY_NEWLINE); return CMD_WARNING; } - - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) return CMD_SUCCESS; @@ -1452,6 +1495,15 @@ DEFUN (show_ip_route_protocol, return CMD_SUCCESS; } +ALIAS (show_ip_route_protocol, + show_ip_route_protocol_vrf_cmd, + "show ip route " QUAGGA_IP_REDIST_STR_ZEBRA " " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + QUAGGA_IP_REDIST_HELP_STR_ZEBRA + VRF_CMD_HELP_STR) + DEFUN (show_ip_route_ospf_instance, show_ip_route_ospf_instance_cmd, "show ip route ospf <1-65535>", @@ -1500,6 +1552,7 @@ DEFUN (show_ip_route_addr, struct prefix_ipv4 p; struct route_table *table; struct route_node *rn; + vrf_id_t vrf_id = VRF_DEFAULT; ret = str2prefix_ipv4 (argv[0], &p); if (ret <= 0) @@ -1508,7 +1561,10 @@ DEFUN (show_ip_route_addr, return CMD_WARNING; } - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) return CMD_SUCCESS; @@ -1526,6 +1582,15 @@ DEFUN (show_ip_route_addr, return CMD_SUCCESS; } +ALIAS (show_ip_route_addr, + show_ip_route_addr_vrf_cmd, + "show ip route A.B.C.D " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "Network in the IP routing table to display\n" + VRF_CMD_HELP_STR) + DEFUN (show_ip_route_prefix, show_ip_route_prefix_cmd, "show ip route A.B.C.D/M", @@ -1538,6 +1603,7 @@ DEFUN (show_ip_route_prefix, struct prefix_ipv4 p; struct route_table *table; struct route_node *rn; + vrf_id_t vrf_id = VRF_DEFAULT; ret = str2prefix_ipv4 (argv[0], &p); if (ret <= 0) @@ -1546,7 +1612,10 @@ DEFUN (show_ip_route_prefix, return CMD_WARNING; } - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) return CMD_SUCCESS; @@ -1564,6 +1633,15 @@ DEFUN (show_ip_route_prefix, return CMD_SUCCESS; } +ALIAS (show_ip_route_prefix, + show_ip_route_prefix_vrf_cmd, + "show ip route A.B.C.D/M " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + VRF_CMD_HELP_STR) + static void vty_show_ip_route_summary (struct vty *vty, struct route_table *table) { @@ -1600,8 +1678,10 @@ vty_show_ip_route_summary (struct vty *vty, struct route_table *table) } } - vty_out (vty, "%-20s %-20s %-20s %s", - "Route Source", "Routes", "FIB", VTY_NEWLINE); + vty_out (vty, "%-20s %-20s %s (vrf %u)%s", + "Route Source", "Routes", "FIB", + ((rib_table_info_t *)table->info)->zvrf->vrf_id, + VTY_NEWLINE); for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { @@ -1626,6 +1706,7 @@ vty_show_ip_route_summary (struct vty *vty, struct route_table *table) vty_out (vty, "------%s", VTY_NEWLINE); vty_out (vty, "%-20s %-20d %-20d %s", "Totals", rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL], VTY_NEWLINE); + vty_out (vty, "%s", VTY_NEWLINE); } /* @@ -1678,8 +1759,10 @@ vty_show_ip_route_summary_prefix (struct vty *vty, struct route_table *table) } } - vty_out (vty, "%-20s %-20s %-20s %s", - "Route Source", "Prefix Routes", "FIB", VTY_NEWLINE); + vty_out (vty, "%-20s %-20s %s (vrf %u)%s", + "Route Source", "Prefix Routes", "FIB", + ((rib_table_info_t *)table->info)->zvrf->vrf_id, + VTY_NEWLINE); for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { @@ -1704,6 +1787,7 @@ vty_show_ip_route_summary_prefix (struct vty *vty, struct route_table *table) vty_out (vty, "------%s", VTY_NEWLINE); vty_out (vty, "%-20s %-20d %-20d %s", "Totals", rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL], VTY_NEWLINE); + vty_out (vty, "%s", VTY_NEWLINE); } /* Show route summary. */ @@ -1716,8 +1800,12 @@ DEFUN (show_ip_route_summary, "Summary of all routes\n") { struct route_table *table; + vrf_id_t vrf_id = VRF_DEFAULT; - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (argc > 0) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) return CMD_SUCCESS; @@ -1726,6 +1814,15 @@ DEFUN (show_ip_route_summary, return CMD_SUCCESS; } +ALIAS (show_ip_route_summary, + show_ip_route_summary_vrf_cmd, + "show ip route summary " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "Summary of all routes\n" + VRF_CMD_HELP_STR) + /* Show route summary prefix. */ DEFUN (show_ip_route_summary_prefix, show_ip_route_summary_prefix_cmd, @@ -1737,8 +1834,12 @@ DEFUN (show_ip_route_summary_prefix, "Prefix routes\n") { struct route_table *table; + vrf_id_t vrf_id = VRF_DEFAULT; - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (argc > 0) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (! table) return CMD_SUCCESS; @@ -1747,61 +1848,380 @@ DEFUN (show_ip_route_summary_prefix, return CMD_SUCCESS; } +ALIAS (show_ip_route_summary_prefix, + show_ip_route_summary_prefix_vrf_cmd, + "show ip route summary prefix " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "Summary of all routes\n" + "Prefix routes\n" + VRF_CMD_HELP_STR) + +DEFUN (show_ip_route_vrf_all, + show_ip_route_vrf_all_cmd, + "show ip route " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + VRF_ALL_CMD_HELP_STR) +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + int first = 1; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) + continue; + + /* Show all IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + } + + return CMD_SUCCESS; +} + +DEFUN (show_ip_route_prefix_longer_vrf_all, + show_ip_route_prefix_longer_vrf_all_cmd, + "show ip route A.B.C.D/M longer-prefixes " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + "Show route matching the specified Network/Mask pair only\n" + VRF_ALL_CMD_HELP_STR) +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + struct prefix p; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + int ret; + int first = 1; + + ret = str2prefix (argv[0], &p); + if (! ret) + { + vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) + continue; + + /* Show matched type IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + if (prefix_match (&p, &rn->p)) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + } + + return CMD_SUCCESS; +} + +DEFUN (show_ip_route_supernets_vrf_all, + show_ip_route_supernets_vrf_all_cmd, + "show ip route supernets-only " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "Show supernet entries only\n" + VRF_ALL_CMD_HELP_STR) +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + u_int32_t addr; + int first = 1; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) + continue; + + /* Show matched type IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + { + addr = ntohl (rn->p.u.prefix4.s_addr); + + if ((IN_CLASSC (addr) && rn->p.prefixlen < 24) + || (IN_CLASSB (addr) && rn->p.prefixlen < 16) + || (IN_CLASSA (addr) && rn->p.prefixlen < 8)) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + } + } + + return CMD_SUCCESS; +} + +DEFUN (show_ip_route_protocol_vrf_all, + show_ip_route_protocol_vrf_all_cmd, + "show ip route " QUAGGA_IP_REDIST_STR_ZEBRA " " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + QUAGGA_IP_REDIST_HELP_STR_ZEBRA + VRF_ALL_CMD_HELP_STR) +{ + int type; + struct route_table *table; + struct route_node *rn; + struct rib *rib; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + int first = 1; + + type = proto_redistnum (AFI_IP, argv[0]); + if (type < 0) + { + vty_out (vty, "Unknown route type%s", VTY_NEWLINE); + return CMD_WARNING; + } + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) + continue; + + /* Show matched type IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + if (rib->type == type) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + } + + return CMD_SUCCESS; +} + +DEFUN (show_ip_route_addr_vrf_all, + show_ip_route_addr_vrf_all_cmd, + "show ip route A.B.C.D " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "Network in the IP routing table to display\n" + VRF_ALL_CMD_HELP_STR) +{ + int ret; + struct prefix_ipv4 p; + struct route_table *table; + struct route_node *rn; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + + ret = str2prefix_ipv4 (argv[0], &p); + if (ret <= 0) + { + vty_out (vty, "%% Malformed IPv4 address%s", VTY_NEWLINE); + return CMD_WARNING; + } + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) + continue; + + rn = route_node_match (table, (struct prefix *) &p); + if (! rn) + continue; + + vty_show_ip_route_detail (vty, rn); + + route_unlock_node (rn); + } + + return CMD_SUCCESS; +} + +DEFUN (show_ip_route_prefix_vrf_all, + show_ip_route_prefix_vrf_all_cmd, + "show ip route A.B.C.D/M " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + VRF_ALL_CMD_HELP_STR) +{ + int ret; + struct prefix_ipv4 p; + struct route_table *table; + struct route_node *rn; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + + ret = str2prefix_ipv4 (argv[0], &p); + if (ret <= 0) + { + vty_out (vty, "%% Malformed IPv4 address%s", VTY_NEWLINE); + return CMD_WARNING; + } + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) + continue; + + rn = route_node_match (table, (struct prefix *) &p); + if (! rn) + continue; + if (rn->p.prefixlen != p.prefixlen) + { + route_unlock_node (rn); + continue; + } + + vty_show_ip_route_detail (vty, rn); + + route_unlock_node (rn); + } + + return CMD_SUCCESS; +} + +DEFUN (show_ip_route_summary_vrf_all, + show_ip_route_summary_vrf_all_cmd, + "show ip route summary " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "Summary of all routes\n" + VRF_ALL_CMD_HELP_STR) +{ + struct zebra_vrf *zvrf; + vrf_iter_t iter; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + if ((zvrf = vrf_iter2info (iter)) != NULL) + vty_show_ip_route_summary (vty, zvrf->table[AFI_IP][SAFI_UNICAST]); + + return CMD_SUCCESS; +} + +DEFUN (show_ip_route_summary_prefix_vrf_all, + show_ip_route_summary_prefix_vrf_all_cmd, + "show ip route summary prefix " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + "Summary of all routes\n" + "Prefix routes\n" + VRF_ALL_CMD_HELP_STR) +{ + struct zebra_vrf *zvrf; + vrf_iter_t iter; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + if ((zvrf = vrf_iter2info (iter)) != NULL) + vty_show_ip_route_summary_prefix (vty, zvrf->table[AFI_IP][SAFI_UNICAST]); + + return CMD_SUCCESS; +} + /* Write IPv4 static route configuration. */ static int -static_config_ipv4 (struct vty *vty) +static_config_ipv4 (struct vty *vty, safi_t safi, const char *cmd) { struct route_node *rn; struct static_ipv4 *si; struct route_table *stable; + struct zebra_vrf *zvrf; + vrf_iter_t iter; int write; write = 0; - /* Lookup table. */ - stable = zebra_vrf_static_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); - if (! stable) - return -1; + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (stable = zvrf->stable[AFI_IP][safi]) == NULL) + continue; - for (rn = route_top (stable); rn; rn = route_next (rn)) - for (si = rn->info; si; si = si->next) - { - vty_out (vty, "ip route %s/%d", inet_ntoa (rn->p.u.prefix4), - rn->p.prefixlen); - - switch (si->type) + for (rn = route_top (stable); rn; rn = route_next (rn)) + for (si = rn->info; si; si = si->next) { - case STATIC_IPV4_GATEWAY: - vty_out (vty, " %s", inet_ntoa (si->gate.ipv4)); - break; - case STATIC_IPV4_IFNAME: - vty_out (vty, " %s", si->gate.ifname); - break; - case STATIC_IPV4_BLACKHOLE: - vty_out (vty, " Null0"); - break; + vty_out (vty, "%s %s/%d", cmd, inet_ntoa (rn->p.u.prefix4), + rn->p.prefixlen); + + switch (si->type) + { + case STATIC_IPV4_GATEWAY: + vty_out (vty, " %s", inet_ntoa (si->gate.ipv4)); + break; + case STATIC_IPV4_IFNAME: + vty_out (vty, " %s", si->gate.ifname); + break; + case STATIC_IPV4_BLACKHOLE: + vty_out (vty, " Null0"); + break; + } + + /* flags are incompatible with STATIC_IPV4_BLACKHOLE */ + if (si->type != STATIC_IPV4_BLACKHOLE) + { + if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT)) + vty_out (vty, " %s", "reject"); + + if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE)) + vty_out (vty, " %s", "blackhole"); + } + + if (si->tag) + vty_out (vty, " tag %d", si->tag); + + if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) + vty_out (vty, " %d", si->distance); + + vty_out (vty, "%s", VTY_NEWLINE); + + write = 1; } - - /* flags are incompatible with STATIC_IPV4_BLACKHOLE */ - if (si->type != STATIC_IPV4_BLACKHOLE) - { - if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, " %s", "reject"); - - if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, " %s", "blackhole"); - } - - if (si->tag) - vty_out (vty, " tag %d", si->tag); - - if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) - vty_out (vty, " %d", si->distance); - - vty_out (vty, "%s", VTY_NEWLINE); - - write = 1; - } + } return write; } @@ -1820,8 +2240,12 @@ DEFUN (show_ip_mroute, struct route_node *rn; struct rib *rib; int first = 1; + vrf_id_t vrf_id = VRF_DEFAULT; - table = zebra_vrf_table (AFI_IP, SAFI_MULTICAST, VRF_DEFAULT); + if (argc > 0) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + + table = zebra_vrf_table (AFI_IP, SAFI_MULTICAST, vrf_id); if (! table) return CMD_SUCCESS; @@ -1839,6 +2263,50 @@ DEFUN (show_ip_mroute, return CMD_SUCCESS; } +ALIAS (show_ip_mroute, + show_ip_mroute_vrf_cmd, + "show ip mroute " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP Multicast routing table\n" + VRF_CMD_HELP_STR) + +DEFUN (show_ip_mroute_vrf_all, + show_ip_mroute_vrf_all_cmd, + "show ip mroute " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IP Multicast routing table\n" + VRF_ALL_CMD_HELP_STR) +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + int first = 1; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) + continue; + + /* Show all IPv4 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + } + + return CMD_SUCCESS; +} #ifdef HAVE_IPV6 /* General fucntion for IPv6 static route. */ @@ -1854,7 +2322,6 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, struct in6_addr *gate = NULL; struct in6_addr gate_addr; u_char type = 0; - int table = 0; u_char flag = 0; u_short tag = 0; @@ -1926,9 +2393,9 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, } if (add_cmd) - static_add_ipv6 (&p, type, gate, ifname, flag, tag, distance, table); + static_add_ipv6 (&p, type, gate, ifname, flag, tag, distance, VRF_DEFAULT); else - static_delete_ipv6 (&p, type, gate, ifname, tag, distance, table); + static_delete_ipv6 (&p, type, gate, ifname, tag, distance, VRF_DEFAULT); return CMD_SUCCESS; } @@ -2617,8 +3084,12 @@ DEFUN (show_ipv6_route, struct route_node *rn; struct rib *rib; int first = 1; + vrf_id_t vrf_id = VRF_DEFAULT; - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + if (argc > 0) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) return CMD_SUCCESS; @@ -2675,6 +3146,14 @@ DEFUN (show_ipv6_route_tag, return CMD_SUCCESS; } +ALIAS (show_ipv6_route, + show_ipv6_route_vrf_cmd, + "show ipv6 route " VRF_CMD_STR, + SHOW_STR + IP_STR + "IPv6 routing table\n" + VRF_CMD_HELP_STR) + DEFUN (show_ipv6_route_prefix_longer, show_ipv6_route_prefix_longer_cmd, "show ipv6 route X:X::X:X/M longer-prefixes", @@ -2690,10 +3169,7 @@ DEFUN (show_ipv6_route_prefix_longer, struct prefix p; int ret; int first = 1; - - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); - if (! table) - return CMD_SUCCESS; + vrf_id_t vrf_id = VRF_DEFAULT; ret = str2prefix (argv[0], &p); if (! ret) @@ -2702,6 +3178,13 @@ DEFUN (show_ipv6_route_prefix_longer, return CMD_WARNING; } + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); + if (! table) + return CMD_SUCCESS; + /* Show matched type IPv6 routes. */ for (rn = route_top (table); rn; rn = route_next (rn)) RNODE_FOREACH_RIB (rn, rib) @@ -2717,6 +3200,16 @@ DEFUN (show_ipv6_route_prefix_longer, return CMD_SUCCESS; } +ALIAS (show_ipv6_route_prefix_longer, + show_ipv6_route_prefix_longer_vrf_cmd, + "show ipv6 route X:X::X:X/M longer-prefixes " VRF_CMD_STR, + SHOW_STR + IP_STR + "IPv6 routing table\n" + "IPv6 prefix\n" + "Show route matching the specified Network/Mask pair only\n" + VRF_CMD_HELP_STR) + DEFUN (show_ipv6_route_protocol, show_ipv6_route_protocol_cmd, "show ipv6 route " QUAGGA_IP6_REDIST_STR_ZEBRA, @@ -2730,6 +3223,7 @@ DEFUN (show_ipv6_route_protocol, struct route_node *rn; struct rib *rib; int first = 1; + vrf_id_t vrf_id = VRF_DEFAULT; type = proto_redistnum (AFI_IP6, argv[0]); if (type < 0) @@ -2737,8 +3231,11 @@ DEFUN (show_ipv6_route_protocol, vty_out (vty, "Unknown route type%s", VTY_NEWLINE); return CMD_WARNING; } - - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) return CMD_SUCCESS; @@ -2757,6 +3254,15 @@ DEFUN (show_ipv6_route_protocol, return CMD_SUCCESS; } +ALIAS (show_ipv6_route_protocol, + show_ipv6_route_protocol_vrf_cmd, + "show ipv6 route " QUAGGA_IP6_REDIST_STR_ZEBRA " " VRF_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + QUAGGA_IP6_REDIST_HELP_STR_ZEBRA + VRF_CMD_HELP_STR) + DEFUN (show_ipv6_route_addr, show_ipv6_route_addr_cmd, "show ipv6 route X:X::X:X", @@ -2769,6 +3275,7 @@ DEFUN (show_ipv6_route_addr, struct prefix_ipv6 p; struct route_table *table; struct route_node *rn; + vrf_id_t vrf_id = VRF_DEFAULT; ret = str2prefix_ipv6 (argv[0], &p); if (ret <= 0) @@ -2777,7 +3284,10 @@ DEFUN (show_ipv6_route_addr, return CMD_WARNING; } - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) return CMD_SUCCESS; @@ -2795,6 +3305,15 @@ DEFUN (show_ipv6_route_addr, return CMD_SUCCESS; } +ALIAS (show_ipv6_route_addr, + show_ipv6_route_addr_vrf_cmd, + "show ipv6 route X:X::X:X " VRF_CMD_STR, + SHOW_STR + IP_STR + "IPv6 routing table\n" + "IPv6 Address\n" + VRF_CMD_HELP_STR) + DEFUN (show_ipv6_route_prefix, show_ipv6_route_prefix_cmd, "show ipv6 route X:X::X:X/M", @@ -2807,6 +3326,7 @@ DEFUN (show_ipv6_route_prefix, struct prefix_ipv6 p; struct route_table *table; struct route_node *rn; + vrf_id_t vrf_id = VRF_DEFAULT; ret = str2prefix_ipv6 (argv[0], &p); if (ret <= 0) @@ -2815,7 +3335,10 @@ DEFUN (show_ipv6_route_prefix, return CMD_WARNING; } - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) return CMD_SUCCESS; @@ -2833,6 +3356,15 @@ DEFUN (show_ipv6_route_prefix, return CMD_SUCCESS; } +ALIAS (show_ipv6_route_prefix, + show_ipv6_route_prefix_vrf_cmd, + "show ipv6 route X:X::X:X/M " VRF_CMD_STR, + SHOW_STR + IP_STR + "IPv6 routing table\n" + "IPv6 prefix\n" + VRF_CMD_HELP_STR) + /* Show route summary. */ DEFUN (show_ipv6_route_summary, show_ipv6_route_summary_cmd, @@ -2843,8 +3375,12 @@ DEFUN (show_ipv6_route_summary, "Summary of all IPv6 routes\n") { struct route_table *table; + vrf_id_t vrf_id = VRF_DEFAULT; - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + if (argc > 0) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) return CMD_SUCCESS; @@ -2853,6 +3389,15 @@ DEFUN (show_ipv6_route_summary, return CMD_SUCCESS; } +ALIAS (show_ipv6_route_summary, + show_ipv6_route_summary_vrf_cmd, + "show ipv6 route summary " VRF_CMD_STR, + SHOW_STR + IP_STR + "IPv6 routing table\n" + "Summary of all IPv6 routes\n" + VRF_CMD_HELP_STR) + /* Show ipv6 route summary prefix. */ DEFUN (show_ipv6_route_summary_prefix, show_ipv6_route_summary_prefix_cmd, @@ -2864,8 +3409,12 @@ DEFUN (show_ipv6_route_summary_prefix, "Prefix routes\n") { struct route_table *table; + vrf_id_t vrf_id = VRF_DEFAULT; - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + if (argc > 0) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (! table) return CMD_SUCCESS; @@ -2874,6 +3423,16 @@ DEFUN (show_ipv6_route_summary_prefix, return CMD_SUCCESS; } +ALIAS (show_ipv6_route_summary_prefix, + show_ipv6_route_summary_prefix_vrf_cmd, + "show ipv6 route summary prefix " VRF_CMD_STR, + SHOW_STR + IP_STR + "IPv6 routing table\n" + "Summary of all IPv6 routes\n" + "Prefix routes\n" + VRF_CMD_HELP_STR) + /* * Show IPv6 mroute command.Used to dump * the Multicast routing table. @@ -2890,8 +3449,12 @@ DEFUN (show_ipv6_mroute, struct route_node *rn; struct rib *rib; int first = 1; + vrf_id_t vrf_id = VRF_DEFAULT; - table = zebra_vrf_table (AFI_IP6, SAFI_MULTICAST, VRF_DEFAULT); + if (argc > 0) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + + table = zebra_vrf_table (AFI_IP6, SAFI_MULTICAST, vrf_id); if (! table) return CMD_SUCCESS; @@ -2909,6 +3472,310 @@ DEFUN (show_ipv6_mroute, return CMD_SUCCESS; } +ALIAS (show_ipv6_mroute, + show_ipv6_mroute_vrf_cmd, + "show ipv6 mroute " VRF_CMD_STR, + SHOW_STR + IP_STR + "IPv6 Multicast routing table\n" + VRF_CMD_HELP_STR) + +DEFUN (show_ipv6_route_vrf_all, + show_ipv6_route_vrf_all_cmd, + "show ipv6 route " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IPv6 routing table\n" + VRF_ALL_CMD_HELP_STR) +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + int first = 1; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) + continue; + + /* Show all IPv6 route. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V6_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + } + + return CMD_SUCCESS; +} + +DEFUN (show_ipv6_route_prefix_longer_vrf_all, + show_ipv6_route_prefix_longer_vrf_all_cmd, + "show ipv6 route X:X::X:X/M longer-prefixes " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IPv6 routing table\n" + "IPv6 prefix\n" + "Show route matching the specified Network/Mask pair only\n" + VRF_ALL_CMD_HELP_STR) +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + struct prefix p; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + int ret; + int first = 1; + + ret = str2prefix (argv[0], &p); + if (! ret) + { + vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) + continue; + + /* Show matched type IPv6 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + if (prefix_match (&p, &rn->p)) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V6_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + } + + return CMD_SUCCESS; +} + +DEFUN (show_ipv6_route_protocol_vrf_all, + show_ipv6_route_protocol_vrf_all_cmd, + "show ipv6 route " QUAGGA_IP6_REDIST_STR_ZEBRA " " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IP routing table\n" + QUAGGA_IP6_REDIST_HELP_STR_ZEBRA + VRF_ALL_CMD_HELP_STR) +{ + int type; + struct route_table *table; + struct route_node *rn; + struct rib *rib; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + int first = 1; + + type = proto_redistnum (AFI_IP6, argv[0]); + if (type < 0) + { + vty_out (vty, "Unknown route type%s", VTY_NEWLINE); + return CMD_WARNING; + } + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) + continue; + + /* Show matched type IPv6 routes. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + if (rib->type == type) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V6_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + } + + return CMD_SUCCESS; +} + +DEFUN (show_ipv6_route_addr_vrf_all, + show_ipv6_route_addr_vrf_all_cmd, + "show ipv6 route X:X::X:X " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IPv6 routing table\n" + "IPv6 Address\n" + VRF_ALL_CMD_HELP_STR) +{ + int ret; + struct prefix_ipv6 p; + struct route_table *table; + struct route_node *rn; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + + ret = str2prefix_ipv6 (argv[0], &p); + if (ret <= 0) + { + vty_out (vty, "Malformed IPv6 address%s", VTY_NEWLINE); + return CMD_WARNING; + } + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) + continue; + + rn = route_node_match (table, (struct prefix *) &p); + if (! rn) + continue; + + vty_show_ip_route_detail (vty, rn); + + route_unlock_node (rn); + } + + return CMD_SUCCESS; +} + +DEFUN (show_ipv6_route_prefix_vrf_all, + show_ipv6_route_prefix_vrf_all_cmd, + "show ipv6 route X:X::X:X/M " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IPv6 routing table\n" + "IPv6 prefix\n" + VRF_ALL_CMD_HELP_STR) +{ + int ret; + struct prefix_ipv6 p; + struct route_table *table; + struct route_node *rn; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + + ret = str2prefix_ipv6 (argv[0], &p); + if (ret <= 0) + { + vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) + continue; + + rn = route_node_match (table, (struct prefix *) &p); + if (! rn) + continue; + if (rn->p.prefixlen != p.prefixlen) + { + route_unlock_node (rn); + continue; + } + + vty_show_ip_route_detail (vty, rn); + + route_unlock_node (rn); + } + + return CMD_SUCCESS; +} + +/* Show route summary. */ +DEFUN (show_ipv6_route_summary_vrf_all, + show_ipv6_route_summary_vrf_all_cmd, + "show ipv6 route summary " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IPv6 routing table\n" + "Summary of all IPv6 routes\n" + VRF_ALL_CMD_HELP_STR) +{ + struct zebra_vrf *zvrf; + vrf_iter_t iter; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + if ((zvrf = vrf_iter2info (iter)) != NULL) + vty_show_ip_route_summary (vty, zvrf->table[AFI_IP6][SAFI_UNICAST]); + + return CMD_SUCCESS; +} + +DEFUN (show_ipv6_mroute_vrf_all, + show_ipv6_mroute_vrf_all_cmd, + "show ipv6 mroute " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IPv6 Multicast routing table\n" + VRF_ALL_CMD_HELP_STR) +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + struct zebra_vrf *zvrf; + vrf_iter_t iter; + int first = 1; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) + continue; + + /* Show all IPv6 route. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + { + if (first) + { + vty_out (vty, SHOW_ROUTE_V6_HEADER); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + } + return CMD_SUCCESS; +} + +DEFUN (show_ipv6_route_summary_prefix_vrf_all, + show_ipv6_route_summary_prefix_vrf_all_cmd, + "show ipv6 route summary prefix " VRF_ALL_CMD_STR, + SHOW_STR + IP_STR + "IPv6 routing table\n" + "Summary of all IPv6 routes\n" + "Prefix routes\n" + VRF_ALL_CMD_HELP_STR) +{ + struct zebra_vrf *zvrf; + vrf_iter_t iter; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + if ((zvrf = vrf_iter2info (iter)) != NULL) + vty_show_ip_route_summary_prefix (vty, zvrf->table[AFI_IP6][SAFI_UNICAST]); + + return CMD_SUCCESS; +} + /* Write IPv6 static route configuration. */ static int static_config_ipv6 (struct vty *vty) @@ -2992,7 +3859,7 @@ zebra_ip_config (struct vty *vty) { int write = 0; - write += static_config_ipv4 (vty); + write += static_config_ipv4 (vty, SAFI_UNICAST, "ip route"); #ifdef HAVE_IPV6 write += static_config_ipv6 (vty); #endif /* HAVE_IPV6 */ @@ -3200,6 +4067,48 @@ zebra_vty_init (void) install_element (ENABLE_NODE, &show_ip_mroute_cmd); + /* Commands for VRF */ + + install_element (VIEW_NODE, &show_ip_route_vrf_cmd); + install_element (VIEW_NODE, &show_ip_route_addr_vrf_cmd); + install_element (VIEW_NODE, &show_ip_route_prefix_vrf_cmd); + install_element (VIEW_NODE, &show_ip_route_prefix_longer_vrf_cmd); + install_element (VIEW_NODE, &show_ip_route_protocol_vrf_cmd); + install_element (VIEW_NODE, &show_ip_route_supernets_vrf_cmd); + install_element (VIEW_NODE, &show_ip_route_summary_vrf_cmd); + install_element (VIEW_NODE, &show_ip_route_summary_prefix_vrf_cmd); + install_element (ENABLE_NODE, &show_ip_route_vrf_cmd); + install_element (ENABLE_NODE, &show_ip_route_addr_vrf_cmd); + install_element (ENABLE_NODE, &show_ip_route_prefix_vrf_cmd); + install_element (ENABLE_NODE, &show_ip_route_prefix_longer_vrf_cmd); + install_element (ENABLE_NODE, &show_ip_route_protocol_vrf_cmd); + install_element (ENABLE_NODE, &show_ip_route_supernets_vrf_cmd); + install_element (ENABLE_NODE, &show_ip_route_summary_vrf_cmd); + install_element (ENABLE_NODE, &show_ip_route_summary_prefix_vrf_cmd); + + install_element (VIEW_NODE, &show_ip_route_vrf_all_cmd); + install_element (VIEW_NODE, &show_ip_route_addr_vrf_all_cmd); + install_element (VIEW_NODE, &show_ip_route_prefix_vrf_all_cmd); + install_element (VIEW_NODE, &show_ip_route_prefix_longer_vrf_all_cmd); + install_element (VIEW_NODE, &show_ip_route_protocol_vrf_all_cmd); + install_element (VIEW_NODE, &show_ip_route_supernets_vrf_all_cmd); + install_element (VIEW_NODE, &show_ip_route_summary_vrf_all_cmd); + install_element (VIEW_NODE, &show_ip_route_summary_prefix_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ip_route_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ip_route_addr_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ip_route_prefix_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ip_route_prefix_longer_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ip_route_protocol_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ip_route_supernets_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ip_route_summary_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ip_route_summary_prefix_vrf_all_cmd); + + install_element (VIEW_NODE, &show_ip_mroute_vrf_cmd); + install_element (ENABLE_NODE, &show_ip_mroute_vrf_cmd); + + install_element (VIEW_NODE, &show_ip_mroute_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ip_mroute_vrf_all_cmd); + #ifdef HAVE_IPV6 install_element (CONFIG_NODE, &ipv6_route_cmd); install_element (CONFIG_NODE, &ipv6_route_flags_cmd); @@ -3256,5 +4165,43 @@ zebra_vty_init (void) install_element (VIEW_NODE, &show_ipv6_mroute_cmd); install_element (ENABLE_NODE, &show_ipv6_mroute_cmd); + + /* Commands for VRF */ + + install_element (VIEW_NODE, &show_ipv6_route_vrf_cmd); + install_element (VIEW_NODE, &show_ipv6_route_summary_vrf_cmd); + install_element (VIEW_NODE, &show_ipv6_route_summary_prefix_vrf_cmd); + install_element (VIEW_NODE, &show_ipv6_route_protocol_vrf_cmd); + install_element (VIEW_NODE, &show_ipv6_route_addr_vrf_cmd); + install_element (VIEW_NODE, &show_ipv6_route_prefix_vrf_cmd); + install_element (VIEW_NODE, &show_ipv6_route_prefix_longer_vrf_cmd); + install_element (ENABLE_NODE, &show_ipv6_route_vrf_cmd); + install_element (ENABLE_NODE, &show_ipv6_route_protocol_vrf_cmd); + install_element (ENABLE_NODE, &show_ipv6_route_addr_vrf_cmd); + install_element (ENABLE_NODE, &show_ipv6_route_prefix_vrf_cmd); + install_element (ENABLE_NODE, &show_ipv6_route_prefix_longer_vrf_cmd); + install_element (ENABLE_NODE, &show_ipv6_route_summary_vrf_cmd); + install_element (ENABLE_NODE, &show_ipv6_route_summary_prefix_vrf_cmd); + + install_element (VIEW_NODE, &show_ipv6_route_vrf_all_cmd); + install_element (VIEW_NODE, &show_ipv6_route_summary_vrf_all_cmd); + install_element (VIEW_NODE, &show_ipv6_route_summary_prefix_vrf_all_cmd); + install_element (VIEW_NODE, &show_ipv6_route_protocol_vrf_all_cmd); + install_element (VIEW_NODE, &show_ipv6_route_addr_vrf_all_cmd); + install_element (VIEW_NODE, &show_ipv6_route_prefix_vrf_all_cmd); + install_element (VIEW_NODE, &show_ipv6_route_prefix_longer_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ipv6_route_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ipv6_route_protocol_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ipv6_route_addr_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ipv6_route_prefix_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ipv6_route_prefix_longer_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ipv6_route_summary_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ipv6_route_summary_prefix_vrf_all_cmd); + + install_element (VIEW_NODE, &show_ipv6_mroute_vrf_cmd); + install_element (ENABLE_NODE, &show_ipv6_mroute_vrf_cmd); + + install_element (VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd); + install_element (ENABLE_NODE, &show_ipv6_mroute_vrf_all_cmd); #endif /* HAVE_IPV6 */ } From 0032dd59cda8215e7ccf4297cd78ee6100de7499 Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:40:04 +0200 Subject: [PATCH 18/27] zebra: let the route-map rule "match interface" work for VRFs Introduce a new "struct nexthop_vrfid" to specify a nexthop together with the VRF ID it belongs to. Thus in route_match_interface(), we can lookup the interface from the correct VRF. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter Conflicts: zebra/zebra_rib.c zebra/zebra_routemap.c --- zebra/zebra_rib.c | 3 ++- zebra/zebra_routemap.c | 22 +++++++++++++--------- zebra/zserv.h | 1 + 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 79aa989814..0f25c76858 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1213,7 +1213,8 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr)); /* It'll get set if required inside */ - ret = zebra_route_map_check(family, rib->type, &rn->p, nexthop, rib->tag); + ret = zebra_route_map_check(family, rib->type, &rn->p, nexthop, rib->vrf_id, + rib->tag); if (ret == RMAP_DENYMATCH) { if (IS_ZEBRA_DEBUG_RIB) diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 1c7b63e757..a8e87dd09c 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -29,6 +29,7 @@ #include "filter.h" #include "plist.h" #include "nexthop.h" +#include "vrf.h" #include "zebra/zserv.h" #include "zebra/debug.h" @@ -45,6 +46,7 @@ extern struct zebra_t zebrad; struct nh_rmap_obj { struct nexthop *nexthop; + vrf_id_t vrf_id; u_int32_t source_protocol; int metric; u_short tag; @@ -255,12 +257,12 @@ route_match_interface (void *rule, struct prefix *prefix, { if (strcasecmp(ifname, "any") == 0) return RMAP_MATCH; - ifindex = ifname2ifindex(ifname); - if (ifindex == 0) - return RMAP_NOMATCH; nh_data = object; if (!nh_data || !nh_data->nexthop) return RMAP_NOMATCH; + ifindex = ifname2ifindex_vrf (ifname, nh_data->vrf_id); + if (ifindex == 0) + return RMAP_NOMATCH; if (nh_data->nexthop->ifindex == ifindex) return RMAP_MATCH; } @@ -767,7 +769,7 @@ DEFUN (ip_protocol, if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update", __func__); - rib_update(); + rib_update(VRF_DEFAULT); return CMD_SUCCESS; } @@ -804,7 +806,7 @@ DEFUN (no_ip_protocol, if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update", __func__); - rib_update(); + rib_update(VRF_DEFAULT); } return CMD_SUCCESS; } @@ -879,7 +881,7 @@ DEFUN (ipv6_protocol, if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update", __func__); - rib_update(); + rib_update(VRF_DEFAULT); return CMD_SUCCESS; } @@ -916,7 +918,7 @@ DEFUN (no_ipv6_protocol, if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update", __func__); - rib_update(); + rib_update(VRF_DEFAULT); } return CMD_SUCCESS; } @@ -1590,7 +1592,7 @@ zebra_route_map_update_timer (struct thread *thread) if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: calling rib_update", __func__); - rib_update(); + rib_update(VRF_DEFAULT); zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); @@ -1621,13 +1623,14 @@ zebra_route_map_write_delay_timer (struct vty *vty) route_map_result_t zebra_route_map_check (int family, int rib_type, struct prefix *p, - struct nexthop *nexthop, u_short tag) + struct nexthop *nexthop, vrf_id_t vrf_id, u_short tag) { struct route_map *rmap = NULL; route_map_result_t ret = RMAP_MATCH; struct nh_rmap_obj nh_obj; nh_obj.nexthop = nexthop; + nh_obj.vrf_id = vrf_id; nh_obj.source_protocol = rib_type; nh_obj.metric = 0; nh_obj.tag = tag; @@ -1652,6 +1655,7 @@ zebra_nht_route_map_check (int family, int client_proto, struct prefix *p, struct nh_rmap_obj nh_obj; nh_obj.nexthop = nexthop; + nh_obj.vrf_id = rib->vrf_id; nh_obj.source_protocol = rib->type; nh_obj.metric = rib->metric; nh_obj.tag = rib->tag; diff --git a/zebra/zserv.h b/zebra/zserv.h index 41a4b9ea9f..ace3715247 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -162,6 +162,7 @@ extern void zebra_route_map_write_delay_timer(struct vty *); extern route_map_result_t zebra_route_map_check (int family, int rib_type, struct prefix *p, struct nexthop *nexthop, + vrf_id_t vrf_id, u_short tag); extern route_map_result_t zebra_nht_route_map_check (int family, int client_proto, From f91386cb7dcc3992d34e220c04f8f1def00105fd Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:40:05 +0200 Subject: [PATCH 19/27] zebra: lookup the address in all VRFs when set the route-map rule "set src" When configuring the route-map rule "set src A.B.C.D", it checked whether the source address exists on some interface. Now it checks the source address throughout all VRFs. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter Conflicts: zebra/zebra_routemap.c Conflicts: zebra/zebra_routemap.c --- zebra/zebra_routemap.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index a8e87dd09c..64d6fda24d 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -659,6 +659,7 @@ DEFUN (set_src, struct interface *pif = NULL; int family; struct prefix p; + vrf_iter_t iter; if (inet_pton(AF_INET, argv[0], &src.ipv4) != 1) { @@ -685,10 +686,18 @@ DEFUN (set_src, return CMD_WARNING; } - if (family == AF_INET) - pif = if_lookup_exact_address ((void *)&src.ipv4, AF_INET); - else if (family == AF_INET6) - pif = if_lookup_exact_address ((void *)&src.ipv6, AF_INET6); + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if (family == AF_INET) + 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) { From 8f527c5e7e6888a7fced25928ea22899259ab49f Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:40:06 +0200 Subject: [PATCH 20/27] zebra: configure static routes in any VRF Introduce new commands to configure static routes in any VRF, by appending the old static route commands with a new parameter "vrf N". A new parameter "const char *vrf_id_str" is added to the functions zebra_static_ipv4() and static_ipv6_func() to get the configured VRF ID. A new member "vrf_id" is added to the "struct static_ipv4" and "struct static_ipv6", indicating which VRF this static route is configured in. But till now, no interface can exist in any non-default VRF. So these static routes in non-default VRFs are kept inactive. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter Conflicts: zebra/zebra_rib.c zebra/zebra_vty.c --- zebra/rib.h | 6 + zebra/zebra_rib.c | 14 +- zebra/zebra_vty.c | 1674 +++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 1571 insertions(+), 123 deletions(-) diff --git a/zebra/rib.h b/zebra/rib.h index 6908e9d816..b76231f8a9 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -174,6 +174,9 @@ struct static_ipv4 struct static_ipv4 *prev; struct static_ipv4 *next; + /* VRF identifier. */ + vrf_id_t vrf_id; + /* Administrative distance. */ u_char distance; @@ -209,6 +212,9 @@ struct static_ipv6 struct static_ipv6 *prev; struct static_ipv6 *next; + /* VRF identifier. */ + vrf_id_t vrf_id; + /* Administrative distance. */ u_char distance; diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 0f25c76858..2b94c6a7c6 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2689,7 +2689,7 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si) struct prefix nh_p; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, si->vrf_id); if (! table) return; @@ -2740,7 +2740,7 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si) rib->instance = 0; rib->distance = si->distance; rib->metric = 0; - rib->vrf_id = VRF_DEFAULT; + rib->vrf_id = si->vrf_id; rib->table = zebrad.rtm_table_default; rib->nexthop_num = 0; rib->tag = si->tag; @@ -2798,7 +2798,7 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si) struct prefix nh_p; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, si->vrf_id); if (! table) return; @@ -2928,6 +2928,7 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, si->distance = distance; si->flags = flags; si->tag = tag; + si->vrf_id = vrf_id; if (gate) si->gate.ipv4 = *gate; @@ -3454,7 +3455,7 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si) struct prefix nh_p; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, si->vrf_id); if (! table) return; @@ -3506,7 +3507,7 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si) rib->instance = 0; rib->distance = si->distance; rib->metric = 0; - rib->vrf_id = VRF_DEFAULT; + rib->vrf_id = si->vrf_id; rib->table = zebrad.rtm_table_default; rib->nexthop_num = 0; rib->tag = si->tag; @@ -3565,7 +3566,7 @@ static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si) struct prefix nh_p; /* Lookup table. */ - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, si->vrf_id); if (! table) return; @@ -3686,6 +3687,7 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, si->distance = distance; si->flags = flags; si->tag = tag; + si->vrf_id = vrf_id; switch (type) { diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index a9fb278aab..4341152e09 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -42,7 +42,7 @@ static int zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, const char *mask_str, const char *gate_str, const char *flag_str, const char *tag_str, - const char *distance_str) + const char *distance_str, const char *vrf_id_str) { int ret; u_char distance; @@ -52,6 +52,7 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, const char *ifname; u_char flag = 0; u_short tag = 0; + vrf_id_t vrf_id = VRF_DEFAULT; ret = str2prefix (dest_str, &p); if (ret <= 0) @@ -85,6 +86,10 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, if (tag_str) tag = atoi(tag_str); + /* VRF id */ + if (vrf_id_str) + VTY_GET_INTEGER ("VRF ID", vrf_id, vrf_id_str); + /* Null0 static route. */ if ((gate_str != NULL) && (strncasecmp (gate_str, "Null0", strlen (gate_str)) == 0)) { @@ -94,9 +99,9 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, return CMD_WARNING; } if (add_cmd) - static_add_ipv4 (&p, NULL, NULL, ZEBRA_FLAG_BLACKHOLE, tag, distance, VRF_DEFAULT); + static_add_ipv4 (&p, NULL, NULL, ZEBRA_FLAG_BLACKHOLE, tag, distance, vrf_id); else - static_delete_ipv4 (&p, NULL, NULL, tag, distance, VRF_DEFAULT); + static_delete_ipv4 (&p, NULL, NULL, tag, distance, vrf_id); return CMD_SUCCESS; } @@ -120,9 +125,9 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, if (gate_str == NULL) { if (add_cmd) - static_add_ipv4 (&p, NULL, NULL, flag, tag, distance, VRF_DEFAULT); + static_add_ipv4 (&p, NULL, NULL, flag, tag, distance, vrf_id); else - static_delete_ipv4 (&p, NULL, NULL, tag, distance, VRF_DEFAULT); + static_delete_ipv4 (&p, NULL, NULL, tag, distance, vrf_id); return CMD_SUCCESS; } @@ -136,9 +141,9 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, ifname = gate_str; if (add_cmd) - static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, flag, tag, distance, VRF_DEFAULT); + static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, flag, tag, distance, vrf_id); else - static_delete_ipv4 (&p, ifname ? NULL : &gate, ifname, tag, distance, VRF_DEFAULT); + static_delete_ipv4 (&p, ifname ? NULL : &gate, ifname, tag, distance, vrf_id); return CMD_SUCCESS; } @@ -154,7 +159,8 @@ DEFUN (ip_route, "IP gateway interface name\n" "Null interface\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL, NULL); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL, + NULL, NULL); } DEFUN (ip_route_tag, @@ -169,7 +175,8 @@ DEFUN (ip_route_tag, "Set tag for this route\n" "Tag value\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2], NULL); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2], + NULL, NULL); } DEFUN (ip_route_flags, @@ -183,7 +190,8 @@ DEFUN (ip_route_flags, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL, NULL); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL, + NULL, NULL); } DEFUN (ip_route_flags_tag, @@ -200,7 +208,8 @@ DEFUN (ip_route_flags_tag, "Tag value\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3], NULL); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3], + NULL, NULL); } DEFUN (ip_route_flags2, @@ -212,7 +221,8 @@ DEFUN (ip_route_flags2, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL, NULL); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL, + NULL, NULL); } DEFUN (ip_route_flags2_tag, @@ -227,7 +237,8 @@ DEFUN (ip_route_flags2_tag, "Tag value\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2], NULL); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2], + NULL, NULL); } /* Mask as A.B.C.D format. */ @@ -242,7 +253,8 @@ DEFUN (ip_route_mask, "IP gateway interface name\n" "Null interface\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, NULL); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, + NULL, NULL); } DEFUN (ip_route_mask_tag, @@ -259,7 +271,8 @@ DEFUN (ip_route_mask_tag, "Tag value\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], NULL); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], + NULL, NULL); } DEFUN (ip_route_mask_flags, @@ -274,7 +287,8 @@ DEFUN (ip_route_mask_flags, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, NULL); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, + NULL, NULL); } DEFUN (ip_route_mask_flags_tag, @@ -292,7 +306,8 @@ DEFUN (ip_route_mask_flags_tag, "Tag value\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], NULL); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], + NULL, NULL); } DEFUN (ip_route_mask_flags2, @@ -305,7 +320,8 @@ DEFUN (ip_route_mask_flags2, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, NULL); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, + NULL, NULL); } DEFUN (ip_route_mask_flags2_tag, @@ -320,7 +336,8 @@ DEFUN (ip_route_mask_flags2_tag, "Set tag for this route\n" "Tag value\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], NULL); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], + NULL, NULL); } /* Distance option value. */ @@ -335,7 +352,8 @@ DEFUN (ip_route_distance, "Null interface\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL, argv[2]); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL, + argv[2], NULL); } DEFUN (ip_route_tag_distance, @@ -352,7 +370,8 @@ DEFUN (ip_route_tag_distance, "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2], argv[3]); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2], + argv[3], NULL); } DEFUN (ip_route_flags_distance, @@ -367,7 +386,8 @@ DEFUN (ip_route_flags_distance, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL, argv[3]); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL, + argv[3], NULL); } DEFUN (ip_route_flags_tag_distance, @@ -384,7 +404,8 @@ DEFUN (ip_route_flags_tag_distance, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3], argv[4]); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3], + argv[4], NULL); } DEFUN (ip_route_flags_distance2, @@ -397,7 +418,8 @@ DEFUN (ip_route_flags_distance2, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL, argv[2]); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL, + argv[2], NULL); } DEFUN (ip_route_flags_tag_distance2, @@ -412,7 +434,8 @@ DEFUN (ip_route_flags_tag_distance2, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2], argv[3]); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2], + argv[3], NULL); } DEFUN (ip_route_mask_distance, @@ -427,7 +450,8 @@ DEFUN (ip_route_mask_distance, "Null interface\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, argv[3]); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, + argv[3], NULL); } DEFUN (ip_route_mask_tag_distance, @@ -444,7 +468,8 @@ DEFUN (ip_route_mask_tag_distance, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], argv[4]); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], + argv[4], NULL); } DEFUN (ip_route_mask_flags_tag_distance, @@ -462,7 +487,8 @@ DEFUN (ip_route_mask_flags_tag_distance, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], + argv[5], NULL); } @@ -479,7 +505,8 @@ DEFUN (ip_route_mask_flags_distance, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, argv[4]); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, + argv[4], NULL); } DEFUN (ip_route_mask_flags_distance2, @@ -493,7 +520,8 @@ DEFUN (ip_route_mask_flags_distance2, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, argv[3]); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, + argv[3], NULL); } DEFUN (ip_route_mask_flags_tag_distance2, @@ -509,7 +537,8 @@ DEFUN (ip_route_mask_flags_tag_distance2, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], argv[4]); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], + argv[4], NULL); } DEFUN (no_ip_route, @@ -523,7 +552,8 @@ DEFUN (no_ip_route, "IP gateway interface name\n" "Null interface\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL, NULL); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL, + NULL, NULL); } DEFUN (no_ip_route_tag, @@ -539,7 +569,8 @@ DEFUN (no_ip_route_tag, "Tag of this route\n" "Tag value\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2], NULL); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2], + NULL, NULL); } ALIAS (no_ip_route, @@ -578,7 +609,8 @@ DEFUN (no_ip_route_flags2, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, NULL, NULL); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, NULL, + NULL, NULL); } DEFUN (no_ip_route_flags2_tag, @@ -593,7 +625,8 @@ DEFUN (no_ip_route_flags2_tag, "Tag of this route\n" "Tag value\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, argv[1], NULL); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, argv[1], + NULL, NULL); } DEFUN (no_ip_route_mask, @@ -608,7 +641,8 @@ DEFUN (no_ip_route_mask, "IP gateway interface name\n" "Null interface\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, NULL); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, + NULL, NULL); } DEFUN (no_ip_route_mask_tag, @@ -625,7 +659,8 @@ DEFUN (no_ip_route_mask_tag, "Tag of this route\n" "Tag value\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], NULL); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], + NULL, NULL); } ALIAS (no_ip_route_mask, @@ -667,7 +702,8 @@ DEFUN (no_ip_route_mask_flags2, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, NULL, NULL); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, NULL, + NULL, NULL); } DEFUN (no_ip_route_mask_flags2_tag, @@ -683,10 +719,10 @@ DEFUN (no_ip_route_mask_flags2_tag, "Tag of this route\n" "Tag value\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], NULL); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], + NULL, NULL); } - DEFUN (no_ip_route_distance, no_ip_route_distance_cmd, "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) <1-255>", @@ -699,7 +735,8 @@ DEFUN (no_ip_route_distance, "Null interface\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL, argv[2]); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL, + argv[2], NULL); } DEFUN (no_ip_route_tag_distance, @@ -716,7 +753,8 @@ DEFUN (no_ip_route_tag_distance, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2], argv[3]); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2], + argv[3], NULL); } DEFUN (no_ip_route_flags_distance, @@ -732,7 +770,8 @@ DEFUN (no_ip_route_flags_distance, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], NULL, argv[3]); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], NULL, + argv[3], NULL); } DEFUN (no_ip_route_flags_tag_distance, @@ -750,7 +789,8 @@ DEFUN (no_ip_route_flags_tag_distance, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], argv[3], argv[4]); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], argv[3], + argv[4], NULL); } DEFUN (no_ip_route_flags_distance2, @@ -764,7 +804,8 @@ DEFUN (no_ip_route_flags_distance2, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], NULL, argv[2]); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], NULL, + argv[2], NULL); } DEFUN (no_ip_route_flags_tag_distance2, @@ -780,7 +821,8 @@ DEFUN (no_ip_route_flags_tag_distance2, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], argv[2] , argv[3]); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], argv[2], + argv[3], NULL); } DEFUN (no_ip_route_mask_distance, @@ -796,7 +838,8 @@ DEFUN (no_ip_route_mask_distance, "Null interface\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, argv[3]); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, + argv[3], NULL); } DEFUN (no_ip_route_mask_tag_distance, @@ -814,7 +857,8 @@ DEFUN (no_ip_route_mask_tag_distance, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], argv[4]); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], + argv[4], NULL); } DEFUN (no_ip_route_mask_flags_distance, @@ -831,7 +875,8 @@ DEFUN (no_ip_route_mask_flags_distance, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], NULL, argv[4]); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], NULL, + argv[4], NULL); } DEFUN (no_ip_route_mask_flags_tag_distance, @@ -850,7 +895,8 @@ DEFUN (no_ip_route_mask_flags_tag_distance, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4], + argv[5], NULL); } DEFUN (no_ip_route_mask_flags_distance2, @@ -865,7 +911,8 @@ DEFUN (no_ip_route_mask_flags_distance2, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], NULL, argv[3]); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], NULL, + argv[3], NULL); } DEFUN (no_ip_route_mask_flags_tag_distance2, @@ -882,7 +929,798 @@ DEFUN (no_ip_route_mask_flags_tag_distance2, "Tag value\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3], argv[4]); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3], + argv[4], NULL); +} + +/* Static route configuration. */ +DEFUN (ip_route_vrf, + ip_route_vrf_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0)" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL, NULL, argv[2]); +} + +DEFUN (ip_route_tag_vrf, + ip_route_tag_vrf_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) tag <1-65535>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2], NULL, argv[3]); +} + +DEFUN (ip_route_flags_vrf, + ip_route_flags_vrf_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole)" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL, NULL, argv[3]); +} + +DEFUN (ip_route_flags_tag_vrf, + ip_route_flags_tag_vrf_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) + +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3], NULL, argv[4]); +} + +DEFUN (ip_route_flags2_vrf, + ip_route_flags2_vrf_cmd, + "ip route A.B.C.D/M (reject|blackhole)" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL, NULL, argv[2]); +} + +DEFUN (ip_route_flags2_tag_vrf, + ip_route_flags2_tag_vrf_cmd, + "ip route A.B.C.D/M (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) + +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2], NULL, argv[3]); +} + +/* Mask as A.B.C.D format. */ +DEFUN (ip_route_mask_vrf, + ip_route_mask_vrf_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0)" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, NULL, argv[3]); +} + +DEFUN (ip_route_mask_tag_vrf, + ip_route_mask_tag_vrf_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) tag <1-65535>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) + +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], NULL, argv[4]); +} + +DEFUN (ip_route_mask_flags_vrf, + ip_route_mask_flags_vrf_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole)" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, NULL, argv[4]); +} + +DEFUN (ip_route_mask_flags_tag_vrf, + ip_route_mask_flags_tag_vrf_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) + +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], NULL, argv[5]); +} + +DEFUN (ip_route_mask_flags2_vrf, + ip_route_mask_flags2_vrf_cmd, + "ip route A.B.C.D A.B.C.D (reject|blackhole)" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, NULL, argv[3]); +} + +DEFUN (ip_route_mask_flags2_tag_vrf, + ip_route_mask_flags2_tag_vrf_cmd, + "ip route A.B.C.D A.B.C.D (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], NULL, argv[4]); +} + +/* Distance option value. */ +DEFUN (ip_route_distance_vrf, + ip_route_distance_vrf_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL, argv[2], argv[3]); +} + +DEFUN (ip_route_tag_distance_vrf, + ip_route_tag_distance_vrf_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) tag <1-65535> <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) + +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2], argv[3], argv[4]); +} + +DEFUN (ip_route_flags_distance_vrf, + ip_route_flags_distance_vrf_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL, argv[3], argv[4]); +} + +DEFUN (ip_route_flags_tag_distance_vrf, + ip_route_flags_tag_distance_vrf_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3], argv[4],argv[5]); +} + +DEFUN (ip_route_flags_distance2_vrf, + ip_route_flags_distance2_vrf_cmd, + "ip route A.B.C.D/M (reject|blackhole) <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL, argv[2], argv[3]); +} + +DEFUN (ip_route_flags_tag_distance2_vrf, + ip_route_flags_tag_distance2_vrf_cmd, + "ip route A.B.C.D/M (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2], argv[3], argv[4]); +} + +DEFUN (ip_route_mask_distance_vrf, + ip_route_mask_distance_vrf_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, argv[3], argv[4]); +} + +DEFUN (ip_route_mask_tag_distance_vrf, + ip_route_mask_tag_distance_vrf_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) tag <1-65535> <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], argv[4], argv[5]); +} + +DEFUN (ip_route_mask_flags_tag_distance_vrf, + ip_route_mask_flags_tag_distance_vrf_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); +} + + +DEFUN (ip_route_mask_flags_distance_vrf, + ip_route_mask_flags_distance_vrf_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, argv[4], argv[5]); +} + +DEFUN (ip_route_mask_flags_distance2_vrf, + ip_route_mask_flags_distance2_vrf_cmd, + "ip route A.B.C.D A.B.C.D (reject|blackhole) <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, argv[3], argv[4]); +} + +DEFUN (ip_route_mask_flags_tag_distance2_vrf, + ip_route_mask_flags_tag_distance2_vrf_cmd, + "ip route A.B.C.D A.B.C.D (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], argv[4], argv[5]); +} + +DEFUN (no_ip_route_vrf, + no_ip_route_vrf_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0)" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL, NULL, argv[2]); +} + +DEFUN (no_ip_route_tag_vrf, + no_ip_route_tag_vrf_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) tag <1-65535>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Tag of this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2], NULL, argv[3]); +} + +ALIAS (no_ip_route_vrf, + no_ip_route_flags_vrf_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole)" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) + +ALIAS (no_ip_route_tag_vrf, + no_ip_route_flags_tag_vrf_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) + +DEFUN (no_ip_route_flags2_vrf, + no_ip_route_flags2_vrf_cmd, + "no ip route A.B.C.D/M (reject|blackhole)" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, NULL, NULL, argv[1]); +} + +DEFUN (no_ip_route_flags2_tag_vrf, + no_ip_route_flags2_tag_vrf_cmd, + "no ip route A.B.C.D/M (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, argv[1], NULL, argv[1]); +} + +DEFUN (no_ip_route_mask_vrf, + no_ip_route_mask_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0)" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, NULL, argv[3]); +} + +DEFUN (no_ip_route_mask_tag_vrf, + no_ip_route_mask_tag_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) tag <1-65535>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Tag of this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], NULL, argv[4]); +} + +ALIAS (no_ip_route_mask_vrf, + no_ip_route_mask_flags_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole)" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) + +ALIAS (no_ip_route_mask_tag_vrf, + no_ip_route_mask_flags_tag_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) + +DEFUN (no_ip_route_mask_flags2_vrf, + no_ip_route_mask_flags2_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (reject|blackhole)" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, NULL, NULL, argv[2]); +} + +DEFUN (no_ip_route_mask_flags2_tag_vrf, + no_ip_route_mask_flags2_tag_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], NULL, argv[3]); +} + + +DEFUN (no_ip_route_distance_vrf, + no_ip_route_distance_vrf_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL, argv[2], argv[3]); +} + +DEFUN (no_ip_route_tag_distance_vrf, + no_ip_route_tag_distance_vrf_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) tag <1-65535> <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2], argv[3], argv[4]); +} + +DEFUN (no_ip_route_flags_distance_vrf, + no_ip_route_flags_distance_vrf_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], NULL, argv[3], argv[4]); +} + +DEFUN (no_ip_route_flags_tag_distance_vrf, + no_ip_route_flags_tag_distance_vrf_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], argv[3], argv[4],argv[5]); +} + +DEFUN (no_ip_route_flags_distance2_vrf, + no_ip_route_flags_distance2_vrf_cmd, + "no ip route A.B.C.D/M (reject|blackhole) <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], NULL, argv[2], argv[3]); +} + +DEFUN (no_ip_route_flags_tag_distance2_vrf, + no_ip_route_flags_tag_distance2_vrf_cmd, + "no ip route A.B.C.D/M (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], argv[2] , argv[3], argv[4]); +} + +DEFUN (no_ip_route_mask_distance_vrf, + no_ip_route_mask_distance_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, argv[3], argv[4]); +} + +DEFUN (no_ip_route_mask_tag_distance_vrf, + no_ip_route_mask_tag_distance_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) tag <1-65535> <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], argv[4], argv[5]); +} + +DEFUN (no_ip_route_mask_flags_distance_vrf, + no_ip_route_mask_flags_distance_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], NULL, argv[4], argv[5]); +} + +DEFUN (no_ip_route_mask_flags_tag_distance_vrf, + no_ip_route_mask_flags_tag_distance_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); +} + +DEFUN (no_ip_route_mask_flags_distance2_vrf, + no_ip_route_mask_flags_distance2_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (reject|blackhole) <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], NULL, argv[3], argv[4]); +} + +DEFUN (no_ip_route_mask_flags_tag_distance2_vrf, + no_ip_route_mask_flags_tag_distance2_vrf_cmd, + "no ip route A.B.C.D A.B.C.D (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n" + VRF_CMD_HELP_STR) +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3], argv[4], argv[5]); } /* New RIB. Detailed information for IPv4 route. */ @@ -2217,6 +3055,9 @@ static_config_ipv4 (struct vty *vty, safi_t safi, const char *cmd) if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) vty_out (vty, " %d", si->distance); + if (si->vrf_id != VRF_DEFAULT) + vty_out (vty, " vrf %u", si->vrf_id); + vty_out (vty, "%s", VTY_NEWLINE); write = 1; @@ -2314,7 +3155,7 @@ static int static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, const char *gate_str, const char *ifname, const char *flag_str, const char *tag_str, - const char *distance_str) + const char *distance_str, const char *vrf_id_str) { int ret; u_char distance; @@ -2322,6 +3163,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, struct in6_addr *gate = NULL; struct in6_addr gate_addr; u_char type = 0; + vrf_id_t vrf_id = VRF_DEFAULT; u_char flag = 0; u_short tag = 0; @@ -2392,10 +3234,14 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, } } + /* VRF id */ + if (vrf_id_str) + VTY_GET_INTEGER ("VRF ID", vrf_id, vrf_id_str); + if (add_cmd) - static_add_ipv6 (&p, type, gate, ifname, flag, tag, distance, VRF_DEFAULT); + static_add_ipv6 (&p, type, gate, ifname, flag, tag, distance, vrf_id); else - static_delete_ipv6 (&p, type, gate, ifname, tag, distance, VRF_DEFAULT); + static_delete_ipv6 (&p, type, gate, ifname, tag, distance, vrf_id); return CMD_SUCCESS; } @@ -2409,7 +3255,7 @@ DEFUN (ipv6_route, "IPv6 gateway address\n" "IPv6 gateway interface name\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL, NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL, NULL, NULL); } DEFUN (ipv6_route_tag, @@ -2423,7 +3269,7 @@ DEFUN (ipv6_route_tag, "Set tag for this route\n" "Tag value\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2], NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2], NULL, NULL); } DEFUN (ipv6_route_flags, @@ -2437,7 +3283,7 @@ DEFUN (ipv6_route_flags, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, NULL, NULL); } DEFUN (ipv6_route_flags_tag, @@ -2453,7 +3299,7 @@ DEFUN (ipv6_route_flags_tag, "Set tag for this route\n" "Tag value\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], NULL, NULL); } DEFUN (ipv6_route_ifname, @@ -2465,7 +3311,7 @@ DEFUN (ipv6_route_ifname, "IPv6 gateway address\n" "IPv6 gateway interface name\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, NULL, NULL); } DEFUN (ipv6_route_ifname_tag, ipv6_route_ifname_tag_cmd, @@ -2478,7 +3324,7 @@ DEFUN (ipv6_route_ifname_tag, "Set tag for this route\n" "Tag value\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], NULL, NULL); } DEFUN (ipv6_route_ifname_flags, @@ -2492,7 +3338,7 @@ DEFUN (ipv6_route_ifname_flags, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, NULL, NULL); } DEFUN (ipv6_route_ifname_flags_tag, @@ -2508,7 +3354,7 @@ DEFUN (ipv6_route_ifname_flags_tag, "Set tag for this route\n" "Tag value\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], NULL, NULL); } DEFUN (ipv6_route_pref, @@ -2521,7 +3367,7 @@ DEFUN (ipv6_route_pref, "IPv6 gateway interface name\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL, argv[2]); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL, argv[2], NULL); } DEFUN (ipv6_route_pref_tag, @@ -2536,7 +3382,7 @@ DEFUN (ipv6_route_pref_tag, "Tag value\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2], argv[3]); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2], argv[3], NULL); } DEFUN (ipv6_route_flags_pref, @@ -2551,7 +3397,7 @@ DEFUN (ipv6_route_flags_pref, "Silently discard pkts when matched\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, argv[3]); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, argv[3], NULL); } DEFUN (ipv6_route_flags_pref_tag, @@ -2568,7 +3414,7 @@ DEFUN (ipv6_route_flags_pref_tag, "Tag value\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], argv[4]); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], argv[4], NULL); } DEFUN (ipv6_route_ifname_pref, @@ -2581,7 +3427,7 @@ DEFUN (ipv6_route_ifname_pref, "IPv6 gateway interface name\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, argv[3]); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, argv[3], NULL); } DEFUN (ipv6_route_ifname_pref_tag, @@ -2596,7 +3442,7 @@ DEFUN (ipv6_route_ifname_pref_tag, "Tag value\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], argv[4]); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], argv[4], NULL); } DEFUN (ipv6_route_ifname_flags_pref, @@ -2611,7 +3457,7 @@ DEFUN (ipv6_route_ifname_flags_pref, "Silently discard pkts when matched\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, argv[4]); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, argv[4], NULL); } DEFUN (ipv6_route_ifname_flags_pref_tag, @@ -2628,7 +3474,7 @@ DEFUN (ipv6_route_ifname_flags_pref_tag, "Tag value\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], NULL); } DEFUN (no_ipv6_route, @@ -2641,7 +3487,7 @@ DEFUN (no_ipv6_route, "IPv6 gateway address\n" "IPv6 gateway interface name\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL, NULL); + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL, NULL, NULL); } DEFUN (no_ipv6_route_tag, @@ -2656,7 +3502,7 @@ DEFUN (no_ipv6_route_tag, "Set tag for this route\n" "Tag value\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], NULL); + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], NULL, NULL); } ALIAS (no_ipv6_route, @@ -2695,7 +3541,7 @@ DEFUN (no_ipv6_route_ifname, "IPv6 gateway address\n" "IPv6 gateway interface name\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, NULL); + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, NULL, NULL); } DEFUN (no_ipv6_route_ifname_tag, @@ -2710,7 +3556,7 @@ DEFUN (no_ipv6_route_ifname_tag, "Set tag for this route\n" "Tag value\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], NULL); + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], NULL, NULL); } ALIAS (no_ipv6_route_ifname, @@ -2750,7 +3596,7 @@ DEFUN (no_ipv6_route_pref, "IPv6 gateway interface name\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL, argv[2]); + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL, argv[2], NULL); } DEFUN (no_ipv6_route_pref_tag, @@ -2766,7 +3612,7 @@ DEFUN (no_ipv6_route_pref_tag, "Tag value\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], argv[3]); + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], argv[3], NULL); } DEFUN (no_ipv6_route_flags_pref, @@ -2783,7 +3629,7 @@ DEFUN (no_ipv6_route_flags_pref, "Distance value for this prefix\n") { /* We do not care about argv[2] */ - return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], NULL, argv[3]); + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], NULL, argv[3], NULL); } DEFUN (no_ipv6_route_flags_pref_tag, @@ -2802,7 +3648,7 @@ DEFUN (no_ipv6_route_flags_pref_tag, "Distance value for this prefix\n") { /* We do not care about argv[2] */ - return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3], argv[4]); + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3], argv[4], NULL); } DEFUN (no_ipv6_route_ifname_pref, @@ -2816,7 +3662,7 @@ DEFUN (no_ipv6_route_ifname_pref, "IPv6 gateway interface name\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, argv[3]); + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, argv[3], NULL); } DEFUN (no_ipv6_route_ifname_pref_tag, @@ -2832,7 +3678,7 @@ DEFUN (no_ipv6_route_ifname_pref_tag, "Tag value\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], argv[4]); + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], argv[4], NULL); } DEFUN (no_ipv6_route_ifname_flags_pref, @@ -2848,7 +3694,7 @@ DEFUN (no_ipv6_route_ifname_flags_pref, "Silently discard pkts when matched\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], NULL, argv[4]); + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], NULL, argv[4], NULL); } DEFUN (no_ipv6_route_ifname_flags_pref_tag, @@ -2866,7 +3712,508 @@ DEFUN (no_ipv6_route_ifname_flags_pref_tag, "Tag value\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], NULL); +} + +DEFUN (ipv6_route_vrf, + ipv6_route_vrf_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL, NULL, argv[2]); +} + +DEFUN (ipv6_route_tag_vrf, + ipv6_route_tag_vrf_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2], NULL, argv[3]); +} + +DEFUN (ipv6_route_flags_vrf, + ipv6_route_flags_vrf_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole)" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, NULL, argv[3]); +} + +DEFUN (ipv6_route_flags_tag_vrf, + ipv6_route_flags_tag_vrf_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], NULL, argv[4]); +} + +DEFUN (ipv6_route_ifname_vrf, + ipv6_route_ifname_vrf_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, NULL, argv[3]); +} +DEFUN (ipv6_route_ifname_tag_vrf, + ipv6_route_ifname_tag_vrf_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], NULL, argv[4]); +} + +DEFUN (ipv6_route_ifname_flags_vrf, + ipv6_route_ifname_flags_vrf_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole)" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, NULL, argv[4]); +} + +DEFUN (ipv6_route_ifname_flags_tag_vrf, + ipv6_route_ifname_flags_tag_vrf_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], NULL, argv[5]); +} + +DEFUN (ipv6_route_pref_vrf, + ipv6_route_pref_vrf_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL, argv[2], argv[3]); +} + +DEFUN (ipv6_route_pref_tag_vrf, + ipv6_route_pref_tag_vrf_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535> <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2], argv[3], argv[4]); +} + +DEFUN (ipv6_route_flags_pref_vrf, + ipv6_route_flags_pref_vrf_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, argv[3], argv[4]); +} + +DEFUN (ipv6_route_flags_pref_tag_vrf, + ipv6_route_flags_pref_tag_vrf_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], argv[4], argv[5]); +} + +DEFUN (ipv6_route_ifname_pref_vrf, + ipv6_route_ifname_pref_vrf_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, argv[3], argv[4]); +} + +DEFUN (ipv6_route_ifname_pref_tag_vrf, + ipv6_route_ifname_pref_tag_vrf_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535> <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], argv[4], argv[5]); +} + +DEFUN (ipv6_route_ifname_flags_pref_vrf, + ipv6_route_ifname_flags_pref_vrf_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, argv[4], argv[5]); +} + +DEFUN (ipv6_route_ifname_flags_pref_tag_vrf, + ipv6_route_ifname_flags_pref_tag_vrf_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); +} + +DEFUN (no_ipv6_route_vrf, + no_ipv6_route_vrf_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL, NULL, argv[2]); +} + +DEFUN (no_ipv6_route_tag_vrf, + no_ipv6_route_tag_vrf_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], NULL, argv[3]); +} + +ALIAS (no_ipv6_route_vrf, + no_ipv6_route_flags_vrf_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole)" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) + +ALIAS (no_ipv6_route_tag_vrf, + no_ipv6_route_flags_tag_vrf_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) + +DEFUN (no_ipv6_route_ifname_vrf, + no_ipv6_route_ifname_vrf_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, NULL, argv[3]); +} + +DEFUN (no_ipv6_route_ifname_tag_vrf, + no_ipv6_route_ifname_tag_vrf_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], NULL, argv[4]); +} + +ALIAS (no_ipv6_route_ifname_vrf, + no_ipv6_route_ifname_flags_vrf_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole)" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + VRF_CMD_HELP_STR) + +ALIAS (no_ipv6_route_ifname_tag_vrf, + no_ipv6_route_ifname_flags_tag_vrf_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + VRF_CMD_HELP_STR) + +DEFUN (no_ipv6_route_pref_vrf, + no_ipv6_route_pref_vrf_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL, argv[2], argv[3]); +} + +DEFUN (no_ipv6_route_pref_tag_vrf, + no_ipv6_route_pref_tag_vrf_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535> <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], argv[3], argv[4]); +} + +DEFUN (no_ipv6_route_flags_pref_vrf, + no_ipv6_route_flags_pref_vrf_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) +{ + /* We do not care about argv[2] */ + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], NULL, argv[3], argv[4]); +} + +DEFUN (no_ipv6_route_flags_pref_tag_vrf, + no_ipv6_route_flags_pref_tag_vrf_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) +{ + /* We do not care about argv[2] */ + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3], argv[4], argv[5]); +} + +DEFUN (no_ipv6_route_ifname_pref_vrf, + no_ipv6_route_ifname_pref_vrf_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, argv[3], argv[4]); +} + +DEFUN (no_ipv6_route_ifname_pref_tag_vrf, + no_ipv6_route_ifname_pref_tag_vrf_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535> <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], argv[4], argv[5]); +} + +DEFUN (no_ipv6_route_ifname_flags_pref_vrf, + no_ipv6_route_ifname_flags_pref_vrf_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], NULL, argv[4], argv[5]); +} + +DEFUN (no_ipv6_route_ifname_flags_pref_tag_vrf, + no_ipv6_route_ifname_flags_pref_tag_vrf_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535> <1-255>" VRF_CMD_STR, + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this prefix\n" + VRF_CMD_HELP_STR) +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); } /* New RIB. Detailed information for IPv6 route. */ @@ -3785,50 +5132,58 @@ static_config_ipv6 (struct vty *vty) int write; char buf[BUFSIZ]; struct route_table *stable; + struct zebra_vrf *zvrf; + vrf_iter_t iter; write = 0; - /* Lookup table. */ - stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); - if (! stable) - return -1; + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + if ((zvrf = vrf_iter2info (iter)) == NULL || + (stable = zvrf->stable[AFI_IP6][SAFI_UNICAST]) == NULL) + continue; - for (rn = route_top (stable); rn; rn = route_next (rn)) - for (si = rn->info; si; si = si->next) - { - vty_out (vty, "ipv6 route %s/%d", - inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ), - rn->p.prefixlen); + for (rn = route_top (stable); rn; rn = route_next (rn)) + for (si = rn->info; si; si = si->next) + { + vty_out (vty, "ipv6 route %s", prefix2str (&rn->p, buf, sizeof buf)); - switch (si->type) - { - case STATIC_IPV6_GATEWAY: - vty_out (vty, " %s", inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ)); - break; - case STATIC_IPV6_IFNAME: - vty_out (vty, " %s", si->ifname); - break; - case STATIC_IPV6_GATEWAY_IFNAME: - vty_out (vty, " %s %s", - inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ), si->ifname); - break; - } + switch (si->type) + { + case STATIC_IPV6_GATEWAY: + vty_out (vty, " %s", + inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ)); + break; + case STATIC_IPV6_IFNAME: + vty_out (vty, " %s", si->ifname); + break; + case STATIC_IPV6_GATEWAY_IFNAME: + vty_out (vty, " %s %s", + inet_ntop (AF_INET6, &si->ipv6, buf, BUFSIZ), + si->ifname); + break; + } - if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, " %s", "reject"); + if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT)) + vty_out (vty, " %s", "reject"); - if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, " %s", "blackhole"); + if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE)) + vty_out (vty, " %s", "blackhole"); - if (si->tag) - vty_out (vty, " tag %d", si->tag); + if (si->tag) + vty_out (vty, " tag %d", si->tag); - if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) - vty_out (vty, " %d", si->distance); - vty_out (vty, "%s", VTY_NEWLINE); + if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) + vty_out (vty, " %d", si->distance); - write = 1; - } + if (si->vrf_id != VRF_DEFAULT) + vty_out (vty, " vrf %u", si->vrf_id); + + vty_out (vty, "%s", VTY_NEWLINE); + + write = 1; + } + } return write; } #endif /* HAVE_IPV6 */ @@ -3976,6 +5331,8 @@ config_write_protocol (struct vty *vty) static struct cmd_node ip_node = { IP_NODE, "", 1 }; static struct cmd_node protocol_node = { PROTOCOL_NODE, "", 1 }; + + /* Route VTY. */ void zebra_vty_init (void) @@ -4069,6 +5426,55 @@ zebra_vty_init (void) /* Commands for VRF */ + install_element (CONFIG_NODE, &ip_route_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_tag_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_flags_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_flags_tag_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_flags2_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_flags2_tag_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_tag_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags_tag_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags2_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags2_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags2_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags2_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags2_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags2_tag_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_distance_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_tag_distance_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_flags_distance_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_flags_tag_distance_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_flags_distance2_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_flags_tag_distance2_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_distance_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_tag_distance_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags_distance_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags_tag_distance_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags_distance2_vrf_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags_tag_distance2_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_distance_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_tag_distance_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags_distance_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags_tag_distance_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags_distance2_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags_tag_distance2_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_distance_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_tag_distance_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags_distance_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags_tag_distance_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags_distance2_vrf_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags_tag_distance2_vrf_cmd); + install_element (VIEW_NODE, &show_ip_route_vrf_cmd); install_element (VIEW_NODE, &show_ip_route_addr_vrf_cmd); install_element (VIEW_NODE, &show_ip_route_prefix_vrf_cmd); @@ -4168,6 +5574,40 @@ zebra_vty_init (void) /* Commands for VRF */ + install_element (CONFIG_NODE, &ipv6_route_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_flags_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_flags_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_flags_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_pref_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_flags_pref_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_pref_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_flags_pref_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_pref_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_flags_pref_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_pref_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_tag_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_flags_tag_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_tag_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_flags_tag_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_pref_tag_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_flags_pref_tag_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_pref_tag_vrf_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_flags_pref_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_flags_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_pref_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_flags_pref_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_tag_vrf_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_pref_tag_vrf_cmd); + + install_element (VIEW_NODE, &show_ipv6_route_vrf_cmd); install_element (VIEW_NODE, &show_ipv6_route_summary_vrf_cmd); install_element (VIEW_NODE, &show_ipv6_route_summary_prefix_vrf_cmd); From c6ffe64543f9a5b8d26ce9274911882dda07065b Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:40:07 +0200 Subject: [PATCH 21/27] zebra: maintain the router-id per VRF A router may need different identifier among the VRFs. So move the maintenance of router-id per VRF. * rib.h: Move the previous global variables in router-id.c into the "struct zebra_vrf": - struct list _rid_all_sorted_list/*rid_all_sorted_list - struct list _rid_lo_sorted_list/*rid_lo_sorted_list - struct prefix rid_user_assigned * router-id.c/router-id.h: A new parameter "vrf_id" is added to all the router-id APIs. Their operations are done only within the specified VRF. A new command "router-id A.B.C.D vrf N" is added to allow manual router-id for any VRF. The old router_id_init() function is splitted into two: - router_id_cmd_init(): it only installs the commands - router_id_init(): this new one initializes the variables for a specified VRF * zebra_rib.c: Add new functions zebra_vrf_get/lookup() called from router-id.c. * main.c: Replace router_id_init() with router_id_cmd_init() and call the new router_id_init() in zebra_vrf_new(). Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter Conflicts: zebra/rib.h Conflicts: zebra/rib.h zebra/router-id.c zebra/zserv.h --- zebra/main.c | 3 +- zebra/rib.h | 10 ++++ zebra/router-id.c | 138 ++++++++++++++++++++++++++++++++-------------- zebra/router-id.h | 5 +- zebra/zserv.c | 7 ++- zebra/zserv.h | 4 +- 6 files changed, 118 insertions(+), 49 deletions(-) diff --git a/zebra/main.c b/zebra/main.c index 92a0c0b31b..95a0e438e8 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -224,6 +224,7 @@ zebra_vrf_new (vrf_id_t vrf_id, void **info) { zvrf = zebra_vrf_alloc (vrf_id); *info = (void *)zvrf; + router_id_init (zvrf); } return 0; @@ -360,7 +361,7 @@ main (int argc, char **argv) rib_init (); zebra_if_init (); zebra_debug_init (); - router_id_init(); + router_id_cmd_init (); zebra_vty_init (); access_list_init (); prefix_list_init (); diff --git a/zebra/rib.h b/zebra/rib.h index b76231f8a9..ddc6a49dcd 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -23,6 +23,7 @@ #ifndef _ZEBRA_RIB_H #define _ZEBRA_RIB_H +#include "linklist.h" #include "prefix.h" #include "table.h" #include "queue.h" @@ -315,6 +316,15 @@ struct zebra_vrf /* Routing tables off of main table for redistribute table */ struct route_table *other_table[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; + + /* 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; }; /* diff --git a/zebra/router-id.c b/zebra/router-id.c index a17cd9e57f..2b470c6dbe 100644 --- a/zebra/router-id.c +++ b/zebra/router-id.c @@ -36,16 +36,12 @@ #include "log.h" #include "table.h" #include "rib.h" +#include "vrf.h" #include "zebra/zserv.h" #include "zebra/router-id.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 */ extern struct zebra_t zebrad; @@ -77,44 +73,55 @@ router_id_bad_address (struct connected *ifc) } void -router_id_get (struct prefix *p) +router_id_get (struct prefix *p, vrf_id_t vrf_id) { struct listnode *node; struct connected *c; + struct zebra_vrf *zvrf = vrf_info_get (vrf_id); p->u.prefix4.s_addr = 0; p->family = AF_INET; p->prefixlen = 32; - if (rid_user_assigned.u.prefix4.s_addr) - p->u.prefix4.s_addr = rid_user_assigned.u.prefix4.s_addr; - else if (!list_isempty (rid_lo_sorted_list)) + if (zvrf->rid_user_assigned.u.prefix4.s_addr) + p->u.prefix4.s_addr = zvrf->rid_user_assigned.u.prefix4.s_addr; + 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); 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); p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; } } static void -router_id_set (struct prefix *p) +router_id_set (struct prefix *p, vrf_id_t vrf_id) { struct prefix p2; struct listnode *node; 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)) - zsend_router_id_update (client, &p2); + zsend_router_id_update (client, &p2, vrf_id); } void @@ -125,28 +132,29 @@ router_id_add_address (struct connected *ifc) struct prefix before; struct prefix after; struct zserv *client; + struct zebra_vrf *zvrf = vrf_info_get (ifc->ifp->vrf_id); if (router_id_bad_address (ifc)) return; - router_id_get (&before); + router_id_get (&before, zvrf->vrf_id); if (!strncmp (ifc->ifp->name, "lo", 2) || !strncmp (ifc->ifp->name, "dummy", 5)) - l = rid_lo_sorted_list; + l = zvrf->rid_lo_sorted_list; else - l = rid_all_sorted_list; + l = zvrf->rid_all_sorted_list; if (!router_id_find_node (l, ifc)) listnode_add_sort (l, ifc); - router_id_get (&after); + router_id_get (&after, zvrf->vrf_id); if (prefix_same (&before, &after)) return; 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 @@ -158,36 +166,51 @@ router_id_del_address (struct connected *ifc) struct prefix before; struct listnode *node; struct zserv *client; + struct zebra_vrf *zvrf = vrf_info_get (ifc->ifp->vrf_id); if (router_id_bad_address (ifc)) return; - router_id_get (&before); + router_id_get (&before, zvrf->vrf_id); if (!strncmp (ifc->ifp->name, "lo", 2) || !strncmp (ifc->ifp->name, "dummy", 5)) - l = rid_lo_sorted_list; + l = zvrf->rid_lo_sorted_list; else - l = rid_all_sorted_list; + l = zvrf->rid_all_sorted_list; if ((c = router_id_find_node (l, ifc))) listnode_delete (l, c); - router_id_get (&after); + router_id_get (&after, zvrf->vrf_id); if (prefix_same (&before, &after)) return; 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 router_id_write (struct vty *vty) { - if (rid_user_assigned.u.prefix4.s_addr) - vty_out (vty, "router-id %s%s", inet_ntoa (rid_user_assigned.u.prefix4), - VTY_NEWLINE); + struct zebra_vrf *zvrf; + vrf_iter_t iter; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + if ((zvrf = vrf_iter2info (iter)) != NULL) + 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, @@ -197,6 +220,7 @@ DEFUN (router_id, "IP address to use for router-id\n") { struct prefix rid; + vrf_id_t vrf_id = VRF_DEFAULT; rid.u.prefix4.s_addr = inet_addr (argv[0]); if (!rid.u.prefix4.s_addr) @@ -205,11 +229,21 @@ DEFUN (router_id, rid.prefixlen = 32; 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; } +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, no_router_id_cmd, "no router-id", @@ -217,16 +251,27 @@ DEFUN (no_router_id, "Remove the manually configured router-id\n") { struct prefix rid; + vrf_id_t vrf_id = VRF_DEFAULT; rid.u.prefix4.s_addr = 0; rid.prefixlen = 0; 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; } +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 router_id_cmp (void *a, void *b) { @@ -237,18 +282,27 @@ router_id_cmp (void *a, void *b) } void -router_id_init (void) +router_id_cmd_init (void) { install_element (CONFIG_NODE, &router_id_cmd); install_element (CONFIG_NODE, &no_router_id_cmd); - - memset (rid_all_sorted_list, 0, sizeof (_rid_all_sorted_list)); - memset (rid_lo_sorted_list, 0, sizeof (_rid_lo_sorted_list)); - memset (&rid_user_assigned, 0, sizeof (rid_user_assigned)); - - rid_all_sorted_list->cmp = router_id_cmp; - rid_lo_sorted_list->cmp = router_id_cmp; - - rid_user_assigned.family = AF_INET; - rid_user_assigned.prefixlen = 32; + install_element (CONFIG_NODE, &router_id_vrf_cmd); + install_element (CONFIG_NODE, &no_router_id_vrf_cmd); +} + +void +router_id_init (struct zebra_vrf *zvrf) +{ + zvrf->rid_all_sorted_list = &zvrf->_rid_all_sorted_list; + zvrf->rid_lo_sorted_list = &zvrf->_rid_lo_sorted_list; + + 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; } diff --git a/zebra/router-id.h b/zebra/router-id.h index be12bf5029..46d300eeac 100644 --- a/zebra/router-id.h +++ b/zebra/router-id.h @@ -33,8 +33,9 @@ extern void router_id_add_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_get(struct prefix *); +extern void router_id_get(struct prefix *, vrf_id_t); #endif diff --git a/zebra/zserv.c b/zebra/zserv.c index 052c797f8b..7a5700210f 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -948,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. */ 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; int blen; @@ -1623,9 +1624,9 @@ zread_router_id_add (struct zserv *client, u_short length) /* Router-id information is needed. */ 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. */ diff --git a/zebra/zserv.h b/zebra/zserv.h index ace3715247..29b3145672 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -151,7 +151,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_redistribute_route (int, struct zserv *, struct prefix *, 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 void zserv_create_header(struct stream *s, uint16_t cmd); From e5bf3e1ed718d5982d5b56209229b669dcd016c9 Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:40:08 +0200 Subject: [PATCH 22/27] lib/vrf: enable / disable a VRF A new API vrf_is_enabled() is defined to check whether a VRF is ready to use, that is, to allocate resources in that VRF. Currently there's only one type of resource: socket. Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell the user when a VRF gets ready or to be unavailable. The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(), which is used to let the VRF be ready to use. Till now, only the default VRF can be enabled, and we need do nothing to enable the default, except calling the hook. The VRF_DISABLE_HOOK callback is called in the new function vrf_disable(), which is used to let the VRF be unusable. Till now, it is called only when the VRF is to be deleted. A new utility vrf_socket() is defined to provide a socket in a given VRF to the user. Till now before introducing a way of VRF realization, only the default VRF is enabled since its birth, and vrf_socket() creates socket for only the default VRF. This patch defines the framework of the VRF APIs. The way they serve the users is: - vrf_is_enabled() is used to tell the user whether a VRF is usable; - users are informed by the VRF_ENABLE_HOOK that a VRF gets usable; they can allocate resources after that; - users are informed by the VRF_DISABLE_HOOK that a VRF is to be unavailable, and they must release the resources instantly; - vrf_socket() is used to provide a socket in a given VRF. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter --- lib/vrf.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++- lib/vrf.h | 9 +++++ 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/lib/vrf.c b/lib/vrf.c index ea14fd3c68..d11a98264c 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -29,6 +29,8 @@ #include "log.h" #include "memory.h" +#define VRF_DEFAULT_NAME "Default-IP-Routing-Table" + struct vrf { /* Identifier, same as the vector index */ @@ -48,11 +50,18 @@ 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) @@ -100,6 +109,9 @@ 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); @@ -129,6 +141,61 @@ vrf_lookup (vrf_id_t vrf_id) 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 **)) @@ -140,6 +207,12 @@ vrf_add_hook (int type, int (*func)(vrf_id_t, void **)) 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; } @@ -281,7 +354,14 @@ vrf_init (void) } /* Set the default VRF name. */ - default_vrf->name = XSTRDUP (MTYPE_VRF_NAME, "Default-IP-Routing-Table"); + 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. */ @@ -299,3 +379,23 @@ vrf_terminate (void) 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; +} + diff --git a/lib/vrf.h b/lib/vrf.h index d7b799875b..653fabf905 100644 --- a/lib/vrf.h +++ b/lib/vrf.h @@ -44,6 +44,8 @@ #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. @@ -114,5 +116,12 @@ extern struct list *vrf_iflist_get (vrf_id_t); 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*/ From a31c5886dda74cab102671d3712fa2070e50d8ed Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:40:09 +0200 Subject: [PATCH 23/27] zebra: add hooks upon enabling / disabling a VRF zebra_vrf_enable() is the callback for VRF_ENABLE_HOOK. It presently needs do nothing. zebra_vrf_disable() is the callback for VRF_DISABLE_HOOK. It presently withdraws routes, shuts down interfaces, and clears the router-id candidates in that VRF. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter --- zebra/main.c | 40 ++++++++++++++++++++++++++++++++++++++++ zebra/rib.h | 1 + zebra/test_main.c | 37 +++++++++++++++++++++++++++++++++++++ zebra/zebra_rib.c | 2 +- 4 files changed, 79 insertions(+), 1 deletion(-) diff --git a/zebra/main.c b/zebra/main.c index 95a0e438e8..22471d3d01 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -230,11 +230,51 @@ zebra_vrf_new (vrf_id_t vrf_id, void **info) return 0; } +/* Callback upon enabling a VRF. */ +static int +zebra_vrf_enable (vrf_id_t vrf_id, void **info) +{ + struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info); + + assert (zvrf); + + return 0; +} + +/* Callback upon disabling a VRF. */ +static int +zebra_vrf_disable (vrf_id_t vrf_id, void **info) +{ + struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info); + struct listnode *list_node; + struct interface *ifp; + + assert (zvrf); + + rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]); + rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), list_node, ifp)) + { + int operative = if_is_operative (ifp); + UNSET_FLAG (ifp->flags, IFF_UP); + if (operative) + if_down (ifp); + } + + list_delete_all_node (zvrf->rid_all_sorted_list); + list_delete_all_node (zvrf->rid_lo_sorted_list); + + return 0; +} + /* Zebra VRF initialization. */ static void zebra_vrf_init (void) { vrf_add_hook (VRF_NEW_HOOK, zebra_vrf_new); + vrf_add_hook (VRF_ENABLE_HOOK, zebra_vrf_enable); + vrf_add_hook (VRF_DISABLE_HOOK, zebra_vrf_disable); vrf_init (); } diff --git a/zebra/rib.h b/zebra/rib.h index ddc6a49dcd..60a39d4727 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -438,6 +438,7 @@ extern void rib_update (vrf_id_t); extern void rib_update_static (vrf_id_t); extern void rib_weed_tables (void); extern void rib_sweep_route (void); +extern void rib_close_table (struct route_table *); extern void rib_close (void); extern void rib_init (void); extern unsigned long rib_score_proto (u_char proto, u_short instance); diff --git a/zebra/test_main.c b/zebra/test_main.c index 0013506b9b..9b83b642d4 100644 --- a/zebra/test_main.c +++ b/zebra/test_main.c @@ -217,11 +217,48 @@ zebra_vrf_new (vrf_id_t vrf_id, void **info) return 0; } +/* Callback upon enabling a VRF. */ +static int +zebra_vrf_enable (vrf_id_t vrf_id, void **info) +{ + struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info); + + assert (zvrf); + + return 0; +} + +/* Callback upon disabling a VRF. */ +static int +zebra_vrf_disable (vrf_id_t vrf_id, void **info) +{ + struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info); + struct listnode *list_node; + struct interface *ifp; + + assert (zvrf); + + rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]); + rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), list_node, ifp)) + { + int operative = if_is_operative (ifp); + UNSET_FLAG (ifp->flags, IFF_UP); + if (operative) + if_down (ifp); + } + + return 0; +} + /* Zebra VRF initialization. */ static void zebra_vrf_init (void) { vrf_add_hook (VRF_NEW_HOOK, zebra_vrf_new); + vrf_add_hook (VRF_ENABLE_HOOK, zebra_vrf_enable); + vrf_add_hook (VRF_DISABLE_HOOK, zebra_vrf_disable); vrf_init (); } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 2b94c6a7c6..ee7abc432c 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -3954,7 +3954,7 @@ rib_score_proto (u_char proto, u_short instance) } /* Close RIB and clean up kernel routes. */ -static void +void rib_close_table (struct route_table *table) { struct route_node *rn; From cd80d74fb275fe68247891d071075f450d4ec41c Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Fri, 22 May 2015 11:40:10 +0200 Subject: [PATCH 24/27] zebra: maintain RTADV per VRF This moves the global variable "rtadv" into the "struct zebra_vrf", so that RTADV feature can work per VRF. * rtadv.c/rtadv.h: Add a proper parameter to the functions so that the entity of the "struct zebra_vrf" and interfaces can be obtained from the specified VRF. The old rtadv_init() is splitted into: - rtadv_cmd_init(): it installs the RTADV commands; is called from main(); - new rtadv_init(): it creates the socket; is called from zebra_vrf_enable(). rtadv_terminate() is added to stop the threads, close the socket and clear the counters. It is called from zebra_vrf_disable(). rtadv_make_socket() now calls vrf_socket() to create a socket in the VRF. * interface.h and rib.h: define the macro RTADV. * main.c: according changes, refer to rtadv.c. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Vincent JARDIN Signed-off-by: David Lamparter Conflicts: zebra/interface.h zebra/rib.h zebra/rtadv.c zebra/rtadv.h --- zebra/interface.h | 2 + zebra/main.c | 9 ++- zebra/rib.h | 27 +++++++++ zebra/rtadv.c | 146 +++++++++++++++++++++++++--------------------- zebra/rtadv.h | 5 +- 5 files changed, 121 insertions(+), 68 deletions(-) diff --git a/zebra/interface.h b/zebra/interface.h index e8456ce59a..ba76d3e845 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -38,11 +38,13 @@ #define IF_ZEBRA_SHUTDOWN_ON 1 /* Router advertisement feature. */ +#ifndef RTADV #if (defined(LINUX_IPV6) && (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1)) || defined(KAME) #ifdef HAVE_RTADV #define RTADV #endif #endif +#endif #ifdef RTADV /* Router advertisement parameter. From RFC4861, RFC6275 and RFC4191. */ diff --git a/zebra/main.c b/zebra/main.c index 22471d3d01..16a11edea3 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -238,6 +238,9 @@ zebra_vrf_enable (vrf_id_t vrf_id, void **info) assert (zvrf); +#ifdef RTADV + rtadv_init (zvrf); +#endif return 0; } @@ -262,6 +265,10 @@ zebra_vrf_disable (vrf_id_t vrf_id, void **info) if_down (ifp); } +#ifdef RTADV + rtadv_terminate (zvrf); +#endif + list_delete_all_node (zvrf->rid_all_sorted_list); list_delete_all_node (zvrf->rid_lo_sorted_list); @@ -406,7 +413,7 @@ main (int argc, char **argv) access_list_init (); prefix_list_init (); #ifdef RTADV - rtadv_init (); + rtadv_cmd_init (); #endif #ifdef HAVE_IRDP irdp_init(); diff --git a/zebra/rib.h b/zebra/rib.h index 60a39d4727..f18b311d47 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -287,6 +287,29 @@ struct static_ipv6 : ((tnexthop) = (nexthop)->next)) \ : (((recursing) = 0),((tnexthop) = (tnexthop)->next))) +/* Router advertisement feature. */ +#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 (HAVE_IPV6) && defined (RTADV) +/* 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; +}; +#endif /* RTADV && HAVE_IPV6 */ + /* Routing table instance. */ struct zebra_vrf { @@ -325,6 +348,10 @@ struct zebra_vrf struct list *rid_all_sorted_list; struct list *rid_lo_sorted_list; struct prefix rid_user_assigned; + +#if defined (HAVE_IPV6) && defined (RTADV) + struct rtadv rtadv; +#endif /* RTADV && HAVE_IPV6 */ }; /* diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 67f6ddb4e9..d48f804f77 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -31,6 +31,7 @@ #include "linklist.h" #include "command.h" #include "privs.h" +#include "vrf.h" #include "zebra/interface.h" #include "zebra/rtadv.h" @@ -62,31 +63,11 @@ extern struct zebra_t zebrad; enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER, 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_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 rtadv_recv_packet (int sock, u_char *buf, int buflen, struct sockaddr_in6 *from, unsigned int *ifindex, @@ -389,24 +370,25 @@ rtadv_send_packet (int sock, struct interface *ifp) static int rtadv_timer (struct thread *thread) { + struct zebra_vrf *zvrf = THREAD_ARG (thread); struct listnode *node, *nnode; struct interface *ifp; struct zebra_if *zif; int period; - rtadv->ra_timer = NULL; - if (rtadv->adv_msec_if_count == 0) + zvrf->rtadv.ra_timer = NULL; + if (zvrf->rtadv.adv_msec_if_count == 0) { period = 1000; /* 1 s */ - rtadv_event (RTADV_TIMER, 1 /* 1 s */); + rtadv_event (zvrf, RTADV_TIMER, 1 /* 1 s */); } else { 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)) continue; @@ -421,7 +403,7 @@ rtadv_timer (struct thread *thread) /* FIXME: using MaxRtrAdvInterval each time isn't what section 6.2.4 of RFC4861 tells to do. */ 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 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 @@ -513,17 +497,17 @@ rtadv_process_advert (u_char *msg, unsigned int len, struct interface *ifp, static void 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 interface *ifp; struct zebra_if *zif; /* Interface search. */ - ifp = if_lookup_by_index (ifindex); + ifp = if_lookup_by_index_vrf (ifindex, vrf_id); if (ifp == NULL) { - zlog_warn ("Unknown interface index: %d", ifindex); + zlog_warn ("Unknown interface index: %d, vrf %u", ifindex, vrf_id); return; } @@ -578,12 +562,13 @@ rtadv_read (struct thread *thread) struct sockaddr_in6 from; unsigned int ifindex = 0; int hoplimit = -1; + struct zebra_vrf *zvrf = THREAD_ARG (thread); sock = THREAD_FD (thread); - rtadv->ra_read = NULL; + zvrf->rtadv.ra_read = NULL; /* Register myself. */ - rtadv_event (RTADV_READ, sock); + rtadv_event (zvrf, RTADV_READ, sock); len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit); @@ -593,13 +578,13 @@ rtadv_read (struct thread *thread) 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; } static int -rtadv_make_socket (void) +rtadv_make_socket (vrf_id_t vrf_id) { int sock; int ret; @@ -609,7 +594,7 @@ rtadv_make_socket (void) zlog_err ("rtadv_make_socket: could not raise privs, %s", 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) ) zlog_err ("rtadv_make_socket: could not lower privs, %s", @@ -731,9 +716,11 @@ DEFUN (ipv6_nd_suppress_ra, { struct interface *ifp; struct zebra_if *zif; + struct zebra_vrf *zvrf; ifp = vty->index; zif = ifp->info; + zvrf = vrf_info_lookup (ifp->vrf_id); if (if_is_loopback (ifp)) { @@ -745,12 +732,12 @@ DEFUN (ipv6_nd_suppress_ra, { zif->rtadv.AdvSendAdvertisements = 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) - rtadv_event (RTADV_STOP, 0); + if (zvrf->rtadv.adv_if_count == 0) + rtadv_event (zvrf, RTADV_STOP, 0); } return CMD_SUCCESS; @@ -766,9 +753,11 @@ DEFUN (no_ipv6_nd_suppress_ra, { struct interface *ifp; struct zebra_if *zif; + struct zebra_vrf *zvrf; ifp = vty->index; zif = ifp->info; + zvrf = vrf_info_lookup (ifp->vrf_id); if (if_is_loopback (ifp)) { @@ -780,12 +769,12 @@ DEFUN (no_ipv6_nd_suppress_ra, { zif->rtadv.AdvSendAdvertisements = 1; 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) - rtadv_event (RTADV_START, rtadv->sock); + if (zvrf->rtadv.adv_if_count == 1) + rtadv_event (zvrf, RTADV_START, zvrf->rtadv.sock); } return CMD_SUCCESS; @@ -802,6 +791,7 @@ DEFUN (ipv6_nd_ra_interval_msec, unsigned interval; struct interface *ifp = (struct interface *) vty->index; 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); 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) - rtadv->adv_msec_if_count--; + zvrf->rtadv.adv_msec_if_count--; if (interval % 1000) - rtadv->adv_msec_if_count++; + zvrf->rtadv.adv_msec_if_count++; zif->rtadv.MaxRtrAdvInterval = interval; zif->rtadv.MinRtrAdvInterval = 0.33 * interval; @@ -834,6 +824,7 @@ DEFUN (ipv6_nd_ra_interval, unsigned interval; struct interface *ifp = (struct interface *) vty->index; 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); if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) @@ -843,7 +834,7 @@ DEFUN (ipv6_nd_ra_interval, } if (zif->rtadv.MaxRtrAdvInterval % 1000) - rtadv->adv_msec_if_count--; + zvrf->rtadv.adv_msec_if_count--; /* convert to milliseconds */ interval = interval * 1000; @@ -865,12 +856,14 @@ DEFUN (no_ipv6_nd_ra_interval, { struct interface *ifp; struct zebra_if *zif; + struct zebra_vrf *zvrf; ifp = (struct interface *) vty->index; zif = ifp->info; + zvrf = vrf_info_lookup (ifp->vrf_id); 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.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL; @@ -1609,9 +1602,6 @@ rtadv_config_write (struct vty *vty, struct interface *ifp) u_char buf[INET6_ADDRSTRLEN]; int interval; - if (! rtadv) - return; - zif = ifp->info; if (! if_is_loopback (ifp)) @@ -1696,16 +1686,18 @@ rtadv_config_write (struct vty *vty, struct interface *ifp) 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) { case RTADV_START: 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) rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer, - NULL, 0); + zvrf, 0); break; case RTADV_STOP: if (rtadv->ra_timer) @@ -1721,17 +1713,17 @@ rtadv_event (enum rtadv_event event, int val) break; case RTADV_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); break; case RTADV_TIMER_MSEC: if (! rtadv->ra_timer) rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer, - NULL, val); + zvrf, val); break; case RTADV_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; default: break; @@ -1740,17 +1732,29 @@ rtadv_event (enum rtadv_event event, int val) } 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 (); - if (sock < 0) - return; +void +rtadv_terminate (struct zebra_vrf *zvrf) +{ + rtadv_event (zvrf, RTADV_STOP, 0); - rtadv = rtadv_new (); - rtadv->sock = sock; + if (zvrf->rtadv.sock >= 0) + { + 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, &no_ipv6_nd_suppress_ra_cmd); install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd); @@ -1845,7 +1849,17 @@ if_leave_all_router (int sock, struct interface *ifp) #else 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.*/; } diff --git a/zebra/rtadv.h b/zebra/rtadv.h index 8cb933e0be..76f98cf2c8 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -59,7 +59,6 @@ struct rtadv_prefix }; extern void rtadv_config_write (struct vty *, struct interface *); -extern void rtadv_init (void); /* RFC4584 Extension to Sockets API for Mobile IPv6 */ @@ -101,4 +100,8 @@ extern const char *rtadv_pref_strs[]; #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 */ From 8f7d9fc0883869bb32f67b4f70f017141d412ccb Mon Sep 17 00:00:00 2001 From: Feng Lu Date: Thu, 3 Jul 2014 18:23:09 +0800 Subject: [PATCH 25/27] zebra, lib/memtypes.c: the netlink sockets work per VRF This patch lets the netlink sockets work per VRF. * The definition of "struct nlsock" is moved into zebra/rib.h. * The previous global variables "netlink" and "netlink_cmd" now become the members of "struct zebra_vrf", and are initialized in zebra_vrf_alloc(). * All relative functions now work for a specific VRF, by adding a new parameter which specifies the working VRF, except those functions in which the VRF ID can be obtained from the interface. * kernel_init(), interface_list() and route_read() are now also working per VRF, and moved from main() to zebra_vrf_enable(). * A new function kernel_terminate() is added to release the netlink sockets. It is called from zebra_vrf_disable(). * Correct VRF ID, instead of the previous VRF_DEFAULT, are now passed to the functions of processing interfaces or route entries. Signed-off-by: Feng Lu Reviewed-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Donald Sharp Conflicts: lib/memtypes.c zebra/rib.h zebra/rt_netlink.c Conflicts: zebra/if_netlink.c zebra/if_sysctl.c zebra/kernel_null.c zebra/rib.h zebra/rt_netlink.c zebra/rt_netlink.h --- lib/memtypes.c | 1 + zebra/if_ioctl.c | 9 +- zebra/if_ioctl_solaris.c | 9 +- zebra/if_netlink.c | 4 +- zebra/if_sysctl.c | 14 ++- zebra/kernel_null.c | 6 +- zebra/kernel_socket.c | 16 ++- zebra/main.c | 8 +- zebra/rib.h | 17 +++ zebra/rt_netlink.c | 244 ++++++++++++++++++++++----------------- zebra/rt_netlink.h | 4 +- zebra/rtread_getmsg.c | 6 +- zebra/rtread_netlink.c | 4 +- zebra/rtread_sysctl.c | 8 +- zebra/test_main.c | 7 +- zebra/zebra_rib.c | 14 +++ zebra/zserv.h | 7 +- 17 files changed, 244 insertions(+), 134 deletions(-) diff --git a/lib/memtypes.c b/lib/memtypes.c index dafd471dd2..fc50443600 100644 --- a/lib/memtypes.c +++ b/lib/memtypes.c @@ -90,6 +90,7 @@ struct memory_list memory_list_zebra[] = { MTYPE_RIB_DEST, "RIB destination" }, { MTYPE_RIB_TABLE_INFO, "RIB table info" }, { MTYPE_RNH, "Nexthop tracking object" }, + { MTYPE_NETLINK_NAME, "Netlink name" }, { -1, NULL }, }; diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index f357e15447..8df877dbaa 100644 --- a/zebra/if_ioctl.c +++ b/zebra/if_ioctl.c @@ -29,8 +29,10 @@ #include "connected.h" #include "memory.h" #include "log.h" +#include "vrf.h" #include "zebra/interface.h" +#include "zebra/rib.h" /* Interface looking up using infamous SIOCGIFCONF. */ static int @@ -442,8 +444,13 @@ interface_info_ioctl () /* Lookup all interface information. */ void -interface_list () +interface_list (struct zebra_vrf *zvrf) { + if (zvrf->vrf_id != VRF_DEFAULT) + { + zlog_warn ("interface_list: ignore VRF %u", zvrf->vrf_id); + return; + } /* Linux can do both proc & ioctl, ioctl is the only way to get interface aliases in 2.2 series kernels. */ #ifdef HAVE_PROC_NET_DEV diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c index fc384ea29a..3f33f749af 100644 --- a/zebra/if_ioctl_solaris.c +++ b/zebra/if_ioctl_solaris.c @@ -30,8 +30,10 @@ #include "memory.h" #include "log.h" #include "privs.h" +#include "vrf.h" #include "zebra/interface.h" +#include "zebra/rib.h" void lifreq_set_name (struct lifreq *, const char *); int if_get_flags_direct (const char *, uint64_t *, unsigned int af); @@ -349,8 +351,13 @@ interface_info_ioctl (struct interface *ifp) /* Lookup all interface information. */ void -interface_list () +interface_list (struct zebra_vrf *zvrf) { + if (zvrf->vrf_id != VRF_DEFAULT) + { + zlog_warn ("interface_list: ignore VRF %u", zvrf->vrf_id); + return; + } interface_list_ioctl (AF_INET); interface_list_ioctl (AF_INET6); interface_list_ioctl (AF_UNSPEC); diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 2016986cb5..9562f2f586 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -27,7 +27,7 @@ /* Interface information read by netlink. */ void -interface_list (void) +interface_list (struct zebra_vrf *zvrf) { - interface_lookup_netlink (); + interface_lookup_netlink (zvrf); } diff --git a/zebra/if_sysctl.c b/zebra/if_sysctl.c index 1150ec1b06..e7b25d1f8f 100644 --- a/zebra/if_sysctl.c +++ b/zebra/if_sysctl.c @@ -29,9 +29,15 @@ #include "memory.h" #include "ioctl.h" #include "log.h" +<<<<<<< HEAD +======= +#include "interface.h" +#include "vrf.h" +>>>>>>> 3c27b5f... zebra, lib/memtypes.c: the netlink sockets work per VRF #include "zebra/rt.h" #include "zebra/kernel_socket.h" +#include "zebra/rib.h" void ifstat_update_sysctl (void) @@ -90,7 +96,7 @@ ifstat_update_sysctl (void) /* Interface listing up function using sysctl(). */ void -interface_list () +interface_list (struct zebra_vrf *zvrf) { caddr_t ref, buf, end; size_t bufsiz; @@ -107,6 +113,12 @@ interface_list () 0 }; + if (zvrf->vrf_id != VRF_DEFAULT) + { + zlog_warn ("interface_list: ignore VRF %u", zvrf->vrf_id); + return; + } + /* Query buffer size. */ if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) { diff --git a/zebra/kernel_null.c b/zebra/kernel_null.c index 5f37e0cc7c..08fef9b309 100644 --- a/zebra/kernel_null.c +++ b/zebra/kernel_null.c @@ -8,6 +8,7 @@ #include "zebra/redistribute.h" #include "zebra/connected.h" #include "zebra/rt_netlink.h" +#include "zebra/rib.h" int kernel_add_ipv4 (struct prefix *a, struct rib *b) { return 0; } int kernel_update_ipv4 (struct prefix *a, struct rib *b) { return 0; } @@ -54,9 +55,10 @@ int netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llale return 0; } -void kernel_init (void) { return; } +void kernel_init (struct zebra_vrf *zvrf) { return; } +void kernel_terminate (struct zebra_vrf *zvrf) { return; } #ifdef HAVE_SYS_WEAK_ALIAS_PRAGMA #pragma weak route_read = kernel_init #else -void route_read (void) { return; } +void route_read (struct zebra_vrf *zvrf) { return; } #endif diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index a1002a4d86..7b4f70fa83 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -38,6 +38,7 @@ #include "zebra/zserv.h" #include "zebra/debug.h" #include "zebra/kernel_socket.h" +#include "zebra/rib.h" extern struct zebra_privs_t zserv_privs; extern struct zebra_t zebrad; @@ -1262,8 +1263,11 @@ kernel_read (struct thread *thread) /* Make routing socket. */ static void -routing_socket (void) +routing_socket (struct zebra_vrf *zvrf) { + if (zvrf->vrf_id != VRF_DEFAULT) + return; + if ( zserv_privs.change (ZPRIVS_RAISE) ) zlog_err ("routing_socket: Can't raise privileges"); @@ -1294,7 +1298,13 @@ routing_socket (void) /* Exported interface function. This function simply calls routing_socket (). */ void -kernel_init (void) +kernel_init (struct zebra_vrf *zvrf) { - routing_socket (); + routing_socket (zvrf); +} + +void +kernel_terminate (struct zebra_vrf *zvrf) +{ + return; } diff --git a/zebra/main.c b/zebra/main.c index 16a11edea3..4b2a89856e 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -241,6 +241,10 @@ zebra_vrf_enable (vrf_id_t vrf_id, void **info) #ifdef RTADV rtadv_init (zvrf); #endif + kernel_init (zvrf); + interface_list (zvrf); + route_read (zvrf); + return 0; } @@ -268,6 +272,7 @@ zebra_vrf_disable (vrf_id_t vrf_id, void **info) #ifdef RTADV rtadv_terminate (zvrf); #endif + kernel_terminate (zvrf); list_delete_all_node (zvrf->rid_all_sorted_list); list_delete_all_node (zvrf->rid_lo_sorted_list); @@ -428,9 +433,6 @@ main (int argc, char **argv) /* Initialize VRF module, and make kernel routing socket. */ zebra_vrf_init (); - kernel_init (); - interface_list (); - route_read (); #ifdef HAVE_SNMP zebra_snmp_init (); diff --git a/zebra/rib.h b/zebra/rib.h index f18b311d47..25ab68df13 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -310,6 +310,17 @@ struct rtadv }; #endif /* RTADV && HAVE_IPV6 */ +#ifdef HAVE_NETLINK +/* Socket interface to kernel */ +struct nlsock +{ + int sock; + int seq; + struct sockaddr_nl snl; + const char *name; +}; +#endif + /* Routing table instance. */ struct zebra_vrf { @@ -340,6 +351,12 @@ struct zebra_vrf /* Routing tables off of main table for redistribute table */ struct route_table *other_table[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; +#ifdef HAVE_NETLINK + struct nlsock netlink; /* kernel messages */ + struct nlsock netlink_cmd; /* command channel */ + struct thread *t_netlink; +#endif + /* 2nd pointer type used primarily to quell a warning on * ALL_LIST_ELEMENTS_RO */ diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index e312801e55..cad367808d 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -47,16 +47,6 @@ #include "rt_netlink.h" -/* Socket interface to kernel */ -struct nlsock -{ - int sock; - int seq; - struct sockaddr_nl snl; - const char *name; -} netlink = { -1, 0, {0}, "netlink-listen"}, /* kernel messages */ - netlink_cmd = { -1, 0, {0}, "netlink-cmd"}; /* command channel */ - static const struct message nlmsg_str[] = { {RTM_NEWROUTE, "RTM_NEWROUTE"}, {RTM_DELROUTE, "RTM_DELROUTE"}, @@ -156,7 +146,7 @@ netlink_recvbuf (struct nlsock *nl, uint32_t newsize) /* Make socket for Linux netlink interface. */ static int -netlink_socket (struct nlsock *nl, unsigned long groups) +netlink_socket (struct nlsock *nl, unsigned long groups, vrf_id_t vrf_id) { int ret; struct sockaddr_nl snl; @@ -170,7 +160,7 @@ netlink_socket (struct nlsock *nl, unsigned long groups) return -1; } - sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + sock = vrf_socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, vrf_id); if (sock < 0) { zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name, @@ -273,8 +263,9 @@ netlink_request (int family, int type, struct nlsock *nl) /* Receive message from netlink interface and pass those information to the given function. */ static int -netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), - struct nlsock *nl) +netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, + vrf_id_t), + struct nlsock *nl, struct zebra_vrf *zvrf) { int status; int ret = 0; @@ -363,7 +354,7 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), } /* Deal with errors that occur because of races in link handling */ - if (nl == &netlink_cmd + if (nl == &zvrf->netlink_cmd && ((msg_type == RTM_DELROUTE && (-errnum == ENODEV || -errnum == ESRCH)) || (msg_type == RTM_NEWROUTE && -errnum == EEXIST))) @@ -376,7 +367,7 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), return 0; } - if (nl == &netlink_cmd + if (nl == &zvrf->netlink_cmd && msg_type == RTM_NEWROUTE && -errnum == ESRCH) { /* This is known to happen in some situations, don't log @@ -407,16 +398,17 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), /* skip unsolicited messages originating from command socket * linux sets the originators port-id for {NEW|DEL}ADDR messages, * so this has to be checked here. */ - if (nl != &netlink_cmd && h->nlmsg_pid == netlink_cmd.snl.nl_pid + if (nl != &zvrf->netlink_cmd + && h->nlmsg_pid == zvrf->netlink_cmd.snl.nl_pid && (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)) { if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug ("netlink_parse_info: %s packet comes from %s", - netlink_cmd.name, nl->name); + zvrf->netlink_cmd.name, nl->name); continue; } - error = (*filter) (&snl, h); + error = (*filter) (&snl, h, zvrf->vrf_id); if (error < 0) { zlog (NULL, LOG_ERR, "%s filter function error", nl->name); @@ -487,7 +479,8 @@ netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp) /* Called from interface_lookup_netlink(). This function is only used during bootstrap. */ static int -netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) +netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, + vrf_id_t vrf_id) { int len; struct ifinfomsg *ifi; @@ -523,7 +516,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) name = (char *) RTA_DATA (tb[IFLA_IFNAME]); /* Add interface. */ - ifp = if_get_by_name (name); + ifp = if_get_by_name_vrf (name, vrf_id); set_ifindex(ifp, ifi->ifi_index); ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); @@ -540,7 +533,8 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) /* Lookup interface IPv4/IPv6 address. */ static int -netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) +netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h, + vrf_id_t vrf_id) { int len; struct ifaddrmsg *ifa; @@ -570,19 +564,19 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) memset (tb, 0, sizeof tb); netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len); - ifp = if_lookup_by_index (ifa->ifa_index); + ifp = if_lookup_by_index_vrf (ifa->ifa_index, vrf_id); if (ifp == NULL) { - zlog_err ("netlink_interface_addr can't find interface by index %d", - ifa->ifa_index); + zlog_err ("netlink_interface_addr can't find interface by index %d vrf %u", + ifa->ifa_index, vrf_id); return -1; } if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */ { char buf[BUFSIZ]; - zlog_debug ("netlink_interface_addr %s %s:", - lookup (nlmsg_str, h->nlmsg_type), ifp->name); + zlog_debug ("netlink_interface_addr %s %s vrf %u:", + lookup (nlmsg_str, h->nlmsg_type), ifp->name, vrf_id); if (tb[IFA_LOCAL]) zlog_debug (" IFA_LOCAL %s/%d", inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]), @@ -675,7 +669,8 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) /* Looking up routing table by netlink interface. */ static int -netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) +netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, + vrf_id_t vrf_id) { int len; struct rtmsg *rtm; @@ -756,7 +751,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) if (!tb[RTA_MULTIPATH]) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, src, index, - VRF_DEFAULT, table, metric, 0, SAFI_UNICAST); + vrf_id, table, metric, 0, SAFI_UNICAST); else { /* This is a multipath route */ @@ -772,7 +767,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) rib->distance = 0; rib->flags = flags; rib->metric = metric; - rib->vrf_id = VRF_DEFAULT; + rib->vrf_id = vrf_id; rib->table = table; rib->nexthop_num = 0; rib->uptime = time (NULL); @@ -823,7 +818,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) memcpy (&p.prefix, dest, 16); p.prefixlen = rtm->rtm_dst_len; - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, index, VRF_DEFAULT, + rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, index, vrf_id, table, metric, 0, SAFI_UNICAST); } #endif /* HAVE_IPV6 */ @@ -848,7 +843,8 @@ static const struct message rtproto_str[] = { /* Routing information change from the kernel. */ static int -netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) +netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, + vrf_id_t vrf_id) { int len; struct rtmsg *rtm; @@ -870,18 +866,19 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) { /* If this is not route add/delete message print warning. */ - zlog_warn ("Kernel message: %d\n", h->nlmsg_type); + zlog_warn ("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id); return 0; } /* Connected route. */ if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s %s %s proto %s", + zlog_debug ("%s %s %s proto %s vrf %u", h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", rtm->rtm_family == AF_INET ? "ipv4" : "ipv6", rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast", - lookup (rtproto_str, rtm->rtm_protocol)); + lookup (rtproto_str, rtm->rtm_protocol), + vrf_id); if (rtm->rtm_type != RTN_UNICAST) { @@ -913,7 +910,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (rtm->rtm_src_len != 0) { - zlog_warn ("netlink_route_change(): no src len"); + zlog_warn ("netlink_route_change(): no src len, vrf %u", vrf_id); return 0; } @@ -949,18 +946,16 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (IS_ZEBRA_DEBUG_KERNEL) { - if (h->nlmsg_type == RTM_NEWROUTE) - zlog_debug ("RTM_NEWROUTE %s/%d", - inet_ntoa (p.prefix), p.prefixlen); - else - zlog_debug ("RTM_DELROUTE %s/%d", - inet_ntoa (p.prefix), p.prefixlen); + char buf[BUFSIZ]; + zlog_debug ("%s %s vrf %u", + h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", + prefix2str (&p, buf, sizeof(buf)), vrf_id); } if (h->nlmsg_type == RTM_NEWROUTE) { if (!tb[RTA_MULTIPATH]) - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, src, index, VRF_DEFAULT, + rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, src, index, vrf_id, table, metric, 0, SAFI_UNICAST); else { @@ -977,7 +972,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) rib->distance = 0; rib->flags = 0; rib->metric = metric; - rib->vrf_id = VRF_DEFAULT; + rib->vrf_id = vrf_id; rib->table = table; rib->nexthop_num = 0; rib->uptime = time (NULL); @@ -1023,7 +1018,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) } else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, - VRF_DEFAULT, table, SAFI_UNICAST); + vrf_id, table, SAFI_UNICAST); } #ifdef HAVE_IPV6 @@ -1038,22 +1033,17 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (IS_ZEBRA_DEBUG_KERNEL) { - if (h->nlmsg_type == RTM_NEWROUTE) - zlog_debug ("RTM_NEWROUTE %s/%d", - inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ), - p.prefixlen); - else - zlog_debug ("RTM_DELROUTE %s/%d", - inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ), - p.prefixlen); + zlog_debug ("%s %s vrf %u", + h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE", + prefix2str (&p, buf, sizeof(buf)), vrf_id); } if (h->nlmsg_type == RTM_NEWROUTE) - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, index, VRF_DEFAULT, + rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, &p, gate, index, vrf_id, table, metric, 0, SAFI_UNICAST); else rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, gate, index, - VRF_DEFAULT, table, SAFI_UNICAST); + vrf_id, table, SAFI_UNICAST); } #endif /* HAVE_IPV6 */ @@ -1061,7 +1051,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) } static int -netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) +netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, + vrf_id_t vrf_id) { int len; struct ifinfomsg *ifi; @@ -1074,8 +1065,8 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) { /* If this is not link add/delete message so print warning. */ - zlog_warn ("netlink_link_change: wrong kernel message %d\n", - h->nlmsg_type); + zlog_warn ("netlink_link_change: wrong kernel message %d vrf %u\n", + h->nlmsg_type, vrf_id); return 0; } @@ -1092,7 +1083,8 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) { if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__); + zlog_debug ("%s: ignoring IFLA_WIRELESS message, vrf %u", __func__, + vrf_id); return 0; } #endif /* IFLA_WIRELESS */ @@ -1104,12 +1096,12 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) /* Add interface. */ if (h->nlmsg_type == RTM_NEWLINK) { - ifp = if_lookup_by_name (name); + ifp = if_lookup_by_name_vrf (name, vrf_id); if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) { if (ifp == NULL) - ifp = if_get_by_name (name); + ifp = if_get_by_name_vrf (name, vrf_id); set_ifindex(ifp, ifi->ifi_index); ifp->flags = ifi->ifi_flags & 0x0000fffff; @@ -1150,12 +1142,12 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) else { /* RTM_DELLINK. */ - ifp = if_lookup_by_name (name); + ifp = if_lookup_by_name_vrf (name, vrf_id); if (ifp == NULL) { - zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find", - name); + zlog_warn ("interface %s vrf %u is deleted but can't find", + name, vrf_id); return 0; } @@ -1166,7 +1158,8 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) } static int -netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h) +netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h, + vrf_id_t vrf_id) { /* JF: Ignore messages that aren't from the kernel */ if ( snl->nl_pid != 0 ) @@ -1178,25 +1171,26 @@ netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h) switch (h->nlmsg_type) { case RTM_NEWROUTE: - return netlink_route_change (snl, h); + return netlink_route_change (snl, h, vrf_id); break; case RTM_DELROUTE: - return netlink_route_change (snl, h); + return netlink_route_change (snl, h, vrf_id); break; case RTM_NEWLINK: - return netlink_link_change (snl, h); + return netlink_link_change (snl, h, vrf_id); break; case RTM_DELLINK: - return netlink_link_change (snl, h); + return netlink_link_change (snl, h, vrf_id); break; case RTM_NEWADDR: - return netlink_interface_addr (snl, h); + return netlink_interface_addr (snl, h, vrf_id); break; case RTM_DELADDR: - return netlink_interface_addr (snl, h); + return netlink_interface_addr (snl, h, vrf_id); break; default: - zlog_warn ("Unknown netlink nlmsg_type %d\n", h->nlmsg_type); + zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type, + vrf_id); break; } return 0; @@ -1204,32 +1198,32 @@ netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h) /* Interface lookup by netlink socket. */ int -interface_lookup_netlink (void) +interface_lookup_netlink (struct zebra_vrf *zvrf) { int ret; /* Get interface information. */ - ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd); + ret = netlink_request (AF_PACKET, RTM_GETLINK, &zvrf->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_interface, &netlink_cmd); + ret = netlink_parse_info (netlink_interface, &zvrf->netlink_cmd, zvrf); if (ret < 0) return ret; /* Get IPv4 address of the interfaces. */ - ret = netlink_request (AF_INET, RTM_GETADDR, &netlink_cmd); + ret = netlink_request (AF_INET, RTM_GETADDR, &zvrf->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd); + ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, zvrf); if (ret < 0) return ret; #ifdef HAVE_IPV6 /* Get IPv6 address of the interfaces. */ - ret = netlink_request (AF_INET6, RTM_GETADDR, &netlink_cmd); + ret = netlink_request (AF_INET6, RTM_GETADDR, &zvrf->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd); + ret = netlink_parse_info (netlink_interface_addr, &zvrf->netlink_cmd, zvrf); if (ret < 0) return ret; #endif /* HAVE_IPV6 */ @@ -1240,24 +1234,24 @@ interface_lookup_netlink (void) /* Routing table read function using netlink interface. Only called bootstrap time. */ int -netlink_route_read (void) +netlink_route_read (struct zebra_vrf *zvrf) { int ret; /* Get IPv4 routing table. */ - ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd); + ret = netlink_request (AF_INET, RTM_GETROUTE, &zvrf->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_routing_table, &netlink_cmd); + ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, zvrf); if (ret < 0) return ret; #ifdef HAVE_IPV6 /* Get IPv6 routing table. */ - ret = netlink_request (AF_INET6, RTM_GETROUTE, &netlink_cmd); + ret = netlink_request (AF_INET6, RTM_GETROUTE, &zvrf->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_routing_table, &netlink_cmd); + ret = netlink_parse_info (netlink_routing_table, &zvrf->netlink_cmd, zvrf); if (ret < 0) return ret; #endif /* HAVE_IPV6 */ @@ -1330,15 +1324,17 @@ addattr32 (struct nlmsghdr *n, unsigned int maxlen, int type, int data) } static int -netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h) +netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h, + vrf_id_t vrf_id) { - zlog_warn ("netlink_talk: ignoring message type 0x%04x", h->nlmsg_type); + zlog_warn ("netlink_talk: ignoring message type 0x%04x vrf %u", h->nlmsg_type, + vrf_id); return 0; } /* sendmsg() to netlink socket then recvmsg(). */ static int -netlink_talk (struct nlmsghdr *n, struct nlsock *nl) +netlink_talk (struct nlmsghdr *n, struct nlsock *nl, struct zebra_vrf *zvrf) { int status; struct sockaddr_nl snl; @@ -1388,7 +1384,7 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl) * Get reply from netlink socket. * The reply should either be an acknowlegement or an error. */ - return netlink_parse_info (netlink_talk_filter, nl); + return netlink_parse_info (netlink_talk_filter, nl, zvrf); } /* Routing table change via netlink interface. */ @@ -1401,6 +1397,8 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate, struct sockaddr_nl snl; int discard; + struct zebra_vrf *zvrf = vrf_info_lookup (VRF_DEFAULT); //Pending + struct { struct nlmsghdr n; @@ -1462,7 +1460,7 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate, snl.nl_family = AF_NETLINK; /* Talk to netlink socket. */ - ret = netlink_talk (&req.n, &netlink_cmd); + ret = netlink_talk (&req.n, &zvrf->netlink_cmd, VRF_DEFAULT); if (ret < 0) return -1; @@ -1763,11 +1761,12 @@ _netlink_route_debug( struct prefix *p, struct nexthop *nexthop, const char *routedesc, - int family) + int family, + struct zebra_vrf *zvrf) { if (IS_ZEBRA_DEBUG_KERNEL) { - zlog_debug ("netlink_route_multipath() (%s): %s %s/%d type %s", + zlog_debug ("netlink_route_multipath() (%s): %s %s/%d vrf %u type %s", routedesc, lookup (nlmsg_str, cmd), #ifdef HAVE_IPV6 @@ -1776,7 +1775,7 @@ _netlink_route_debug( #else inet_ntoa (p->u.prefix4), #endif /* HAVE_IPV6 */ - p->prefixlen, nexthop_type_to_str (nexthop->type)); + p->prefixlen, zvrf->vrf_id, nexthop_type_to_str (nexthop->type)); } } @@ -1789,6 +1788,8 @@ netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen) char buf[256]; } req; + struct zebra_vrf *zvrf = vrf_info_lookup (VRF_DEFAULT); //Pending + memset(&req.n, 0, sizeof(req.n)); memset(&req.ndm, 0, sizeof(req.ndm)); @@ -1803,7 +1804,7 @@ netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen) addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4); addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); - return netlink_talk (&req.n, &netlink_cmd); + return netlink_talk (&req.n, &zvrf->netlink_cmd, VRF_DEFAULT); } /* Routing table change via netlink interface. */ @@ -1829,6 +1830,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, char buf[NL_PKT_BUF_SIZE]; } req; + struct zebra_vrf *zvrf = vrf_info_lookup (rib->vrf_id); + memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); bytelen = (family == AF_INET ? 4 : 16); @@ -1950,7 +1953,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, { routedesc = recursing ? "recursive, 1 hop" : "single hop"; - _netlink_route_debug(cmd, p, nexthop, routedesc, family); + _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf); _netlink_route_build_singlepath(routedesc, bytelen, nexthop, &req.n, &req.r, sizeof req, cmd); @@ -2031,7 +2034,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, nexthop_num++; _netlink_route_debug(cmd, p, nexthop, - routedesc, family); + routedesc, family, zvrf); _netlink_route_build_multipath(routedesc, bytelen, nexthop, rta, rtnh, &req.r, &src1); rtnh = RTNH_NEXT (rtnh); @@ -2079,7 +2082,7 @@ skip: snl.nl_family = AF_NETLINK; /* Talk to netlink socket. */ - return netlink_talk (&req.n, &netlink_cmd); + return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf); } int @@ -2142,6 +2145,8 @@ netlink_address (int cmd, int family, struct interface *ifp, char buf[NL_PKT_BUF_SIZE]; } req; + struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id); + p = ifc->address; memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); @@ -2174,7 +2179,7 @@ netlink_address (int cmd, int family, struct interface *ifp, addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label, strlen (ifc->label) + 1); - return netlink_talk (&req.n, &netlink_cmd); + return netlink_talk (&req.n, &zvrf->netlink_cmd, zvrf); } int @@ -2196,8 +2201,10 @@ extern struct thread_master *master; static int kernel_read (struct thread *thread) { - netlink_parse_info (netlink_information_fetch, &netlink); - thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); + struct zebra_vrf *zvrf = (struct zebra_vrf *)THREAD_ARG (thread); + netlink_parse_info (netlink_information_fetch, &zvrf->netlink, zvrf); + zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf, + zvrf->netlink.sock); return 0; } @@ -2236,7 +2243,7 @@ static void netlink_install_filter (int sock, __u32 pid) /* Exported interface function. This function simply calls netlink_socket (). */ void -kernel_init (void) +kernel_init (struct zebra_vrf *zvrf) { unsigned long groups; @@ -2244,23 +2251,42 @@ kernel_init (void) #ifdef HAVE_IPV6 groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR; #endif /* HAVE_IPV6 */ - netlink_socket (&netlink, groups); - netlink_socket (&netlink_cmd, 0); + netlink_socket (&zvrf->netlink, groups, zvrf->vrf_id); + netlink_socket (&zvrf->netlink_cmd, 0, zvrf->vrf_id); /* Register kernel socket. */ - if (netlink.sock > 0) + if (zvrf->netlink.sock > 0) { /* Only want non-blocking on the netlink event socket */ - if (fcntl (netlink.sock, F_SETFL, O_NONBLOCK) < 0) - zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", netlink.name, - safe_strerror (errno)); + if (fcntl (zvrf->netlink.sock, F_SETFL, O_NONBLOCK) < 0) + zlog_err ("Can't set %s socket flags: %s", zvrf->netlink.name, + safe_strerror (errno)); /* Set receive buffer size if it's set from command line */ if (nl_rcvbufsize) - netlink_recvbuf (&netlink, nl_rcvbufsize); + netlink_recvbuf (&zvrf->netlink, nl_rcvbufsize); - netlink_install_filter (netlink.sock, netlink_cmd.snl.nl_pid); - thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); + netlink_install_filter (zvrf->netlink.sock, zvrf->netlink_cmd.snl.nl_pid); + zvrf->t_netlink = thread_add_read (zebrad.master, kernel_read, zvrf, + zvrf->netlink.sock); + } +} + +void +kernel_terminate (struct zebra_vrf *zvrf) +{ + THREAD_READ_OFF (zvrf->t_netlink); + + if (zvrf->netlink.sock >= 0) + { + close (zvrf->netlink.sock); + zvrf->netlink.sock = -1; + } + + if (zvrf->netlink_cmd.sock >= 0) + { + close (zvrf->netlink_cmd.sock); + zvrf->netlink_cmd.sock = -1; } } diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index 5b1b48cb0a..d45d22f936 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -44,8 +44,8 @@ nl_rtproto_to_str (u_char rtproto); int netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen); -extern int netlink_route_read(void); -extern int interface_lookup_netlink(void); +extern int interface_lookup_netlink (struct zebra_vrf *zvrf); +extern int netlink_route_read (struct zebra_vrf *zvrf); #endif /* HAVE_NETLINK */ diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index f9bfb338a0..6975390415 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -95,7 +95,7 @@ handle_route_entry (mib2_ipRouteEntry_t *routeEntry) } void -route_read (void) +route_read (struct zebra_vrf *zvrf) { char storage[RT_BUFSIZ]; @@ -110,6 +110,10 @@ route_read (void) struct strbuf msgdata; int flags, dev, retval, process; + if (zvrf->vrf_id != VRF_DEFAULT) { + return; + } + if ((dev = open (_PATH_GETMSG_ROUTE, O_RDWR)) == -1) { zlog_warn ("can't open %s: %s", _PATH_GETMSG_ROUTE, safe_strerror (errno)); diff --git a/zebra/rtread_netlink.c b/zebra/rtread_netlink.c index 09191d517b..5b26449798 100644 --- a/zebra/rtread_netlink.c +++ b/zebra/rtread_netlink.c @@ -25,7 +25,7 @@ #include "zebra/zserv.h" #include "zebra/rt_netlink.h" -void route_read (void) +void route_read (struct zebra_vrf *zvrf) { - netlink_route_read (); + netlink_route_read (zvrf); } diff --git a/zebra/rtread_sysctl.c b/zebra/rtread_sysctl.c index 69d45950ae..2a9601a304 100644 --- a/zebra/rtread_sysctl.c +++ b/zebra/rtread_sysctl.c @@ -24,6 +24,7 @@ #include "memory.h" #include "log.h" +#include "vrf.h" #include "zebra/zserv.h" #include "zebra/rt.h" @@ -31,7 +32,7 @@ /* Kernel routing table read up by sysctl function. */ void -route_read (void) +route_read (struct zebra_vrf *zvrf) { caddr_t buf, end, ref; size_t bufsiz; @@ -47,7 +48,10 @@ route_read (void) NET_RT_DUMP, 0 }; - + + if (zvrf->vrf_id != VRF_DEFAULT) + return; + /* Get buffer size. */ if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) { diff --git a/zebra/test_main.c b/zebra/test_main.c index 9b83b642d4..027d2a1580 100644 --- a/zebra/test_main.c +++ b/zebra/test_main.c @@ -225,6 +225,9 @@ zebra_vrf_enable (vrf_id_t vrf_id, void **info) assert (zvrf); + kernel_init (zvrf); + route_read (zvrf); + return 0; } @@ -249,6 +252,8 @@ zebra_vrf_disable (vrf_id_t vrf_id, void **info) if_down (ifp); } + kernel_terminate (zvrf); + return 0; } @@ -363,8 +368,6 @@ main (int argc, char **argv) /* Make kernel routing socket. */ zebra_vrf_init (); - kernel_init (); - route_read (); zebra_vty_init(); /* Configuration file read*/ diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index ee7abc432c..5fd6545ffe 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -4135,6 +4135,9 @@ struct zebra_vrf * zebra_vrf_alloc (vrf_id_t vrf_id) { struct zebra_vrf *zvrf; +#ifdef HAVE_NETLINK + char nl_name[64]; +#endif zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf)); @@ -4157,6 +4160,17 @@ zebra_vrf_alloc (vrf_id_t vrf_id) /* Set VRF ID */ zvrf->vrf_id = vrf_id; +#ifdef HAVE_NETLINK + /* Initialize netlink sockets */ + snprintf (nl_name, 64, "netlink-listen (vrf %u)", vrf_id); + zvrf->netlink.sock = -1; + zvrf->netlink.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name); + + snprintf (nl_name, 64, "netlink-cmd (vrf %u)", vrf_id); + zvrf->netlink_cmd.sock = -1; + zvrf->netlink_cmd.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name); +#endif + return zvrf; } diff --git a/zebra/zserv.h b/zebra/zserv.h index 29b3145672..f4da43d0b0 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -134,9 +134,10 @@ extern void zebra_if_init (void); extern void zebra_zserv_socket_init (char *path); extern void hostinfo_get (void); extern void rib_init (void); -extern void interface_list (void); -extern void kernel_init (void); -extern void route_read (void); +extern void interface_list (struct zebra_vrf *); +extern void route_read (struct zebra_vrf *); +extern void kernel_init (struct zebra_vrf *); +extern void kernel_terminate (struct zebra_vrf *); extern void zebra_route_map_init (void); extern void zebra_snmp_init (void); extern void zebra_vty_init (void); From 92955671de04097089fc3fd62dda351ab00b0ce6 Mon Sep 17 00:00:00 2001 From: Vipin Kumar Date: Fri, 30 Oct 2015 02:12:14 -0700 Subject: [PATCH 26/27] zebra_vrf lookup fix in upstream VRF patches Ticket: Reviewed By: Testing Done: --- zebra/zebra_rib.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 5fd6545ffe..ffa3161f2b 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -79,9 +79,6 @@ static const struct /* no entry/default: 150 */ }; -/* Vector for routing table. */ -static vector zebra_vrf_vector; - /* * nexthop_type_to_str */ @@ -4178,7 +4175,7 @@ zebra_vrf_alloc (vrf_id_t vrf_id) struct zebra_vrf * zebra_vrf_lookup (vrf_id_t vrf_id) { - return vector_lookup (zebra_vrf_vector, vrf_id); + return vrf_info_lookup (vrf_id); } /* Lookup the routing table in an enabled VRF. */ From 4670bdadfea2ab129cd5632720d5f9c7748543a6 Mon Sep 17 00:00:00 2001 From: Vipin Kumar Date: Fri, 30 Oct 2015 03:05:03 -0700 Subject: [PATCH 27/27] Fixing a few compile errors Ticket: Reviewed By: Testing Done: --- babeld/babel_interface.c | 3 ++- zebra/redistribute.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c index ace28127ff..c7c1527481 100644 --- a/babeld/babel_interface.c +++ b/babeld/babel_interface.c @@ -55,6 +55,7 @@ THE SOFTWARE. #include "neighbour.h" #include "route.h" #include "xroute.h" +#include "vrf.h" #define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0) @@ -878,7 +879,7 @@ void babel_if_init () { /* initialize interface list */ - if_init(); + vrf_init(); if_add_hook (IF_NEW_HOOK, babel_if_new_hook); if_add_hook (IF_DELETE_HOOK, babel_if_delete_hook); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 4b4db1dcee..01b85700f2 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -500,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, gate, &nhop->src.ipv4, - nhop->ifindex, zebrad.rtm_table_default, + nhop->ifindex, rib->vrf_id, zebrad.rtm_table_default, rib->metric, zebra_import_table_distance[AFI_IP][rib->table], SAFI_UNICAST); @@ -540,7 +540,7 @@ zebra_del_import_table_entry (struct route_node *rn, struct rib *rib) p4.prefix = rn->p.u.prefix4; 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 */