diff options
66 files changed, 1252 insertions, 1701 deletions
@@ -2,7 +2,7 @@ Quagga is free software that manages various IPv4 and IPv6 routing protocols. Currently Quagga supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1, -RIPv2, and RIPng as well as very early support for IS-IS. +RIPv2, RIPng, PIM-SSM and LDP as well as very early support for IS-IS. See the file INSTALL.quagga.txt for building and installation instructions. diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 2f2ea3ae4..60a647533 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -172,8 +172,7 @@ peer_xfer_conn(struct peer *from_peer) peer->hostname = NULL; } - peer->hostname = XSTRDUP(MTYPE_BGP_PEER_HOST, from_peer->hostname); - XFREE(MTYPE_BGP_PEER_HOST, from_peer->hostname); + peer->hostname = from_peer->hostname; from_peer->hostname = NULL; } @@ -185,8 +184,7 @@ peer_xfer_conn(struct peer *from_peer) peer->domainname= NULL; } - peer->domainname = XSTRDUP(MTYPE_BGP_PEER_HOST, from_peer->domainname); - XFREE(MTYPE_BGP_PEER_HOST, from_peer->domainname); + peer->domainname = from_peer->domainname; from_peer->domainname = NULL; } diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 50ca7eda4..91eacc932 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -308,38 +308,33 @@ bgp_exit (int status) } static int -bgp_vrf_new (vrf_id_t vrf_id, const char *name, void **info) +bgp_vrf_new (struct vrf *vrf) { if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug ("VRF Created: %s(%d)", name, vrf_id); + zlog_debug ("VRF Created: %s(%d)", vrf->name, vrf->vrf_id); return 0; } static int -bgp_vrf_delete (vrf_id_t vrf_id, const char *name, void **info) +bgp_vrf_delete (struct vrf *vrf) { if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug ("VRF Deletion: %s(%d)", name, vrf_id); + zlog_debug ("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id); return 0; } static int -bgp_vrf_enable (vrf_id_t vrf_id, const char *name, void **info) +bgp_vrf_enable (struct vrf *vrf) { - struct vrf *vrf; struct bgp *bgp; vrf_id_t old_vrf_id; - vrf = vrf_lookup (vrf_id); - if (!vrf) // unexpected - return -1; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("VRF enable add %s id %d", name, vrf_id); + zlog_debug("VRF enable add %s id %d", vrf->name, vrf->vrf_id); - bgp = bgp_lookup_by_name(name); + bgp = bgp_lookup_by_name (vrf->name); if (bgp) { old_vrf_id = bgp->vrf_id; @@ -356,23 +351,18 @@ bgp_vrf_enable (vrf_id_t vrf_id, const char *name, void **info) } static int -bgp_vrf_disable (vrf_id_t vrf_id, const char *name, void **info) +bgp_vrf_disable (struct vrf *vrf) { - struct vrf *vrf; struct bgp *bgp; vrf_id_t old_vrf_id; - if (vrf_id == VRF_DEFAULT) + if (vrf->vrf_id == VRF_DEFAULT) return 0; - vrf = vrf_lookup (vrf_id); - if (!vrf) // unexpected - return -1; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("VRF disable %s id %d", name, vrf_id); + zlog_debug("VRF disable %s id %d", vrf->name, vrf->vrf_id); - bgp = bgp_lookup_by_name(name); + bgp = bgp_lookup_by_name (vrf->name); if (bgp) { old_vrf_id = bgp->vrf_id; diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 493655d7f..a77e92c17 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -113,6 +113,12 @@ bgp_address_hash_alloc (void *p) return addr; } +static void +bgp_address_hash_free (void *addr) +{ + XFREE (MTYPE_BGP_ADDR, addr); +} + static unsigned int bgp_address_hash_key_make (void *p) { @@ -142,7 +148,7 @@ bgp_address_destroy (struct bgp *bgp) { if (bgp->address_hash == NULL) return; - hash_clean(bgp->address_hash, NULL); + hash_clean(bgp->address_hash, bgp_address_hash_free); hash_free(bgp->address_hash); bgp->address_hash = NULL; } @@ -523,17 +529,14 @@ DEFUN (show_ip_bgp_instance_all_nexthop, void bgp_scan_init (struct bgp *bgp) { - bgp->nexthop_cache_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST); - bgp->connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST); - bgp->import_check_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST); - - bgp->nexthop_cache_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); - bgp->connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); - bgp->import_check_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); + afi_t afi; - bgp->nexthop_cache_table[AFI_ETHER] = bgp_table_init (AFI_ETHER, SAFI_UNICAST); - bgp->connected_table[AFI_ETHER] = bgp_table_init (AFI_ETHER, SAFI_UNICAST); - bgp->import_check_table[AFI_ETHER] = bgp_table_init (AFI_ETHER, SAFI_UNICAST); + for (afi = AFI_IP; afi < AFI_MAX; afi++) + { + bgp->nexthop_cache_table[afi] = bgp_table_init (afi, SAFI_UNICAST); + bgp->connected_table[afi] = bgp_table_init (afi, SAFI_UNICAST); + bgp->import_check_table[afi] = bgp_table_init (afi, SAFI_UNICAST); + } } void @@ -546,29 +549,19 @@ bgp_scan_vty_init (void) void bgp_scan_finish (struct bgp *bgp) { - /* Only the current one needs to be reset. */ - bgp_nexthop_cache_reset (bgp->nexthop_cache_table[AFI_IP]); - - bgp_table_unlock (bgp->nexthop_cache_table[AFI_IP]); - bgp->nexthop_cache_table[AFI_IP] = NULL; - - bgp_table_unlock (bgp->connected_table[AFI_IP]); - bgp->connected_table[AFI_IP] = NULL; - - bgp_table_unlock (bgp->import_check_table[AFI_IP]); - bgp->import_check_table[AFI_IP] = NULL; - -#ifdef HAVE_IPV6 - /* Only the current one needs to be reset. */ - bgp_nexthop_cache_reset (bgp->nexthop_cache_table[AFI_IP6]); + afi_t afi; - bgp_table_unlock (bgp->nexthop_cache_table[AFI_IP6]); - bgp->nexthop_cache_table[AFI_IP6] = NULL; + for (afi = AFI_IP; afi < AFI_MAX; afi++) + { + /* Only the current one needs to be reset. */ + bgp_nexthop_cache_reset (bgp->nexthop_cache_table[afi]); + bgp_table_unlock (bgp->nexthop_cache_table[afi]); + bgp->nexthop_cache_table[afi] = NULL; - bgp_table_unlock (bgp->connected_table[AFI_IP6]); - bgp->connected_table[AFI_IP6] = NULL; + bgp_table_unlock (bgp->connected_table[afi]); + bgp->connected_table[afi] = NULL; - bgp_table_unlock (bgp->import_check_table[AFI_IP6]); - bgp->import_check_table[AFI_IP6] = NULL; -#endif /* HAVE_IPV6 */ + bgp_table_unlock (bgp->import_check_table[afi]); + bgp->import_check_table[afi] = NULL; + } } diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 9aae3e7b3..1ca048367 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -115,19 +115,7 @@ bgp_unlink_nexthop_by_peer (struct peer *peer) struct bgp_nexthop_cache *bnc; afi_t afi = family2afi(peer->su.sa.sa_family); - if (afi == AFI_IP) - { - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = peer->su.sin.sin_addr; - } - else if (afi == AFI_IP6) - { - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_BITLEN; - p.u.prefix6 = peer->su.sin6.sin6_addr; - } - else + if (! sockunion2hostprefix (&peer->su, &p)) return; rn = bgp_node_get (peer->bgp->nexthop_cache_table[afi], &p); @@ -168,23 +156,11 @@ bgp_find_or_add_nexthop (struct bgp *bgp, afi_t afi, struct bgp_info *ri, } else if (peer) { - if (afi == AFI_IP) - { - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = peer->su.sin.sin_addr; - } - else if (afi == AFI_IP6) - { - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_BITLEN; - p.u.prefix6 = peer->su.sin6.sin6_addr; + /* Don't register link local NH */ + if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&peer->su.sin6.sin6_addr)) + return 1; - /* Don't register link local NH */ - if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) - return 1; - } - else + if (! sockunion2hostprefix (&peer->su, &p)) { if (BGP_DEBUG(nht, NHT)) { @@ -297,23 +273,11 @@ bgp_delete_connected_nexthop (afi_t afi, struct peer *peer) if (!peer) return; - if (afi == AFI_IP) - { - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = peer->su.sin.sin_addr; - } - else if (afi == AFI_IP6) - { - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_BITLEN; - p.u.prefix6 = peer->su.sin6.sin6_addr; + /* We don't register link local address for NHT */ + if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&peer->su.sin6.sin6_addr)) + return; - /* We don't register link local address for NHT */ - if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) - return; - } - else + if (! sockunion2hostprefix (&peer->su, &p)) return; rn = bgp_node_lookup(peer->bgp->nexthop_cache_table[family2afi(p.family)], &p); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 6af7aced1..ade05a2c0 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -3121,7 +3121,7 @@ bgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi, struct bgp_table *table) { struct bgp_node *rn; - + int force = bm->process_main_queue ? 0 : 1; if (! table) table = peer->bgp->rib[afi][safi]; @@ -3132,7 +3132,7 @@ bgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi, for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) { - struct bgp_info *ri; + struct bgp_info *ri, *next; struct bgp_adj_in *ain; struct bgp_adj_in *ain_next; @@ -3184,20 +3184,28 @@ bgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi, ain = ain_next; } - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == peer) - { - struct bgp_clear_node_queue *cnq; - - /* both unlocked in bgp_clear_node_queue_del */ - bgp_table_lock (bgp_node_table (rn)); - bgp_lock_node (rn); - cnq = XCALLOC (MTYPE_BGP_CLEAR_NODE_QUEUE, - sizeof (struct bgp_clear_node_queue)); - cnq->rn = rn; - work_queue_add (peer->clear_node_queue, cnq); - break; - } + for (ri = rn->info; ri; ri = next) + { + next = ri->next; + if (ri->peer != peer) + continue; + + if (force) + bgp_info_reap (rn, ri); + else + { + struct bgp_clear_node_queue *cnq; + + /* both unlocked in bgp_clear_node_queue_del */ + bgp_table_lock (bgp_node_table (rn)); + bgp_lock_node (rn); + cnq = XCALLOC (MTYPE_BGP_CLEAR_NODE_QUEUE, + sizeof (struct bgp_clear_node_queue)); + cnq->rn = rn; + work_queue_add (peer->clear_node_queue, cnq); + break; + } + } } return; } @@ -3333,52 +3341,48 @@ bgp_cleanup_table(struct bgp_table *table, safi_t safi) if (table->owner && table->owner->bgp) vnc_import_bgp_del_route(table->owner->bgp, &rn->p, ri); #endif - bgp_zebra_withdraw (&rn->p, ri, safi); + bgp_zebra_withdraw (&rn->p, ri, safi); + bgp_info_reap (rn, ri); + } } } -} /* Delete all kernel routes. */ void -bgp_cleanup_routes (void) +bgp_cleanup_routes (struct bgp *bgp) { - struct bgp *bgp; - struct listnode *node, *nnode; afi_t afi; - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - struct bgp_node *rn; + struct bgp_node *rn; - bgp_cleanup_table(bgp->rib[afi][SAFI_UNICAST], SAFI_UNICAST); + bgp_cleanup_table(bgp->rib[afi][SAFI_UNICAST], SAFI_UNICAST); - /* - * VPN and ENCAP tables are two-level (RD is top level) - */ - for (rn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn; - rn = bgp_route_next (rn)) + /* + * VPN and ENCAP tables are two-level (RD is top level) + */ + for (rn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn; + rn = bgp_route_next (rn)) + { + if (rn->info) { - if (rn->info) - { - bgp_cleanup_table((struct bgp_table *)(rn->info), SAFI_MPLS_VPN); - bgp_table_finish ((struct bgp_table **)&(rn->info)); - rn->info = NULL; - bgp_unlock_node(rn); - } + bgp_cleanup_table((struct bgp_table *)(rn->info), SAFI_MPLS_VPN); + bgp_table_finish ((struct bgp_table **)&(rn->info)); + rn->info = NULL; + bgp_unlock_node(rn); } + } - for (rn = bgp_table_top(bgp->rib[afi][SAFI_ENCAP]); rn; - rn = bgp_route_next (rn)) + for (rn = bgp_table_top(bgp->rib[afi][SAFI_ENCAP]); rn; + rn = bgp_route_next (rn)) + { + if (rn->info) { - if (rn->info) - { - bgp_cleanup_table((struct bgp_table *)(rn->info), SAFI_ENCAP); - bgp_table_finish ((struct bgp_table **)&(rn->info)); - rn->info = NULL; - bgp_unlock_node(rn); - } + bgp_cleanup_table((struct bgp_table *)(rn->info), SAFI_ENCAP); + bgp_table_finish ((struct bgp_table **)&(rn->info)); + rn->info = NULL; + bgp_unlock_node(rn); } } } @@ -6072,7 +6076,7 @@ route_vty_out (struct vty *vty, struct prefix *p, vty_out (vty, "%s", VTY_NEWLINE); #if ENABLE_BGP_VNC /* prints an additional line, indented, with VNC info, if present */ - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_UNICAST)) + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) rfapi_vty_out_vncinfo(vty, p, binfo, safi); #endif } diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 6bd54aba1..63b18aa2d 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -241,7 +241,7 @@ bgp_bump_version (struct bgp_node *node) extern void bgp_process_queue_init (void); extern void bgp_route_init (void); extern void bgp_route_finish (void); -extern void bgp_cleanup_routes (void); +extern void bgp_cleanup_routes (struct bgp *); extern void bgp_announce_route (struct peer *, afi_t, safi_t); extern void bgp_stop_announce_route_timer(struct peer_af *paf); extern void bgp_announce_route_all (struct peer *); diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index c485e61e5..a95a11b62 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -573,8 +573,8 @@ subgroup_clear_table (struct update_subgroup *subgrp) SUBGRP_FOREACH_ADJ_SAFE (subgrp, aout, taout) { - bgp_unlock_node (aout->rn); bgp_adj_out_remove_subgroup (aout->rn, aout, subgrp); + bgp_unlock_node (aout->rn); } } diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 8ecd02539..3d3bd90f5 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1792,6 +1792,7 @@ bgp_redist_del (struct bgp *bgp, afi_t afi, u_char type, u_short instance) if (red) { listnode_delete(bgp->redist[afi][type], red); + XFREE (MTYPE_BGP_REDIST, red); if (!bgp->redist[afi][type]->count) { list_free(bgp->redist[afi][type]); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 50d412633..6d479e102 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1044,6 +1044,12 @@ peer_free (struct peer *peer) peer->host = NULL; } + if (peer->domainname) + { + XFREE (MTYPE_BGP_PEER_HOST, peer->domainname); + peer->domainname = NULL; + } + if (peer->ifname) { XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname); @@ -1972,7 +1978,8 @@ peer_delete (struct peer *peer) bgp_fsm_change_status (peer, Deleted); /* Remove from NHT */ - bgp_unlink_nexthop_by_peer (peer); + if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + bgp_unlink_nexthop_by_peer (peer); /* Password configuration */ if (peer->password) @@ -2964,7 +2971,7 @@ bgp_lookup_by_vrf_id (vrf_id_t vrf_id) struct vrf *vrf; /* Lookup VRF (in tree) and follow link. */ - vrf = vrf_lookup (vrf_id); + vrf = vrf_lookup_by_id (vrf_id); if (!vrf) return NULL; return (vrf->info) ? (struct bgp *)vrf->info : NULL; @@ -3122,6 +3129,7 @@ bgp_delete (struct bgp *bgp) struct peer *peer; struct peer_group *group; struct listnode *node, *next; + struct vrf *vrf; afi_t afi; int i; @@ -3178,15 +3186,13 @@ bgp_delete (struct bgp *bgp) #if ENABLE_BGP_VNC rfapi_delete(bgp); - bgp_cleanup_routes(); /* rfapi cleanup can create route entries! */ #endif + bgp_cleanup_routes(bgp); /* Remove visibility via the master list - there may however still be * routes to be processed still referencing the struct bgp. */ listnode_delete (bm->bgp, bgp); - if (list_isempty(bm->bgp)) - bgp_close (); /* Deregister from Zebra, if needed */ if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) @@ -3195,6 +3201,10 @@ bgp_delete (struct bgp *bgp) /* Free interfaces in this instance. */ bgp_if_finish (bgp); + vrf = bgp_vrf_lookup_by_instance_type (bgp); + if (vrf) + bgp_vrf_unlink (bgp, vrf); + thread_master_free_unused(bm->master); bgp_unlock(bgp); /* initial reference */ @@ -3222,7 +3232,6 @@ bgp_free (struct bgp *bgp) { afi_t afi; safi_t safi; - struct vrf *vrf; list_delete (bgp->group); list_delete (bgp->peer); @@ -3244,13 +3253,9 @@ bgp_free (struct bgp *bgp) bgp_table_finish (&bgp->rib[afi][safi]); } + bgp_scan_finish (bgp); bgp_address_destroy (bgp); - /* If Default instance or VRF, unlink from the VRF structure. */ - vrf = bgp_vrf_lookup_by_instance_type (bgp); - if (vrf) - bgp_vrf_unlink (bgp, vrf); - if (bgp->name) XFREE(MTYPE_BGP, bgp->name); @@ -7596,8 +7601,6 @@ bgp_terminate (void) bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_PEER_UNCONFIG); - bgp_cleanup_routes (); - if (bm->process_main_queue) { work_queue_free (bm->process_main_queue); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index dd6a0fdcc..510082fdc 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1490,7 +1490,7 @@ bgp_vrf_lookup_by_instance_type (struct bgp *bgp) struct vrf *vrf; if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - vrf = vrf_lookup (VRF_DEFAULT); + vrf = vrf_lookup_by_id (VRF_DEFAULT); else if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) vrf = vrf_lookup_by_name (bgp->name); else diff --git a/ldpd/socket.c b/ldpd/socket.c index cf352d720..1bb083740 100644 --- a/ldpd/socket.c +++ b/ldpd/socket.c @@ -421,15 +421,7 @@ sock_set_ipv4_mcast(struct iface *iface) int sock_set_ipv4_mcast_loop(int fd) { - uint8_t loop = 0; - - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, - (char *)&loop, sizeof(loop)) < 0) { - log_warn("%s: error setting IP_MULTICAST_LOOP", __func__); - return (-1); - } - - return (0); + return (setsockopt_ipv4_multicast_loop(fd, 0)); } int diff --git a/lib/command.c b/lib/command.c index 3c429ce1a..f691cb599 100644 --- a/lib/command.c +++ b/lib/command.c @@ -2496,4 +2496,6 @@ cmd_terminate () XFREE (MTYPE_HOST, host.motdfile); if (host.config) XFREE (MTYPE_HOST, host.config); + + qobj_finish (); } @@ -307,13 +307,11 @@ if_lookup_by_name_vrf (const char *name, vrf_id_t vrf_id) struct interface * if_lookup_by_name_all_vrf (const char *name) { + struct vrf *vrf; struct interface *ifp; - struct vrf *vrf = NULL; - vrf_iter_t iter; - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - vrf = vrf_iter2vrf (iter); ifp = if_lookup_by_name_vrf (name, vrf->vrf_id); if (ifp) return ifp; @@ -392,7 +390,7 @@ if_lookup_exact_address (void *src, int family) } /* Lookup interface by IPv4 address. */ -struct interface * +struct connected * if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id) { struct listnode *node; @@ -401,7 +399,7 @@ if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id) struct listnode *cnode; struct interface *ifp; struct connected *c; - struct interface *match; + struct connected *match; if (family == AF_INET) { @@ -427,14 +425,14 @@ if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id) (c->address->prefixlen > bestlen)) { bestlen = c->address->prefixlen; - match = ifp; + match = c; } } } return match; } -struct interface * +struct connected * if_lookup_address (void *matchaddr, int family) { return if_lookup_address_vrf (matchaddr, family, VRF_DEFAULT); @@ -489,18 +487,16 @@ struct interface * if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id, int vty) { struct interface *ifp; + struct vrf *vrf; struct listnode *node; - struct vrf *vrf = NULL; - vrf_iter_t iter; ifp = if_lookup_by_name_len_vrf (name, namelen, vrf_id); if (ifp) return ifp; /* Didn't find the interface on that vrf. Defined on a different one? */ - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - vrf = vrf_iter2vrf(iter); for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf->vrf_id), node, ifp)) { if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0')) @@ -665,14 +661,13 @@ if_dump (const struct interface *ifp) void if_dump_all (void) { - struct list *intf_list; + struct vrf *vrf; struct listnode *node; void *p; - vrf_iter_t iter; - 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)) + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) + if (vrf->iflist != NULL) + for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, p)) if_dump (p); } @@ -832,65 +827,6 @@ DEFUN_NOSH (no_interface, return CMD_SUCCESS; } -DEFUN (vrf, - vrf_cmd, - "vrf NAME", - "Select a VRF to configure\n" - "VRF's name\n") -{ - int idx_name = 1; - const char *vrfname = argv[idx_name]->arg; - - struct vrf *vrfp; - size_t sl; - - if ((sl = strlen(vrfname)) > VRF_NAMSIZ) - { - vty_out (vty, "%% VRF name %s is invalid: length exceeds " - "%d characters%s", - vrfname, VRF_NAMSIZ, VTY_NEWLINE); - return CMD_WARNING; - } - - vrfp = vrf_get (VRF_UNKNOWN, vrfname); - - VTY_PUSH_CONTEXT_COMPAT (VRF_NODE, vrfp); - - return CMD_SUCCESS; -} - -DEFUN_NOSH (no_vrf, - no_vrf_cmd, - "no vrf NAME", - NO_STR - "Delete a pseudo VRF's configuration\n" - "VRF's name\n") -{ - const char *vrfname = argv[2]->arg; - - struct vrf *vrfp; - - vrfp = vrf_list_lookup_by_name (vrfname);; - - if (vrfp == NULL) - { - vty_out (vty, "%% VRF %s does not exist%s", vrfname, VTY_NEWLINE); - return CMD_WARNING; - } - - if (CHECK_FLAG (vrfp->status, VRF_ACTIVE)) - { - vty_out (vty, "%% Only inactive VRFs can be deleted%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - vrf_delete(vrfp); - - return CMD_SUCCESS; -} - - /* For debug purpose. */ DEFUN (show_address, show_address_cmd, @@ -931,24 +867,22 @@ DEFUN (show_address_vrf_all, "address\n" VRF_ALL_CMD_HELP_STR) { - struct list *intf_list; + struct vrf *vrf; 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)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - intf_list = vrf_iter2iflist (iter); - if (!intf_list || !listcount (intf_list)) + if (!vrf->iflist || !listcount (vrf->iflist)) continue; - vty_out (vty, "%sVRF %u%s%s", VTY_NEWLINE, vrf_iter2id (iter), - VTY_NEWLINE, VTY_NEWLINE); + vty_out (vty, "%sVRF %u%s%s", VTY_NEWLINE, vrf->vrf_id, VTY_NEWLINE, + VTY_NEWLINE); - for (ALL_LIST_ELEMENTS_RO (intf_list, node, ifp)) + for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp)) { for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc)) { @@ -1359,14 +1293,14 @@ if_link_params_get (struct interface *ifp) iflp->te_metric = ifp->metric; /* Compute default bandwidth based on interface */ - int bw = (float)((ifp->bandwidth ? ifp->bandwidth : DEFAULT_BANDWIDTH) - * TE_KILO_BIT / TE_BYTE); + iflp->default_bw = ((ifp->bandwidth ? ifp->bandwidth : DEFAULT_BANDWIDTH) + * TE_KILO_BIT / TE_BYTE); /* Set Max, Reservable and Unreserved Bandwidth */ - iflp->max_bw = bw; - iflp->max_rsv_bw = bw; + iflp->max_bw = iflp->default_bw; + iflp->max_rsv_bw = iflp->default_bw; for (i = 0; i < MAX_CLASS_TYPE; i++) - iflp->unrsv_bw[i] = bw; + iflp->unrsv_bw[i] = iflp->default_bw; /* Update Link parameters status */ iflp->lp_status = LP_TE | LP_MAX_BW | LP_MAX_RSV_BW | LP_UNRSV_BW; @@ -161,6 +161,7 @@ struct if_stats #define LP_RES_BW 0x0400 #define LP_AVA_BW 0x0800 #define LP_USE_BW 0x1000 +#define LP_TE_METRIC 0x2000 #define IS_PARAM_UNSET(lp, st) !(lp->lp_status & st) #define IS_PARAM_SET(lp, st) (lp->lp_status & st) @@ -174,6 +175,7 @@ struct if_stats struct if_link_params { u_int32_t lp_status; /* Status of Link Parameters: */ u_int32_t te_metric; /* Traffic Engineering metric */ + float default_bw; float max_bw; /* Maximum Bandwidth */ float max_rsv_bw; /* Maximum Reservable Bandwidth */ float unrsv_bw[MAX_CLASS_TYPE]; /* Unreserved Bandwidth per Class Type (8) */ @@ -387,7 +389,7 @@ extern int if_cmp_name_func (char *, char *); extern struct interface *if_create (const char *name, int namelen); extern struct interface *if_lookup_by_index (ifindex_t); extern struct interface *if_lookup_exact_address (void *matchaddr, int family); -extern struct interface *if_lookup_address (void *matchaddr, int family); +extern struct connected *if_lookup_address (void *matchaddr, int family); extern struct interface *if_lookup_prefix (struct prefix *prefix); extern void if_update_vrf (struct interface *, const char *name, int namelen, @@ -397,7 +399,7 @@ extern struct interface *if_create_vrf (const char *name, int namelen, extern struct interface *if_lookup_by_index_vrf (ifindex_t, 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, +extern struct connected *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); @@ -31,8 +31,6 @@ #include "if.h" #include "ns.h" -#include "prefix.h" -#include "table.h" #include "log.h" #include "memory.h" @@ -41,7 +39,13 @@ DEFINE_MTYPE_STATIC(LIB, NS, "Logical-Router") DEFINE_MTYPE_STATIC(LIB, NS_NAME, "Logical-Router Name") -DEFINE_MTYPE_STATIC(LIB, NS_BITMAP, "Logical-Router bit-map") + +static __inline int ns_compare (struct ns *, struct ns *); +static struct ns *ns_lookup (ns_id_t); + +RB_GENERATE (ns_head, ns, entry, ns_compare) + +struct ns_head ns_tree = RB_INITIALIZER (&ns_tree); #ifndef CLONE_NEWNET #define CLONE_NEWNET 0x40000000 /* New network namespace (lo, device, names sockets, etc) */ @@ -91,22 +95,6 @@ static int have_netns(void) #endif } -struct ns -{ - /* Identifier, same as the vector index */ - ns_id_t ns_id; - /* Name */ - char *name; - /* File descriptor */ - int fd; - - /* Master list of interfaces belonging to this NS */ - struct list *iflist; - - /* User data */ - void *info; -}; - /* Holding NS hooks */ struct ns_master { @@ -116,44 +104,30 @@ struct ns_master int (*ns_disable_hook) (ns_id_t, void **); } ns_master = {0,}; -/* NS table */ -struct route_table *ns_table = NULL; - static int ns_is_enabled (struct ns *ns); static int ns_enable (struct ns *ns); static void ns_disable (struct ns *ns); - -/* Build the table key */ -static void -ns_build_key (ns_id_t ns_id, struct prefix *p) +static __inline int +ns_compare(struct ns *a, struct ns *b) { - p->family = AF_INET; - p->prefixlen = IPV4_MAX_BITLEN; - p->u.prefix4.s_addr = ns_id; + return (a->ns_id - b->ns_id); } /* Get a NS. If not found, create one. */ static struct ns * ns_get (ns_id_t ns_id) { - struct prefix p; - struct route_node *rn; struct ns *ns; - ns_build_key (ns_id, &p); - rn = route_node_get (ns_table, &p); - if (rn->info) - { - ns = (struct ns *)rn->info; - route_unlock_node (rn); /* get */ - return ns; - } + ns = ns_lookup (ns_id); + if (ns) + return (ns); ns = XCALLOC (MTYPE_NS, sizeof (struct ns)); ns->ns_id = ns_id; ns->fd = -1; - rn->info = ns; + RB_INSERT (ns_head, &ns_tree, ns); /* * Initialize interfaces. @@ -188,6 +162,7 @@ ns_delete (struct ns *ns) */ //if_terminate (&ns->iflist); + RB_REMOVE (ns_head, &ns_tree, ns); if (ns->name) XFREE (MTYPE_NS_NAME, ns->name); @@ -198,18 +173,9 @@ ns_delete (struct ns *ns) static struct ns * ns_lookup (ns_id_t ns_id) { - struct prefix p; - struct route_node *rn; - struct ns *ns = NULL; - - ns_build_key (ns_id, &p); - rn = route_node_lookup (ns_table, &p); - if (rn) - { - ns = (struct ns *)rn->info; - route_unlock_node (rn); /* lookup */ - } - return ns; + struct ns ns; + ns.ns_id = ns_id; + return (RB_FIND (ns_head, &ns_tree, &ns)); } /* @@ -310,217 +276,6 @@ ns_add_hook (int type, int (*func)(ns_id_t, void **)) } } -/* Return the iterator of the first NS. */ -ns_iter_t -ns_first (void) -{ - struct route_node *rn; - - for (rn = route_top (ns_table); rn; rn = route_next (rn)) - if (rn->info) - { - route_unlock_node (rn); /* top/next */ - return (ns_iter_t)rn; - } - return NS_ITER_INVALID; -} - -/* Return the next NS iterator to the given iterator. */ -ns_iter_t -ns_next (ns_iter_t iter) -{ - struct route_node *rn = NULL; - - /* Lock it first because route_next() will unlock it. */ - if (iter != NS_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 (ns_iter_t)rn; - } - return NS_ITER_INVALID; -} - -/* Return the NS iterator of the given NS ID. If it does not exist, - * the iterator of the next existing NS is returned. */ -ns_iter_t -ns_iterator (ns_id_t ns_id) -{ - struct prefix p; - struct route_node *rn; - - ns_build_key (ns_id, &p); - rn = route_node_get (ns_table, &p); - if (rn->info) - { - /* OK, the NS exists. */ - route_unlock_node (rn); /* get */ - return (ns_iter_t)rn; - } - - /* Find the next NS. */ - for (rn = route_next (rn); rn; rn = route_next (rn)) - if (rn->info) - { - route_unlock_node (rn); /* next */ - return (ns_iter_t)rn; - } - - return NS_ITER_INVALID; -} - -/* Obtain the NS ID from the given NS iterator. */ -ns_id_t -ns_iter2id (ns_iter_t iter) -{ - struct route_node *rn = (struct route_node *) iter; - return (rn && rn->info) ? ((struct ns *)rn->info)->ns_id : NS_DEFAULT; -} - -/* Obtain the data pointer from the given NS iterator. */ -void * -ns_iter2info (ns_iter_t iter) -{ - struct route_node *rn = (struct route_node *) iter; - return (rn && rn->info) ? ((struct ns *)rn->info)->info : NULL; -} - -/* Obtain the interface list from the given NS iterator. */ -struct list * -ns_iter2iflist (ns_iter_t iter) -{ - struct route_node *rn = (struct route_node *) iter; - return (rn && rn->info) ? ((struct ns *)rn->info)->iflist : NULL; -} - -/* Get the data pointer of the specified NS. If not found, create one. */ -void * -ns_info_get (ns_id_t ns_id) -{ - struct ns *ns = ns_get (ns_id); - return ns->info; -} - -/* Look up the data pointer of the specified NS. */ -void * -ns_info_lookup (ns_id_t ns_id) -{ - struct ns *ns = ns_lookup (ns_id); - return ns ? ns->info : NULL; -} - -/* Look up the interface list in a NS. */ -struct list * -ns_iflist (ns_id_t ns_id) -{ - struct ns * ns = ns_lookup (ns_id); - return ns ? ns->iflist : NULL; -} - -/* Get the interface list of the specified NS. Create one if not find. */ -struct list * -ns_iflist_get (ns_id_t ns_id) -{ - struct ns * ns = ns_get (ns_id); - return ns->iflist; -} - -/* - * NS bit-map - */ - -#define NS_BITMAP_NUM_OF_GROUPS 8 -#define NS_BITMAP_NUM_OF_BITS_IN_GROUP \ - (UINT16_MAX / NS_BITMAP_NUM_OF_GROUPS) -#define NS_BITMAP_NUM_OF_BYTES_IN_GROUP \ - (NS_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */ - -#define NS_BITMAP_GROUP(_id) \ - ((_id) / NS_BITMAP_NUM_OF_BITS_IN_GROUP) -#define NS_BITMAP_BIT_OFFSET(_id) \ - ((_id) % NS_BITMAP_NUM_OF_BITS_IN_GROUP) - -#define NS_BITMAP_INDEX_IN_GROUP(_bit_offset) \ - ((_bit_offset) / CHAR_BIT) -#define NS_BITMAP_FLAG(_bit_offset) \ - (((u_char)1) << ((_bit_offset) % CHAR_BIT)) - -struct ns_bitmap -{ - u_char *groups[NS_BITMAP_NUM_OF_GROUPS]; -}; - -ns_bitmap_t -ns_bitmap_init (void) -{ - return (ns_bitmap_t) XCALLOC (MTYPE_NS_BITMAP, sizeof (struct ns_bitmap)); -} - -void -ns_bitmap_free (ns_bitmap_t bmap) -{ - struct ns_bitmap *bm = (struct ns_bitmap *) bmap; - int i; - - if (bmap == NS_BITMAP_NULL) - return; - - for (i = 0; i < NS_BITMAP_NUM_OF_GROUPS; i++) - if (bm->groups[i]) - XFREE (MTYPE_NS_BITMAP, bm->groups[i]); - - XFREE (MTYPE_NS_BITMAP, bm); -} - -void -ns_bitmap_set (ns_bitmap_t bmap, ns_id_t ns_id) -{ - struct ns_bitmap *bm = (struct ns_bitmap *) bmap; - u_char group = NS_BITMAP_GROUP (ns_id); - u_char offset = NS_BITMAP_BIT_OFFSET (ns_id); - - if (bmap == NS_BITMAP_NULL) - return; - - if (bm->groups[group] == NULL) - bm->groups[group] = XCALLOC (MTYPE_NS_BITMAP, - NS_BITMAP_NUM_OF_BYTES_IN_GROUP); - - SET_FLAG (bm->groups[group][NS_BITMAP_INDEX_IN_GROUP (offset)], - NS_BITMAP_FLAG (offset)); -} - -void -ns_bitmap_unset (ns_bitmap_t bmap, ns_id_t ns_id) -{ - struct ns_bitmap *bm = (struct ns_bitmap *) bmap; - u_char group = NS_BITMAP_GROUP (ns_id); - u_char offset = NS_BITMAP_BIT_OFFSET (ns_id); - - if (bmap == NS_BITMAP_NULL || bm->groups[group] == NULL) - return; - - UNSET_FLAG (bm->groups[group][NS_BITMAP_INDEX_IN_GROUP (offset)], - NS_BITMAP_FLAG (offset)); -} - -int -ns_bitmap_check (ns_bitmap_t bmap, ns_id_t ns_id) -{ - struct ns_bitmap *bm = (struct ns_bitmap *) bmap; - u_char group = NS_BITMAP_GROUP (ns_id); - u_char offset = NS_BITMAP_BIT_OFFSET (ns_id); - - if (bmap == NS_BITMAP_NULL || bm->groups[group] == NULL) - return 0; - - return CHECK_FLAG (bm->groups[group][NS_BITMAP_INDEX_IN_GROUP (offset)], - NS_BITMAP_FLAG (offset)) ? 1 : 0; -} - /* * NS realization with NETNS */ @@ -645,17 +400,17 @@ static struct cmd_node ns_node = static int ns_config_write (struct vty *vty) { - struct route_node *rn; struct ns *ns; int write = 0; - for (rn = route_top (ns_table); rn; rn = route_next (rn)) - if ((ns = rn->info) != NULL && - ns->ns_id != NS_DEFAULT && ns->name) - { - vty_out (vty, "logical-router %u netns %s%s", ns->ns_id, ns->name, VTY_NEWLINE); - write++; - } + RB_FOREACH (ns, ns_head, &ns_tree) { + if (ns->ns_id == NS_DEFAULT || ns->name == NULL) + continue; + + vty_out (vty, "logical-router %u netns %s%s", ns->ns_id, ns->name, + VTY_NEWLINE); + write = 1; + } return write; } @@ -666,9 +421,6 @@ ns_init (void) { struct ns *default_ns; - /* Allocate NS table. */ - ns_table = route_table_init (); - /* The default NS always exists. */ default_ns = ns_get (NS_DEFAULT); if (!default_ns) @@ -700,15 +452,10 @@ ns_init (void) void ns_terminate (void) { - struct route_node *rn; struct ns *ns; - for (rn = route_top (ns_table); rn; rn = route_next (rn)) - if ((ns = rn->info) != NULL) - ns_delete (ns); - - route_table_finish (ns_table); - ns_table = NULL; + while ((ns = RB_ROOT (&ns_tree)) != NULL) + ns_delete (ns); } /* Create a socket for the NS. */ @@ -23,6 +23,7 @@ #ifndef _ZEBRA_NS_H #define _ZEBRA_NS_H +#include "openbsd-tree.h" #include "linklist.h" typedef u_int16_t ns_id_t; @@ -30,15 +31,32 @@ typedef u_int16_t ns_id_t; /* The default NS ID */ #define NS_DEFAULT 0 -/* - * The command strings - */ +/* Default netns directory (Linux) */ #define NS_RUN_DIR "/var/run/netns" -#define NS_CMD_STR "logical-router <0-65535>" -#define NS_CMD_HELP_STR "Specify the Logical-Router\nThe Logical-Router ID\n" -#define NS_ALL_CMD_STR "logical-router all" -#define NS_ALL_CMD_HELP_STR "Specify the logical-router\nAll logical-router's\n" +struct ns +{ + RB_ENTRY(ns) entry; + + /* Identifier, same as the vector index */ + ns_id_t ns_id; + + /* Name */ + char *name; + + /* File descriptor */ + int fd; + + /* Master list of interfaces belonging to this NS */ + struct list *iflist; + + /* User data */ + void *info; +}; +RB_HEAD (ns_head, ns); +RB_PROTOTYPE (ns_head, ns, entry, ns_compare) + +extern struct ns_head ns_tree; /* * NS hooks @@ -60,71 +78,6 @@ typedef u_int16_t ns_id_t; extern void ns_add_hook (int, int (*)(ns_id_t, void **)); /* - * NS iteration - */ - -typedef void * ns_iter_t; -#define NS_ITER_INVALID NULL /* invalid value of the iterator */ - -/* - * NS iteration utilities. Example for the usage: - * - * ns_iter_t iter = ns_first(); - * for (; iter != NS_ITER_INVALID; iter = ns_next (iter)) - * - * or - * - * ns_iter_t iter = ns_iterator (<a given NS ID>); - * for (; iter != NS_ITER_INVALID; iter = ns_next (iter)) - */ - -/* Return the iterator of the first NS. */ -extern ns_iter_t ns_first (void); -/* Return the next NS iterator to the given iterator. */ -extern ns_iter_t ns_next (ns_iter_t); -/* Return the NS iterator of the given NS ID. If it does not exist, - * the iterator of the next existing NS is returned. */ -extern ns_iter_t ns_iterator (ns_id_t); - -/* - * NS iterator to properties - */ -extern ns_id_t ns_iter2id (ns_iter_t); -extern void *ns_iter2info (ns_iter_t); -extern struct list *ns_iter2iflist (ns_iter_t); - -/* - * Utilities to obtain the user data - */ - -/* Get the data pointer of the specified NS. If not found, create one. */ -extern void *ns_info_get (ns_id_t); -/* Look up the data pointer of the specified NS. */ -extern void *ns_info_lookup (ns_id_t); - -/* - * Utilities to obtain the interface list - */ - -/* Look up the interface list of the specified NS. */ -extern struct list *ns_iflist (ns_id_t); -/* Get the interface list of the specified NS. Create one if not find. */ -extern struct list *ns_iflist_get (ns_id_t); - -/* - * NS bit-map: maintaining flags, one bit per NS ID - */ - -typedef void * ns_bitmap_t; -#define NS_BITMAP_NULL NULL - -extern ns_bitmap_t ns_bitmap_init (void); -extern void ns_bitmap_free (ns_bitmap_t); -extern void ns_bitmap_set (ns_bitmap_t, ns_id_t); -extern void ns_bitmap_unset (ns_bitmap_t, ns_id_t); -extern int ns_bitmap_check (ns_bitmap_t, ns_id_t); - -/* * NS initializer/destructor */ /* Please add hooks before calling ns_init(). */ diff --git a/lib/qobj.c b/lib/qobj.c index 65b537f96..f64972e32 100644 --- a/lib/qobj.c +++ b/lib/qobj.c @@ -78,6 +78,7 @@ void qobj_init (void) void qobj_finish (void) { + hash_clean (nodes, NULL); hash_free (nodes); nodes = NULL; } diff --git a/lib/sockopt.c b/lib/sockopt.c index c480cee0d..be3ac0e4b 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -384,7 +384,20 @@ setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr, #error "Unsupported multicast API" #endif } - + +int +setsockopt_ipv4_multicast_loop (int sock, u_char val) +{ + int ret; + + ret = setsockopt (sock, IPPROTO_IP, IP_MULTICAST_LOOP, (void *) &val, + sizeof (val)); + if (ret < 0) + zlog_warn ("can't setsockopt IP_MULTICAST_LOOP"); + + return ret; +} + static int setsockopt_ipv4_ifindex (int sock, ifindex_t val) { diff --git a/lib/sockopt.h b/lib/sockopt.h index d67b510b6..02f018934 100644 --- a/lib/sockopt.h +++ b/lib/sockopt.h @@ -89,6 +89,8 @@ extern int setsockopt_ipv4_multicast(int sock, int optname, struct in_addr if_addr, unsigned int mcast_addr, ifindex_t ifindex); +extern int setsockopt_ipv4_multicast_loop (int sock, u_char val); + extern int setsockopt_ipv4_tos(int sock, int tos); /* Ask for, and get, ifindex, by whatever method is supported. */ diff --git a/lib/table.c b/lib/table.c index d0e084ead..5133ef697 100644 --- a/lib/table.c +++ b/lib/table.c @@ -494,7 +494,7 @@ route_table_count (const struct route_table *table) * * Default function for creating a route node. */ -static struct route_node * +struct route_node * route_node_create (route_table_delegate_t *delegate, struct route_table *table) { @@ -508,7 +508,7 @@ route_node_create (route_table_delegate_t *delegate, * * Default function for destroying a route node. */ -static void +void route_node_destroy (route_table_delegate_t *delegate, struct route_table *table, struct route_node *node) { diff --git a/lib/table.h b/lib/table.h index e6cdcfef1..78bf5da74 100644 --- a/lib/table.h +++ b/lib/table.h @@ -169,6 +169,11 @@ extern struct route_node *route_node_match_ipv6 (const struct route_table *, extern unsigned long route_table_count (const struct route_table *); +extern struct route_node *route_node_create (route_table_delegate_t *, + struct route_table *); +extern void route_node_destroy (route_table_delegate_t *, + struct route_table *, struct route_node *); + extern struct route_node * route_table_get_next (const struct route_table *table, struct prefix *p); extern int @@ -35,6 +35,15 @@ DEFINE_MTYPE_STATIC(LIB, VRF_BITMAP, "VRF bit-map") DEFINE_QOBJ_TYPE(vrf) +static __inline int vrf_id_compare (struct vrf *, struct vrf *); +static __inline int vrf_name_compare (struct vrf *, struct vrf *); + +RB_GENERATE (vrf_id_head, vrf, id_entry, vrf_id_compare) +RB_GENERATE (vrf_name_head, vrf, name_entry, vrf_name_compare) + +struct vrf_id_head vrfs_by_id = RB_INITIALIZER (&vrfs_by_id); +struct vrf_name_head vrfs_by_name = RB_INITIALIZER (&vrfs_by_name); + /* * Turn on/off debug code * for vrf. @@ -44,44 +53,34 @@ int debug_vrf = 0; /* Holding VRF hooks */ struct vrf_master { - int (*vrf_new_hook) (vrf_id_t, const char *, void **); - int (*vrf_delete_hook) (vrf_id_t, const char *, void **); - int (*vrf_enable_hook) (vrf_id_t, const char *, void **); - int (*vrf_disable_hook) (vrf_id_t, const char *, void **); + int (*vrf_new_hook) (struct vrf *); + int (*vrf_delete_hook) (struct vrf *); + int (*vrf_enable_hook) (struct vrf *); + int (*vrf_disable_hook) (struct vrf *); } vrf_master = {0,}; -/* VRF table */ -struct route_table *vrf_table = NULL; - -/* VRF is part of a list too to store it before its actually active */ -struct list *vrf_list; - static int vrf_is_enabled (struct vrf *vrf); static void vrf_disable (struct vrf *vrf); /* VRF list existance check by name. */ struct vrf * -vrf_list_lookup_by_name (const char *name) +vrf_lookup_by_name (const char *name) { - struct listnode *node; - struct vrf *vrfp; + struct vrf vrf; + strlcpy (vrf.name, name, sizeof (vrf.name)); + return (RB_FIND (vrf_name_head, &vrfs_by_name, &vrf)); +} - if (name) - for (ALL_LIST_ELEMENTS_RO (vrf_list, node, vrfp)) - { - if (strcmp(name, vrfp->name) == 0) - return vrfp; - } - return NULL; +static __inline int +vrf_id_compare (struct vrf *a, struct vrf *b) +{ + return (a->vrf_id - b->vrf_id); } -/* Build the table key */ -static void -vrf_build_key (vrf_id_t vrf_id, struct prefix *p) +static int +vrf_name_compare (struct vrf *a, struct vrf *b) { - p->family = AF_INET; - p->prefixlen = IPV4_MAX_BITLEN; - p->u.prefix4.s_addr = vrf_id; + return strcmp (a->name, b->name); } /* Get a VRF. If not found, create one. @@ -94,177 +93,59 @@ vrf_build_key (vrf_id_t vrf_id, struct prefix *p) struct vrf * vrf_get (vrf_id_t vrf_id, const char *name) { - struct prefix p; - struct route_node *rn = NULL; struct vrf *vrf = NULL; + int new = 0; if (debug_vrf) zlog_debug ("VRF_GET: %s(%d)", name, vrf_id); - /* - * Nothing to see, move along here - */ + /* Nothing to see, move along here */ if (!name && vrf_id == VRF_UNKNOWN) return NULL; - /* - * Valid vrf name and unknown vrf_id case - * - * This is called when we are configured from - * the cli but we have no kernel information yet. - */ - if (name && vrf_id == VRF_UNKNOWN) - { - vrf = vrf_list_lookup_by_name (name); - if (vrf) - return vrf; + /* Try to find VRF both by ID and name */ + if (vrf_id != VRF_UNKNOWN) + vrf = vrf_lookup_by_id (vrf_id); + if (! vrf && name) + vrf = vrf_lookup_by_name (name); + if (vrf == NULL) + { vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf)); - if (debug_vrf) - zlog_debug ("VRF(%u) %s is created.", - vrf_id, (name) ? name : "(NULL)"); - strcpy (vrf->name, name); - listnode_add_sort (vrf_list, vrf); + vrf->vrf_id = VRF_UNKNOWN; if_init (&vrf->iflist); QOBJ_REG (vrf, vrf); - if (vrf_master.vrf_new_hook) - { - (*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info); + new = 1; - if (debug_vrf && vrf->info) - zlog_info ("zvrf is created."); - } if (debug_vrf) - zlog_debug("Vrf Created: %p", vrf); - return vrf; + zlog_debug ("VRF(%u) %s is created.", + vrf_id, (name) ? name : "(NULL)"); } - /* - * Valid vrf name and valid vrf_id case - * - * This can be passed from the kernel - */ - else if (name && vrf_id != VRF_UNKNOWN) + + /* Set identifier */ + if (vrf_id != VRF_UNKNOWN && vrf->vrf_id == VRF_UNKNOWN) { - vrf = vrf_list_lookup_by_name (name); - if (vrf) - { - /* - * If the passed in vrf_id and name match - * return, nothing to do here. - */ - if (vrf->vrf_id == vrf_id) - return vrf; - - /* - * Now we have a situation where we've had a - * vrf created, but not yet created the vrf_id route - * node, let's do so and match the code up. - */ - vrf_build_key (vrf_id, &p); - rn = route_node_get (vrf_table, &p); - - rn->info = vrf; - vrf->node = rn; - vrf->vrf_id = vrf_id; - if (vrf_master.vrf_new_hook) - (*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info); - - if (debug_vrf) - zlog_debug("Vrf found matched stuff up: %p", vrf); - - return vrf; - } - else - { - /* - * We can have 1 of two situations here - * We've already been told about the vrf_id - * or we haven't. - */ - vrf_build_key (vrf_id, &p); - rn = route_node_get (vrf_table, &p); - if (rn->info) - { - vrf = rn->info; - route_unlock_node (rn); - /* - * We know at this point that the vrf->name is not - * right because we would have caught it above. - * so let's set it. - */ - strcpy (vrf->name, name); - listnode_add_sort (vrf_list, vrf); - if (vrf_master.vrf_new_hook) - { - (*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info); - - if (debug_vrf && vrf->info) - zlog_info ("zvrf is created."); - } - if (debug_vrf) - zlog_debug("Vrf Created: %p", vrf); - return vrf; - } - else - { - vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf)); - - rn->info = vrf; - vrf->node = rn; - vrf->vrf_id = vrf_id; - strcpy (vrf->name, name); - listnode_add_sort (vrf_list, vrf); - if_init (&vrf->iflist); - QOBJ_REG (vrf, vrf); - if (vrf_master.vrf_new_hook) - { - (*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info); - - if (debug_vrf && vrf->info) - zlog_info ("zvrf is created."); - } - if (debug_vrf) - zlog_debug("Vrf Created: %p", vrf); - return vrf; - } - } + vrf->vrf_id = vrf_id; + RB_INSERT (vrf_id_head, &vrfs_by_id, vrf); } - /* - * The final case, we've been passed a valid vrf_id - * but no name. So we create the route node - * if it hasn't already been created. - */ - else if (!name) + + /* Set name */ + if (name && vrf->name[0] != '\0' && strcmp (name, vrf->name)) { - vrf_build_key (vrf_id, &p); - rn = route_node_get (vrf_table, &p); - if (debug_vrf) - zlog_debug("Vrf found: %p", rn->info); - - if (rn->info) - { - route_unlock_node (rn); - return (rn->info); - } - else - { - vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf)); - rn->info = vrf; - vrf->node = rn; - vrf->vrf_id = vrf_id; - if_init (&vrf->iflist); - QOBJ_REG (vrf, vrf); - if (debug_vrf) - zlog_debug("Vrf Created: %p", vrf); - return vrf; - } + RB_REMOVE (vrf_name_head, &vrfs_by_name, vrf); + strlcpy (vrf->name, name, sizeof (vrf->name)); + RB_INSERT (vrf_name_head, &vrfs_by_name, vrf); + } + else if (name && vrf->name[0] == '\0') + { + strlcpy (vrf->name, name, sizeof (vrf->name)); + RB_INSERT (vrf_name_head, &vrfs_by_name, vrf); } - /* - * We shouldn't get here and if we do - * something has gone wrong. - */ - return NULL; + if (new && vrf_master.vrf_new_hook) + (*vrf_master.vrf_new_hook) (vrf); + + return vrf; } /* Delete a VRF. This is called in vrf_terminate(). */ @@ -278,53 +159,35 @@ vrf_delete (struct vrf *vrf) vrf_disable (vrf); if (vrf_master.vrf_delete_hook) - (*vrf_master.vrf_delete_hook) (vrf->vrf_id, vrf->name, &vrf->info); + (*vrf_master.vrf_delete_hook) (vrf); QOBJ_UNREG (vrf); if_terminate (&vrf->iflist); - if (vrf->node) - { - vrf->node->info = NULL; - route_unlock_node(vrf->node); - } - - listnode_delete (vrf_list, vrf); + if (vrf->vrf_id != VRF_UNKNOWN) + RB_REMOVE (vrf_id_head, &vrfs_by_id, vrf); + if (vrf->name[0] != '\0') + RB_REMOVE (vrf_name_head, &vrfs_by_name, vrf); XFREE (MTYPE_VRF, vrf); } /* Look up a VRF by identifier. */ struct vrf * -vrf_lookup (vrf_id_t vrf_id) +vrf_lookup_by_id (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; + struct vrf vrf; + vrf.vrf_id = vrf_id; + return (RB_FIND (vrf_id_head, &vrfs_by_id, &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. + * Check whether the VRF is enabled. */ static int vrf_is_enabled (struct vrf *vrf) { return vrf && CHECK_FLAG (vrf->status, VRF_ACTIVE); - - /*Pending: figure out the real use of this routine.. it used to be.. - return vrf && vrf->vrf_id == VRF_DEFAULT; - */ } /* @@ -337,14 +200,16 @@ vrf_is_enabled (struct vrf *vrf) int vrf_enable (struct vrf *vrf) { + if (vrf_is_enabled (vrf)) + return 1; + if (debug_vrf) zlog_debug ("VRF %u is enabled.", vrf->vrf_id); - if (!CHECK_FLAG (vrf->status, VRF_ACTIVE)) - SET_FLAG (vrf->status, VRF_ACTIVE); + SET_FLAG (vrf->status, VRF_ACTIVE); if (vrf_master.vrf_enable_hook) - (*vrf_master.vrf_enable_hook) (vrf->vrf_id, vrf->name, &vrf->info); + (*vrf_master.vrf_enable_hook) (vrf); return 1; } @@ -357,26 +222,25 @@ vrf_enable (struct vrf *vrf) static void vrf_disable (struct vrf *vrf) { - if (vrf_is_enabled (vrf)) - { - UNSET_FLAG (vrf->status, VRF_ACTIVE); + if (! vrf_is_enabled (vrf)) + return; - if (debug_vrf) - zlog_debug ("VRF %u is to be disabled.", vrf->vrf_id); + UNSET_FLAG (vrf->status, VRF_ACTIVE); - /* Till now, nothing to be done for the default VRF. */ - //Pending: see why this statement. + if (debug_vrf) + zlog_debug ("VRF %u is to be disabled.", vrf->vrf_id); - if (vrf_master.vrf_disable_hook) - (*vrf_master.vrf_disable_hook) (vrf->vrf_id, vrf->name, &vrf->info); - } + /* Till now, nothing to be done for the default VRF. */ + //Pending: see why this statement. + if (vrf_master.vrf_disable_hook) + (*vrf_master.vrf_disable_hook) (vrf); } /* Add a VRF hook. Please add hooks before calling vrf_init(). */ void -vrf_add_hook (int type, int (*func)(vrf_id_t, const char *, void **)) +vrf_add_hook (int type, int (*func)(struct vrf *)) { if (debug_vrf) zlog_debug ("%s: Add Hook %d to function %p", __PRETTY_FUNCTION__, @@ -400,116 +264,6 @@ vrf_add_hook (int type, int (*func)(vrf_id_t, const char *, void **)) } } -/* 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; -} - -struct vrf * -vrf_iter2vrf (vrf_iter_t iter) -{ - struct route_node *rn = (struct route_node *) iter; - return (rn && rn->info) ? (struct vrf *)rn->info : NULL; -} - -/* Obtain the data pointer from the given VRF iterator. */ -void * -vrf_iter2info (vrf_iter_t iter) -{ - struct route_node *rn = (struct route_node *) iter; - return (rn && rn->info) ? ((struct vrf *)rn->info)->info : NULL; -} - -/* Obtain the interface list from the given VRF iterator. */ -struct list * -vrf_iter2iflist (vrf_iter_t iter) -{ - struct route_node *rn = (struct route_node *) iter; - return (rn && rn->info) ? ((struct vrf *)rn->info)->iflist : NULL; -} - -/* Look up a VRF by name. */ -struct vrf * -vrf_lookup_by_name (const char *name) -{ - struct vrf *vrf = NULL; - vrf_iter_t iter; - - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - { - vrf = vrf_iter2vrf (iter); - if (vrf && !strcmp(vrf->name, name)) - return vrf; - } - - return NULL; -} - vrf_id_t vrf_name_to_id (const char *name) { @@ -535,7 +289,7 @@ vrf_info_get (vrf_id_t vrf_id) void * vrf_info_lookup (vrf_id_t vrf_id) { - struct vrf *vrf = vrf_lookup (vrf_id); + struct vrf *vrf = vrf_lookup_by_id (vrf_id); return vrf ? vrf->info : NULL; } @@ -543,7 +297,7 @@ vrf_info_lookup (vrf_id_t vrf_id) struct list * vrf_iflist (vrf_id_t vrf_id) { - struct vrf * vrf = vrf_lookup (vrf_id); + struct vrf * vrf = vrf_lookup_by_id (vrf_id); return vrf ? vrf->iflist : NULL; } @@ -559,7 +313,7 @@ vrf_iflist_get (vrf_id_t vrf_id) void vrf_iflist_create (vrf_id_t vrf_id) { - struct vrf * vrf = vrf_lookup (vrf_id); + struct vrf * vrf = vrf_lookup_by_id (vrf_id); if (vrf && !vrf->iflist) if_init (&vrf->iflist); } @@ -568,7 +322,7 @@ vrf_iflist_create (vrf_id_t vrf_id) void vrf_iflist_terminate (vrf_id_t vrf_id) { - struct vrf * vrf = vrf_lookup (vrf_id); + struct vrf * vrf = vrf_lookup_by_id (vrf_id); if (vrf && vrf->iflist) if_terminate (&vrf->iflist); } @@ -666,20 +420,6 @@ vrf_bitmap_check (vrf_bitmap_t bmap, vrf_id_t vrf_id) VRF_BITMAP_FLAG (offset)) ? 1 : 0; } -/* Compare interface names, returning an integer greater than, equal to, or - * less than 0, (following the strcmp convention), according to the - * relationship between vrfp1 and vrfp2. Interface names consist of an - * alphabetic prefix and a numeric suffix. The primary sort key is - * lexicographic by name, and then numeric by number. No number sorts - * before all numbers. Examples: de0 < de1, de100 < fxp0 < xl0, devpty < - * devpty0, de0 < del0 - */ -static int -vrf_cmp_func (struct vrf *vrfp1, struct vrf *vrfp2) -{ - return if_cmp_name_func (vrfp1->name, vrfp2->name); -} - /* Initialize VRF module. */ void vrf_init (void) @@ -689,12 +429,6 @@ vrf_init (void) if (debug_vrf) zlog_debug ("%s: Initializing VRF subsystem", __PRETTY_FUNCTION__); - vrf_list = list_new (); - vrf_list->cmp = (int (*)(void *, void *))vrf_cmp_func; - - /* Allocate VRF table. */ - vrf_table = route_table_init (); - /* The default VRF always exists. */ default_vrf = vrf_get (VRF_DEFAULT, VRF_DEFAULT_NAME); if (!default_vrf) @@ -715,18 +449,15 @@ vrf_init (void) void vrf_terminate (void) { - struct route_node *rn; struct vrf *vrf; if (debug_vrf) zlog_debug ("%s: Shutting down vrf subsystem", __PRETTY_FUNCTION__); - 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; + while ((vrf = RB_ROOT (&vrfs_by_id)) != NULL) + vrf_delete (vrf); + while ((vrf = RB_ROOT (&vrfs_by_name)) != NULL) + vrf_delete (vrf); } /* Create a socket for the VRF. */ @@ -740,6 +471,66 @@ vrf_socket (int domain, int type, int protocol, vrf_id_t vrf_id) return ret; } +/* vrf CLI commands */ +DEFUN (vrf, + vrf_cmd, + "vrf NAME", + "Select a VRF to configure\n" + "VRF's name\n") +{ + int idx_name = 1; + const char *vrfname = argv[idx_name]->arg; + + struct vrf *vrfp; + size_t sl; + + if ((sl = strlen(vrfname)) > VRF_NAMSIZ) + { + vty_out (vty, "%% VRF name %s is invalid: length exceeds " + "%d characters%s", + vrfname, VRF_NAMSIZ, VTY_NEWLINE); + return CMD_WARNING; + } + + vrfp = vrf_get (VRF_UNKNOWN, vrfname); + + VTY_PUSH_CONTEXT_COMPAT (VRF_NODE, vrfp); + + return CMD_SUCCESS; +} + +DEFUN_NOSH (no_vrf, + no_vrf_cmd, + "no vrf NAME", + NO_STR + "Delete a pseudo VRF's configuration\n" + "VRF's name\n") +{ + const char *vrfname = argv[2]->arg; + + struct vrf *vrfp; + + vrfp = vrf_lookup_by_name (vrfname); + + if (vrfp == NULL) + { + vty_out (vty, "%% VRF %s does not exist%s", vrfname, VTY_NEWLINE); + return CMD_WARNING; + } + + if (CHECK_FLAG (vrfp->status, VRF_ACTIVE)) + { + vty_out (vty, "%% Only inactive VRFs can be deleted%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + vrf_delete(vrfp); + + return CMD_SUCCESS; +} + + /* * Debug CLI for vrf's */ @@ -791,4 +582,7 @@ vrf_install_commands (void) install_element (ENABLE_NODE, &vrf_debug_cmd); install_element (CONFIG_NODE, &no_vrf_debug_cmd); install_element (ENABLE_NODE, &no_vrf_debug_cmd); + + install_element (CONFIG_NODE, &vrf_cmd); + install_element (CONFIG_NODE, &no_vrf_cmd); } @@ -23,6 +23,7 @@ #ifndef _ZEBRA_VRF_H #define _ZEBRA_VRF_H +#include "openbsd-tree.h" #include "linklist.h" #include "qobj.h" @@ -65,18 +66,18 @@ enum { struct vrf { + RB_ENTRY(vrf) id_entry, name_entry; + /* Identifier, same as the vector index */ vrf_id_t vrf_id; - /* Name */ + /* Name */ char name[VRF_NAMSIZ + 1]; /* Zebra internal VRF status */ u_char status; #define VRF_ACTIVE (1 << 0) - struct route_node *node; - /* Master list of interfaces belonging to this VRF */ struct list *iflist; @@ -85,10 +86,15 @@ struct vrf QOBJ_FIELDS }; +RB_HEAD (vrf_id_head, vrf); +RB_PROTOTYPE (vrf_id_head, vrf, id_entry, vrf_id_compare) +RB_HEAD (vrf_name_head, vrf); +RB_PROTOTYPE (vrf_name_head, vrf, name_entry, vrf_name_compare) DECLARE_QOBJ_TYPE(vrf) -extern struct list *vrf_list; +extern struct vrf_id_head vrfs_by_id; +extern struct vrf_name_head vrfs_by_name; /* * Add a specific hook to VRF module. @@ -98,18 +104,10 @@ extern struct list *vrf_list; * - 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, const char *, void **)); +extern void vrf_add_hook (int, int (*)(struct vrf *)); -/* - * VRF iteration - */ - -typedef void * vrf_iter_t; -#define VRF_ITER_INVALID NULL /* invalid value of the iterator */ - -extern struct vrf *vrf_lookup (vrf_id_t); +extern struct vrf *vrf_lookup_by_id (vrf_id_t); extern struct vrf *vrf_lookup_by_name (const char *); -extern struct vrf *vrf_list_lookup_by_name (const char *); extern struct vrf *vrf_get (vrf_id_t, const char *); extern void vrf_delete (struct vrf *); extern int vrf_enable (struct vrf *); @@ -118,7 +116,7 @@ extern vrf_id_t vrf_name_to_id (const char *); #define VRF_GET_ID(V,NAME) \ do { \ struct vrf *vrf; \ - if (!(vrf = vrf_list_lookup_by_name(NAME))) \ + if (!(vrf = vrf_lookup_by_name(NAME))) \ { \ vty_out (vty, "%% VRF %s not found%s", NAME, VTY_NEWLINE);\ return CMD_WARNING; \ @@ -132,34 +130,6 @@ extern vrf_id_t vrf_name_to_id (const char *); } while (0) /* - * VRF iteration utilities. Example for the usage: - * - * vrf_iter_t iter = vrf_first(); - * for (; iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - * - * or - * - * vrf_iter_t iter = vrf_iterator (<a given VRF ID>); - * for (; iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - */ - -/* Return the iterator of the first VRF. */ -extern vrf_iter_t vrf_first (void); -/* Return the next VRF iterator to the given iterator. */ -extern vrf_iter_t vrf_next (vrf_iter_t); -/* Return the VRF iterator of the given VRF ID. If it does not exist, - * the iterator of the next existing VRF is returned. */ -extern vrf_iter_t vrf_iterator (vrf_id_t); - -/* - * VRF iterator to properties - */ -extern vrf_id_t vrf_iter2id (vrf_iter_t); -extern struct vrf *vrf_iter2vrf (vrf_iter_t); -extern void *vrf_iter2info (vrf_iter_t); -extern struct list *vrf_iter2iflist (vrf_iter_t); - -/* * Utilities to obtain the user data */ diff --git a/lib/zclient.c b/lib/zclient.c index 84f7314ba..894e0d19e 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1042,7 +1042,7 @@ zclient_vrf_delete (struct zclient *zclient, vrf_id_t vrf_id) struct vrf *vrf; /* Lookup vrf by vrf_id. */ - vrf = vrf_lookup (vrf_id); + vrf = vrf_lookup_by_id (vrf_id); /* * If a routing protocol doesn't know about a diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index 6caa38d68..088123ea2 100644 --- a/ospfd/ospf_network.c +++ b/ospfd/ospf_network.c @@ -132,18 +132,16 @@ ospf_if_ipmulticast (struct ospf *top, struct prefix *p, ifindex_t ifindex) { u_char val; int ret, len; - - val = 0; - len = sizeof (val); - + /* Prevent receiving self-origined multicast packets. */ - ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void *)&val, len); + ret = setsockopt_ipv4_multicast_loop (top->fd, 0); if (ret < 0) zlog_warn ("can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s", top->fd, safe_strerror(errno)); /* Explicitly set multicast ttl to 1 -- endo. */ val = 1; + len = sizeof (val); ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, len); if (ret < 0) zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s", diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index b7ef24409..72ce5586f 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -2772,6 +2772,7 @@ ospf_read (struct thread *thread) struct ospf_header *ospfh; u_int16_t length; struct interface *ifp; + struct connected *c; /* first of all get interface pointer. */ ospf = THREAD_ARG (thread); @@ -2790,13 +2791,16 @@ ospf_read (struct thread *thread) /* Note that sockopt_iphdrincl_swab_systoh was called in ospf_recv_packet. */ if (ifp == NULL) - /* Handle cases where the platform does not support retrieving the ifindex, - and also platforms (such as Solaris 8) that claim to support ifindex - retrieval but do not. */ - ifp = if_lookup_address ((void *)&iph->ip_src, AF_INET); - - if (ifp == NULL) - return 0; + { + /* Handle cases where the platform does not support retrieving the ifindex, + and also platforms (such as Solaris 8) that claim to support ifindex + retrieval but do not. */ + c = if_lookup_address ((void *)&iph->ip_src, AF_INET); + if (c) + ifp = c->ifp; + if (ifp == NULL) + return 0; + } /* IP Header dump. */ if (IS_DEBUG_OSPF_PACKET(0, RECV)) diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 8662eb425..bc013a83e 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -4393,10 +4393,15 @@ show_ip_ospf_neighbor_detail_sub (struct vty *vty, struct ospf_interface *oi, /* Show Router Dead interval timer. */ if (use_json) { - struct timeval res = tv_sub (nbr->t_inactivity->u.sands, recent_relative_time ()); - unsigned long time_store = 0; - time_store = (1000 * res.tv_sec) + (res.tv_usec / 1000); - json_object_int_add(json_sub, "routerDeadIntervalTimerDueMsec", time_store); + if (nbr->t_inactivity) + { + struct timeval res = tv_sub (nbr->t_inactivity->u.sands, recent_relative_time ()); + unsigned long time_store = 0; + time_store = (1000 * res.tv_sec) + (res.tv_usec / 1000); + json_object_int_add(json_sub, "routerDeadIntervalTimerDueMsec", time_store); + } + else + json_object_int_add(json_sub, "routerDeadIntervalTimerDueMsec", -1); } else vty_out (vty, " Dead timer due in %s%s", diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index a024e3ae0..231efd0f2 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -35,6 +35,7 @@ #include "privs.h" #include "if.h" #include "vrf.h" +#include "sockopt.h" #include "pimd.h" #include "pim_mroute.h" @@ -68,7 +69,7 @@ int pim_socket_raw(int protocol) return fd; } -int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, int loop) +int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char loop) { int fd; @@ -173,8 +174,7 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, int loop) } } - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, - (void *) &loop, sizeof(loop))) { + if (setsockopt_ipv4_multicast_loop (fd, loop)) { zlog_warn("Could not %s Multicast Loopback Option on socket fd=%d: errno=%d: %s", loop ? "enable" : "disable", fd, errno, safe_strerror(errno)); diff --git a/pimd/pim_sock.h b/pimd/pim_sock.h index f0a160081..cd29543fa 100644 --- a/pimd/pim_sock.h +++ b/pimd/pim_sock.h @@ -39,7 +39,7 @@ #define PIM_SOCK_ERR_BIND (-11) /* Can't bind to interface */ int pim_socket_raw(int protocol); -int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, int loop); +int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char loop); int pim_socket_join(int fd, struct in_addr group, struct in_addr ifaddr, ifindex_t ifindex); int pim_socket_join_source(int fd, ifindex_t ifindex, diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index fe88eba27..fba563a6f 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -25,6 +25,7 @@ #include "if.h" #include "log.h" #include "memory.h" +#include "sockopt.h" #include "pim_ssmpingd.h" #include "pim_time.h" @@ -150,17 +151,12 @@ static int ssmpingd_socket(struct in_addr addr, int port, int mttl) return -1; } - { - int loop = 0; - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, - (void *) &loop, sizeof(loop))) { - zlog_warn("%s: could not %s Multicast Loopback Option on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, - loop ? "enable" : "disable", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_LOOP; - } + if (setsockopt_ipv4_multicast_loop (fd, 0)) { + zlog_warn("%s: could not disable Multicast Loopback Option on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_LOOP; } if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, diff --git a/render_md.py b/render_md.py index d2d1fb480..16c4bbe8a 100644 --- a/render_md.py +++ b/render_md.py @@ -4,11 +4,14 @@ import sys, markdown template = '''<html><head><meta charset="UTF-8"><style type="text/css"> body { max-width: 45em; margin: auto; margin-top: 2em; margin-bottom: 2em; - font-family:Fira Sans,sans-serif; text-align: justify; } + font-family:Fira Sans,sans-serif; text-align: justify; + counter-reset: ch2; } pre, code { font-family:Fira Mono,monospace; } pre > code { display: block; padding:0.5em; border:1px solid black; background-color:#eee; color:#000; } -h2 { clear: both; margin-top: 3em; text-decoration: underline; } +h2:before { content: counter(ch2) ". "; counter-increment: ch2; } +h2 { clear: both; margin-top: 3em; text-decoration: underline; counter-reset: ch3; } +h3:before { content: counter(ch2) "." counter(ch3) ". "; counter-increment: ch3; } h3 { clear: both; margin-top: 2em; font-weight: normal; font-style: italic; } h4 { font-weight: normal; font-style: italic; } img[alt~="float-right"] { float:right; margin-left:2em; margin-bottom:2em; } diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 8c5092d78..9cf3338bb 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -55,6 +55,7 @@ const struct message ri_version_msg[] = {RI_RIP_VERSION_1, "1"}, {RI_RIP_VERSION_2, "2"}, {RI_RIP_VERSION_1_AND_2, "1 2"}, + {RI_RIP_VERSION_NONE, "none"}, }; extern struct zebra_privs_t ripd_privs; @@ -537,6 +538,8 @@ rip_interface_reset (struct rip_interface *ri) ri->ri_send = RI_RIP_UNSPEC; ri->ri_receive = RI_RIP_UNSPEC; + ri->v2_broadcast = 0; + if (ri->auth_str) { free (ri->auth_str); @@ -1320,13 +1323,14 @@ DEFUN (no_rip_neighbor, DEFUN (ip_rip_receive_version, ip_rip_receive_version_cmd, - "ip rip receive version (1-2)", + "ip rip receive version <1|2|none>", IP_STR "Routing Information Protocol\n" "Advertisement reception\n" "Version control\n" "RIP version 1\n" - "RIP version 2\n") + "RIP version 2\n" + "None\n") { int idx_type = 4; struct interface *ifp; @@ -1335,17 +1339,21 @@ DEFUN (ip_rip_receive_version, ifp = (struct interface *)vty->index; ri = ifp->info; - /* Version 1. */ - if (atoi (argv[idx_type]->arg) == 1) + switch (argv[idx_type]->arg[0]) { + case '1': ri->ri_receive = RI_RIP_VERSION_1; return CMD_SUCCESS; - } - if (atoi (argv[idx_type]->arg) == 2) - { + case '2': ri->ri_receive = RI_RIP_VERSION_2; return CMD_SUCCESS; + case 'n': + ri->ri_receive = RI_RIP_VERSION_NONE; + return CMD_SUCCESS; + default: + break; } + return CMD_WARNING; } @@ -1508,6 +1516,41 @@ DEFUN (no_ip_rip_send_version, } +DEFUN (ip_rip_v2_broadcast, + ip_rip_v2_broadcast_cmd, + "ip rip v2-broadcast", + IP_STR + "Routing Information Protocol\n" + "Send ip broadcast v2 update\n") +{ + struct interface *ifp; + struct rip_interface *ri; + + ifp = (struct interface *)vty->index; + ri = ifp->info; + + ri->v2_broadcast = 1; + return CMD_SUCCESS; +} + +DEFUN (no_ip_rip_v2_broadcast, + no_ip_rip_v2_broadcast_cmd, + "no ip rip v2-broadcast", + NO_STR + IP_STR + "Routing Information Protocol\n" + "Send ip broadcast v2 update\n") +{ + struct interface *ifp; + struct rip_interface *ri; + + ifp = (struct interface *)vty->index; + ri = ifp->info; + + ri->v2_broadcast = 0; + return CMD_SUCCESS; +} + DEFUN (ip_rip_authentication_mode, ip_rip_authentication_mode_cmd, "ip rip authentication mode <md5|text> [auth-length <rfc|old-ripd>]", @@ -1850,6 +1893,7 @@ rip_interface_config_write (struct vty *vty) (ri->ri_send == RI_RIP_UNSPEC) && (ri->ri_receive == RI_RIP_UNSPEC) && (ri->auth_type != RIP_AUTH_MD5) && + (!ri->v2_broadcast) && (ri->md5_auth_len != RIP_AUTH_MD5_SIZE) && (!ri->auth_str) && (!ri->key_chain) ) @@ -1891,6 +1935,9 @@ rip_interface_config_write (struct vty *vty) lookup (ri_version_msg, ri->ri_receive), VTY_NEWLINE); + if (ri->v2_broadcast) + vty_out (vty, " ip rip v2-broadcast%s", VTY_NEWLINE); + /* RIP authentication. */ if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD) vty_out (vty, " ip rip authentication mode text%s", VTY_NEWLINE); @@ -2029,6 +2076,9 @@ rip_if_init (void) install_element (INTERFACE_NODE, &ip_rip_receive_version_2_cmd); install_element (INTERFACE_NODE, &no_ip_rip_receive_version_cmd); + install_element (INTERFACE_NODE, &ip_rip_v2_broadcast_cmd); + install_element (INTERFACE_NODE, &no_ip_rip_v2_broadcast_cmd); + install_element (INTERFACE_NODE, &ip_rip_authentication_mode_cmd); install_element (INTERFACE_NODE, &no_ip_rip_authentication_mode_cmd); diff --git a/ripd/ripd.c b/ripd/ripd.c index 24ba74c73..9de3ca7c3 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -812,7 +812,15 @@ rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from, struct interface *ifp) { struct rip_interface *ri; - char *auth_str; + char *auth_str = (char *) &rte->prefix; + int i; + + /* reject passwords with zeros in the middle of the string */ + for (i = strlen (auth_str); i < 16; i++) + { + if (auth_str[i] != '\0') + return 0; + } if (IS_RIP_DEBUG_EVENT) zlog_debug ("RIPv2 simple password authentication from %s", @@ -827,8 +835,6 @@ rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from, /* Simple password authentication. */ if (ri->auth_str) { - auth_str = (char *) &rte->prefix; - if (strncmp (auth_str, ri->auth_str, 16) == 0) return 1; } @@ -841,7 +847,7 @@ rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from, if (keychain == NULL) return 0; - key = key_match_for_accept (keychain, (char *) &rte->prefix); + key = key_match_for_accept (keychain, auth_str); if (key) return 1; } @@ -1333,30 +1339,23 @@ rip_response_process (struct rip_packet *packet, int size, /* Make socket for RIP protocol. */ static int -rip_create_socket (struct sockaddr_in *from) +rip_create_socket (void) { int ret; int sock; struct sockaddr_in addr; memset (&addr, 0, sizeof (struct sockaddr_in)); - - if (!from) - { - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - addr.sin_len = sizeof (struct sockaddr_in); + addr.sin_len = sizeof (struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - } else { - memcpy(&addr, from, sizeof(addr)); - } - /* sending port must always be the RIP port */ addr.sin_port = htons (RIP_PORT_DEFAULT); /* Make datagram socket. */ - sock = socket (AF_INET, SOCK_DGRAM, 0); + sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock < 0) { zlog_err("Cannot create UDP socket: %s", safe_strerror(errno)); @@ -1366,6 +1365,7 @@ rip_create_socket (struct sockaddr_in *from) sockopt_broadcast (sock); sockopt_reuseaddr (sock); sockopt_reuseport (sock); + setsockopt_ipv4_multicast_loop (sock, 0); #ifdef RIP_RECVMSG setsockopt_pktinfo (sock); #endif /* RIP_RECVMSG */ @@ -1406,7 +1406,7 @@ static int rip_send_packet (u_char * buf, int size, struct sockaddr_in *to, struct connected *ifc) { - int ret, send_sock; + int ret; struct sockaddr_in sin; assert (ifc != NULL); @@ -1462,38 +1462,16 @@ rip_send_packet (u_char * buf, int size, struct sockaddr_in *to, { sin.sin_port = to->sin_port; sin.sin_addr = to->sin_addr; - send_sock = rip->sock; } else { - struct sockaddr_in from; - sin.sin_port = htons (RIP_PORT_DEFAULT); sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP); - - /* multicast send should bind to local interface address */ - memset (&from, 0, sizeof (from)); - from.sin_family = AF_INET; - from.sin_port = htons (RIP_PORT_DEFAULT); - from.sin_addr = ifc->address->u.prefix4; -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - from.sin_len = sizeof (struct sockaddr_in); -#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - - /* - * we have to open a new socket for each packet because this - * is the most portable way to bind to a different source - * ipv4 address for each packet. - */ - if ( (send_sock = rip_create_socket (&from)) < 0) - { - zlog_warn("rip_send_packet could not create socket."); - return -1; - } - rip_interface_multicast_set (send_sock, ifc); + + rip_interface_multicast_set (rip->sock, ifc); } - ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin, + ret = sendto (rip->sock, buf, size, 0, (struct sockaddr *)&sin, sizeof (struct sockaddr_in)); if (IS_RIP_DEBUG_EVENT) @@ -1503,9 +1481,6 @@ rip_send_packet (u_char * buf, int size, struct sockaddr_in *to, if (ret < 0) zlog_warn ("can't send packet : %s", safe_strerror (errno)); - if (!to) - close(send_sock); - return ret; } @@ -1681,6 +1656,9 @@ rip_request_process (struct rip_packet *packet, int size, } else { + if (ntohs (rte->family) != AF_INET) + return; + /* Examine the list of RTEs in the Request one by one. For each entry, look up the destination in the router's routing database and, if there is a route, put that route's metric in @@ -1803,7 +1781,7 @@ rip_read (struct thread *t) int len; int vrecv; socklen_t fromlen; - struct interface *ifp; + struct interface *ifp = NULL; struct connected *ifc; struct rip_interface *ri; struct prefix p; @@ -1836,8 +1814,10 @@ rip_read (struct thread *t) } /* Which interface is this packet comes from. */ - ifp = if_lookup_address ((void *)&from.sin_addr, AF_INET); - + ifc = if_lookup_address ((void *)&from.sin_addr, AF_INET); + if (ifc) + ifp = ifc->ifp; + /* RIP packet received */ if (IS_RIP_DEBUG_EVENT) zlog_debug ("RECV packet from %s port %d on %s", @@ -1928,15 +1908,9 @@ rip_read (struct thread *t) /* RIP Version check. RFC2453, 4.6 and 5.1 */ vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv : ri->ri_receive); - if ((packet->version == RIPv1) && !(vrecv & RIPv1)) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug (" packet's v%d doesn't fit to if version spec", - packet->version); - rip_peer_bad_packet (&from); - return -1; - } - if ((packet->version == RIPv2) && !(vrecv & RIPv2)) + if (vrecv == RI_RIP_VERSION_NONE || + ((packet->version == RIPv1) && !(vrecv & RIPv1)) || + ((packet->version == RIPv2) && !(vrecv & RIPv2))) { if (IS_RIP_DEBUG_PACKET) zlog_debug (" packet's v%d doesn't fit to if version spec", @@ -2434,20 +2408,22 @@ rip_output_process (struct connected *ifc, struct sockaddr_in *to, static void rip_update_interface (struct connected *ifc, u_char version, int route_type) { + struct interface *ifp = ifc->ifp; + struct rip_interface *ri = ifp->info; struct sockaddr_in to; /* When RIP version is 2 and multicast enable interface. */ - if (version == RIPv2 && if_is_multicast (ifc->ifp)) + if (version == RIPv2 && !ri->v2_broadcast && if_is_multicast (ifp)) { if (IS_RIP_DEBUG_EVENT) - zlog_debug ("multicast announce on %s ", ifc->ifp->name); + zlog_debug ("multicast announce on %s ", ifp->name); rip_output_process (ifc, NULL, route_type, version); return; } /* If we can't send multicast packet, send it with unicast. */ - if (if_is_broadcast (ifc->ifp) || if_is_pointopoint (ifc->ifp)) + if (if_is_broadcast (ifp) || if_is_pointopoint (ifp)) { if (ifc->address->family == AF_INET) { @@ -2469,7 +2445,7 @@ rip_update_interface (struct connected *ifc, u_char version, int route_type) if (IS_RIP_DEBUG_EVENT) zlog_debug("%s announce to %s on %s", CONNECTED_PEER(ifc) ? "unicast" : "broadcast", - inet_ntoa (to.sin_addr), ifc->ifp->name); + inet_ntoa (to.sin_addr), ifp->name); rip_output_process (ifc, &to, route_type, version); } @@ -2539,21 +2515,14 @@ rip_update_process (int route_type) { p = &rp->p; - ifp = if_lookup_prefix (p); - if (! ifp) + connected = if_lookup_address (&p->u.prefix4, AF_INET); + if (! connected) { zlog_warn ("Neighbor %s doesnt have connected interface!", inet_ntoa (p->u.prefix4)); continue; } - if ( (connected = connected_lookup_prefix (ifp, p)) == NULL) - { - zlog_warn ("Neighbor %s doesnt have connected network", - inet_ntoa (p->u.prefix4)); - continue; - } - /* Set destination address and port */ memset (&to, 0, sizeof (struct sockaddr_in)); to.sin_addr = p->u.prefix4; @@ -2579,11 +2548,7 @@ rip_update (struct thread *t) /* Triggered updates may be suppressed if a regular update is due by the time the triggered update would be sent. */ - if (rip->t_triggered_interval) - { - thread_cancel (rip->t_triggered_interval); - rip->t_triggered_interval = NULL; - } + RIP_TIMER_OFF (rip->t_triggered_interval); rip->trigger = 0; /* Register myself. */ @@ -2637,11 +2602,7 @@ rip_triggered_update (struct thread *t) rip->t_triggered_update = NULL; /* Cancel interval timer. */ - if (rip->t_triggered_interval) - { - thread_cancel (rip->t_triggered_interval); - rip->t_triggered_interval = NULL; - } + RIP_TIMER_OFF (rip->t_triggered_interval); rip->trigger = 0; /* Logging triggered update. */ @@ -2729,7 +2690,7 @@ rip_create (void) rip->obuf = stream_new (1500); /* Make socket. */ - rip->sock = rip_create_socket (NULL); + rip->sock = rip_create_socket (); if (rip->sock < 0) return rip->sock; @@ -2819,11 +2780,7 @@ rip_event (enum rip_event event, int sock) rip->t_read = thread_add_read (master, rip_read, NULL, sock); break; case RIP_UPDATE_EVENT: - if (rip->t_update) - { - thread_cancel (rip->t_update); - rip->t_update = NULL; - } + RIP_TIMER_OFF (rip->t_update); jitter = rip_update_jitter (rip->update_time); rip->t_update = thread_add_timer (master, rip_update, NULL, @@ -3919,11 +3876,7 @@ rip_clean (void) RIP_TIMER_OFF (rip->t_triggered_interval); /* Cancel read thread. */ - if (rip->t_read) - { - thread_cancel (rip->t_read); - rip->t_read = NULL; - } + THREAD_READ_OFF (rip->t_read); /* Close RIP socket. */ if (rip->sock >= 0) diff --git a/ripd/ripd.h b/ripd/ripd.h index 1cc46ff31..cd4d560af 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -258,6 +258,9 @@ struct rip_interface int ri_send; int ri_receive; + /* RIPv2 broadcast mode */ + int v2_broadcast; + /* RIPv2 authentication type. */ int auth_type; @@ -347,6 +350,7 @@ struct rip_md5_data #define RI_RIP_VERSION_1 1 #define RI_RIP_VERSION_2 2 #define RI_RIP_VERSION_1_AND_2 3 +#define RI_RIP_VERSION_NONE 4 /* N.B. stuff will break if (RIPv1 != RI_RIP_VERSION_1) || (RIPv2 != RI_RIP_VERSION_2) */ @@ -369,14 +373,7 @@ enum rip_event } while (0) /* Macro for timer turn off. */ -#define RIP_TIMER_OFF(X) \ - do { \ - if (X) \ - { \ - thread_cancel (X); \ - (X) = NULL; \ - } \ - } while (0) +#define RIP_TIMER_OFF(X) THREAD_TIMER_OFF(X) /* Prototypes. */ extern void rip_init (void); diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index 7bee7625d..664187030 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -65,7 +65,7 @@ ripng_multicast_join (struct interface *ifp) struct ipv6_mreq mreq; int save_errno; - if (if_is_up (ifp) && if_is_multicast (ifp)) { + if (if_is_multicast (ifp)) { memset (&mreq, 0, sizeof (mreq)); inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr); mreq.ipv6mr_interface = ifp->ifindex; @@ -116,7 +116,7 @@ ripng_multicast_leave (struct interface *ifp) int ret; struct ipv6_mreq mreq; - if (if_is_up (ifp) && if_is_multicast (ifp)) { + if (if_is_multicast (ifp)) { memset (&mreq, 0, sizeof (mreq)); inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr); mreq.ipv6mr_interface = ifp->ifindex; diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index e7db97120..ca8850e5f 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -829,8 +829,10 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from, * with the new one in below. */ break; - /* Metrics are same. Keep "rinfo" null and the new route - * is added in the ECMP list in below. */ + /* Metrics are same. Unless ECMP is disabled, keep "rinfo" null and + * the new route is added in the ECMP list in below. */ + if (! ripng->ecmp) + break; } } @@ -874,11 +876,24 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from, same = (IN6_ARE_ADDR_EQUAL (&rinfo->from, &from->sin6_addr) && (rinfo->ifindex == ifp->ifindex)); + /* + * RFC 2080 - Section 2.4.2: + * "If the new metric is the same as the old one, examine the timeout + * for the existing route. If it is at least halfway to the expiration + * point, switch to the new route. This heuristic is optional, but + * highly recommended". + */ + if (!ripng->ecmp && !same && + rinfo->metric == rte->metric && rinfo->t_timeout && + (thread_timer_remain_second (rinfo->t_timeout) < (ripng->timeout_time / 2))) + { + ripng_ecmp_replace (&newinfo); + } /* Next, compare the metrics. If the datagram is from the same router as the existing route, and the new metric is different than the old one; or, if the new metric is lower than the old one; do the following actions: */ - if ((same && rinfo->metric != rte->metric) || + else if ((same && rinfo->metric != rte->metric) || rte->metric < rinfo->metric) { if (listcount (list) == 1) @@ -2155,6 +2170,54 @@ DEFUN (show_ipv6_ripng_status, return CMD_SUCCESS; } +DEFUN (clear_ipv6_rip, + clear_ipv6_rip_cmd, + "clear ipv6 ripng", + CLEAR_STR + IPV6_STR + "Clear IPv6 RIP database") +{ + struct route_node *rp; + struct ripng_info *rinfo; + struct list *list; + struct listnode *listnode; + + /* Clear received RIPng routes */ + for (rp = route_top (ripng->table); rp; rp = route_next (rp)) + { + list = rp->info; + if (list == NULL) + continue; + + for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) + { + if (! ripng_route_rte (rinfo)) + continue; + + if (CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB)) + ripng_zebra_ipv6_delete (rp); + break; + } + + if (rinfo) + { + RIPNG_TIMER_OFF (rinfo->t_timeout); + RIPNG_TIMER_OFF (rinfo->t_garbage_collect); + listnode_delete (list, rinfo); + ripng_info_free (rinfo); + } + + if (list_isempty (list)) + { + list_free (list); + rp->info = NULL; + route_unlock_node (rp); + } + } + + return CMD_SUCCESS; +} + DEFUN (router_ripng, router_ripng_cmd, "router ripng", @@ -3028,6 +3091,8 @@ ripng_init () install_element (VIEW_NODE, &show_ipv6_ripng_cmd); install_element (VIEW_NODE, &show_ipv6_ripng_status_cmd); + install_element (ENABLE_NODE, &clear_ipv6_rip_cmd); + install_element (CONFIG_NODE, &router_ripng_cmd); install_element (CONFIG_NODE, &no_router_ripng_cmd); diff --git a/tests/bgp_mpath_test.c b/tests/bgp_mpath_test.c index dbcb00a2e..723f2977d 100644 --- a/tests/bgp_mpath_test.c +++ b/tests/bgp_mpath_test.c @@ -37,6 +37,7 @@ #include "bgpd/bgp_table.h" #include "bgpd/bgp_route.h" #include "bgpd/bgp_attr.h" +#include "bgpd/bgp_nexthop.h" #include "bgpd/bgp_mpath.h" #define VT100_RESET "\x1b[0m" @@ -116,6 +117,7 @@ bgp_create_fake (as_t *as, const char *name) bgp->maxpaths[afi][safi].maxpaths_ibgp = MULTIPATH_NUM; } + bgp_scan_init (bgp); bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF; bgp->default_holdtime = BGP_DEFAULT_HOLDTIME; bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE; diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index f7f6334a7..c5fd16b9c 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -209,13 +209,6 @@ netlink_vrf_change (struct nlmsghdr *h, struct rtattr *tb, const char *name) if (h->nlmsg_type == RTM_NEWLINK) { - /* If VRF already exists, we just return; status changes are handled - * against the VRF "interface". - */ - vrf = vrf_lookup ((vrf_id_t)ifi->ifi_index); - if (vrf && vrf->info) - return; - if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug ("RTM_NEWLINK for VRF %s(%u) table %u", name, ifi->ifi_index, nl_table_id); @@ -251,7 +244,7 @@ netlink_vrf_change (struct nlmsghdr *h, struct rtattr *tb, const char *name) if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug ("RTM_DELLINK for VRF %s(%u)", name, ifi->ifi_index); - vrf = vrf_lookup ((vrf_id_t)ifi->ifi_index); + vrf = vrf_lookup_by_id ((vrf_id_t)ifi->ifi_index); if (!vrf) { diff --git a/zebra/interface.c b/zebra/interface.c index 91dbe5276..f48450d5e 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -59,6 +59,20 @@ const char *rtadv_pref_strs[] = { "medium", "high", "INVALID", "low", 0 }; static void if_down_del_nbr_connected (struct interface *ifp); +static void +zebra_if_node_destroy (route_table_delegate_t *delegate, + struct route_table *table, struct route_node *node) +{ + if (node->info) + list_delete (node->info); + route_node_destroy (delegate, table, node); +} + +route_table_delegate_t zebra_if_table_delegate = { + .create_node = route_node_create, + .destroy_node = zebra_if_node_destroy +}; + /* Called when new interface is added. */ static int if_zebra_new_hook (struct interface *ifp) @@ -101,7 +115,7 @@ if_zebra_new_hook (struct interface *ifp) #endif /* HAVE_RTADV */ /* Initialize installed address chains tree. */ - zebra_if->ipv4_subnets = route_table_init (); + zebra_if->ipv4_subnets = route_table_init_with_delegate (&zebra_if_table_delegate); ifp->info = zebra_if; @@ -1025,7 +1039,7 @@ if_dump_vty (struct vty *vty, struct interface *ifp) zebra_ptm_show_status(vty, ifp); - vrf = vrf_lookup(ifp->vrf_id); + vrf = vrf_lookup_by_id (ifp->vrf_id); vty_out (vty, " vrf: %s%s", vrf->name, VTY_NEWLINE); if (ifp->desc) @@ -1269,33 +1283,6 @@ struct cmd_node interface_node = 1 }; -/* Wrapper hook point for zebra daemon so that ifindex can be set - * DEFUN macro not used as extract.pl HAS to ignore this - * See also interface_cmd in lib/if.c - */ -DEFUN_NOSH (zebra_vrf, - zebra_vrf_cmd, - "vrf NAME", - "Select a VRF to configure\n" - "VRF's name\n") -{ - // VTY_DECLVAR_CONTEXT (vrf, vrfp); - int ret; - - /* Call lib vrf() */ - if ((ret = vrf_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS) - return ret; - - return ret; -} - -struct cmd_node vrf_node = -{ - VRF_NODE, - "%s(config-vrf)# ", - 1 -}; - /* Show all interfaces to vty. */ DEFUN (show_interface, show_interface_cmd, @@ -1329,15 +1316,15 @@ DEFUN (show_interface_vrf_all, "Interface status and configuration\n" VRF_ALL_CMD_HELP_STR) { + struct vrf *vrf; struct listnode *node; struct interface *ifp; - vrf_iter_t iter; interface_update_stats (); /* 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)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp)) if_dump_vty (vty, ifp); return CMD_SUCCESS; @@ -1385,17 +1372,17 @@ DEFUN (show_interface_name_vrf_all, VRF_ALL_CMD_HELP_STR) { int idx_ifname = 2; + struct vrf *vrf; struct interface *ifp; - vrf_iter_t iter; int found = 0; interface_update_stats (); /* All interface print. */ - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { /* Specified interface print. */ - ifp = if_lookup_by_name_vrf (argv[idx_ifname]->arg, vrf_iter2id (iter)); + ifp = if_lookup_by_name_vrf (argv[idx_ifname]->arg, vrf->vrf_id); if (ifp) { if_dump_vty (vty, ifp); @@ -1480,15 +1467,14 @@ DEFUN (show_interface_desc_vrf_all, "Interface description\n" VRF_ALL_CMD_HELP_STR) { - vrf_iter_t iter; + struct vrf *vrf; - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - if (!list_isempty (vrf_iter2iflist (iter))) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + if (!list_isempty (vrf->iflist)) { - vty_out (vty, "%s\tVRF %u%s%s", VTY_NEWLINE, - vrf_iter2id (iter), - VTY_NEWLINE, VTY_NEWLINE); - if_show_description (vty, vrf_iter2id (iter)); + vty_out (vty, "%s\tVRF %u%s%s", VTY_NEWLINE, vrf->vrf_id, + VTY_NEWLINE, VTY_NEWLINE); + if_show_description (vty, vrf->vrf_id); } return CMD_SUCCESS; @@ -1825,7 +1811,7 @@ DEFUN (link_params_metric, VTY_GET_ULONG("metric", metric, argv[idx_number]->arg); /* Update TE metric if needed */ - link_param_cmd_set_uint32 (ifp, &iflp->te_metric, LP_TE, metric); + link_param_cmd_set_uint32 (ifp, &iflp->te_metric, LP_TE | LP_TE_METRIC, metric); return CMD_SUCCESS; } @@ -1839,7 +1825,7 @@ DEFUN (no_link_params_metric, VTY_DECLVAR_CONTEXT (interface, ifp); /* Unset TE Metric */ - link_param_cmd_unset(ifp, LP_TE); + link_param_cmd_unset(ifp, LP_TE | LP_TE_METRIC); return CMD_SUCCESS; } @@ -2777,20 +2763,21 @@ link_params_config_write (struct vty *vty, struct interface *ifp) vty_out (vty, " link-params%s", VTY_NEWLINE); vty_out(vty, " enable%s", VTY_NEWLINE); - if (IS_PARAM_SET(iflp, LP_TE)) + if (IS_PARAM_SET(iflp, LP_TE) && IS_PARAM_SET(iflp, LP_TE_METRIC)) vty_out(vty, " metric %u%s",iflp->te_metric, VTY_NEWLINE); - if (IS_PARAM_SET(iflp, LP_MAX_BW)) + if (IS_PARAM_SET(iflp, LP_MAX_BW) && iflp->max_bw != iflp->default_bw) vty_out(vty, " max-bw %g%s", iflp->max_bw, VTY_NEWLINE); - if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW)) + if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW) && iflp->max_rsv_bw != iflp->default_bw) vty_out(vty, " max-rsv-bw %g%s", iflp->max_rsv_bw, VTY_NEWLINE); if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) { for (i = 0; i < 8; i++) - vty_out(vty, " unrsv-bw %d %g%s", - i, iflp->unrsv_bw[i], VTY_NEWLINE); + if (iflp->unrsv_bw[i] != iflp->default_bw) + vty_out(vty, " unrsv-bw %d %g%s", + i, iflp->unrsv_bw[i], VTY_NEWLINE); } if (IS_PARAM_SET(iflp, LP_ADM_GRP)) - vty_out(vty, " admin-grp %u%s", iflp->admin_grp, VTY_NEWLINE); + vty_out(vty, " admin-grp 0x%x%s", iflp->admin_grp, VTY_NEWLINE); if (IS_PARAM_SET(iflp, LP_DELAY)) { vty_out(vty, " delay %u", iflp->av_delay); @@ -2821,14 +2808,14 @@ link_params_config_write (struct vty *vty, struct interface *ifp) static int if_config_write (struct vty *vty) { + struct vrf *vrf; struct listnode *node; struct interface *ifp; - vrf_iter_t iter; zebra_ptm_write (vty); - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - for (ALL_LIST_ELEMENTS_RO (vrf_iter2iflist (iter), node, ifp)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp)) { struct zebra_if *if_data; struct listnode *addrnode; @@ -2837,7 +2824,7 @@ if_config_write (struct vty *vty) struct vrf *vrf; if_data = ifp->info; - vrf = vrf_lookup(ifp->vrf_id); + vrf = vrf_lookup_by_id (ifp->vrf_id); if (ifp->vrf_id == VRF_DEFAULT) vty_out (vty, "interface %s%s", ifp->name, VTY_NEWLINE); @@ -2905,23 +2892,6 @@ if_config_write (struct vty *vty) return 0; } -static int -vrf_config_write (struct vty *vty) -{ - struct listnode *node; - struct zebra_vrf *zvrf; - - for (ALL_LIST_ELEMENTS_RO (zvrf_list, node, zvrf)) - { - if (strcmp(zvrf->name, VRF_DEFAULT_NAME)) - { - vty_out (vty, "vrf %s%s", zvrf->name, VTY_NEWLINE); - vty_out (vty, "!%s", VTY_NEWLINE); - } - } - return 0; -} - /* Allocate and initialize interface vector. */ void zebra_if_init (void) @@ -2933,7 +2903,6 @@ zebra_if_init (void) /* Install configuration write function. */ install_node (&interface_node, if_config_write); install_node (&link_params_node, NULL); - install_node (&vrf_node, vrf_config_write); install_element (VIEW_NODE, &show_interface_cmd); install_element (VIEW_NODE, &show_interface_vrf_all_cmd); @@ -2990,8 +2959,4 @@ zebra_if_init (void) install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd); install_element(LINK_PARAMS_NODE, &no_link_params_use_bw_cmd); install_element(LINK_PARAMS_NODE, &exit_link_params_cmd); - - install_element (CONFIG_NODE, &zebra_vrf_cmd); - install_element (CONFIG_NODE, &no_vrf_cmd); - install_default (VRF_NODE); } diff --git a/zebra/irdp_main.c b/zebra/irdp_main.c index cc3a4abaf..7fa4ad4cb 100644 --- a/zebra/irdp_main.c +++ b/zebra/irdp_main.c @@ -304,17 +304,16 @@ void process_solicit (struct interface *ifp) void irdp_finish() { - + struct vrf *vrf; struct listnode *node, *nnode; struct interface *ifp; struct zebra_if *zi; struct irdp_interface *irdp; - vrf_iter_t iter; zlog_info("IRDP: Received shutdown notification."); - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - for (ALL_LIST_ELEMENTS (vrf_iter2iflist (iter), node, nnode, ifp)) + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) + for (ALL_LIST_ELEMENTS (vrf->iflist, node, nnode, ifp)) { zi = ifp->info; diff --git a/zebra/irdp_packet.c b/zebra/irdp_packet.c index 25c7aff26..c9c32ce31 100644 --- a/zebra/irdp_packet.c +++ b/zebra/irdp_packet.c @@ -282,7 +282,7 @@ send_packet(struct interface *ifp, char buf[256]; struct in_pktinfo *pktinfo; u_long src; - int on; + u_char on; if (!(ifp->flags & IFF_UP)) return; @@ -323,12 +323,8 @@ send_packet(struct interface *ifp, zlog_warn("sendto %s", safe_strerror (errno)); } - if(dst != INADDR_BROADCAST) { - on = 0; - if( setsockopt(irdp_sock,IPPROTO_IP, IP_MULTICAST_LOOP, - (char *)&on,sizeof(on)) < 0) - zlog_warn("sendto %s", safe_strerror (errno)); - } + if(dst != INADDR_BROADCAST) + setsockopt_ipv4_multicast_loop (irdp_sock, 0); memset(&sockdst,0,sizeof(sockdst)); sockdst.sin_family=AF_INET; diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 378327ab4..9f9a62f38 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -716,11 +716,18 @@ kernel_init (struct zebra_ns *zns) { unsigned long groups; - groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR; -#ifdef HAVE_IPV6 - groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR; -#endif /* HAVE_IPV6 */ + /* Initialize netlink sockets */ + groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR | + RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR; + + snprintf (zns->netlink.name, sizeof (zns->netlink.name), + "netlink-listen (NS %u)", zns->ns_id); + zns->netlink.sock = -1; netlink_socket (&zns->netlink, groups, zns->ns_id); + + snprintf (zns->netlink_cmd.name, sizeof (zns->netlink_cmd.name), + "netlink-cmd (NS %u)", zns->ns_id); + zns->netlink_cmd.sock = -1; netlink_socket (&zns->netlink_cmd, 0, zns->ns_id); /* Register kernel socket. */ diff --git a/zebra/main.c b/zebra/main.c index 9247d4350..4fea0104f 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -182,20 +182,46 @@ sighup (void) static void sigint (void) { + struct vrf *vrf; + struct zebra_vrf *zvrf; struct zebra_ns *zns; zlog_notice ("Terminating on signal"); - if (!retain_mode) - rib_close (); #ifdef HAVE_IRDP irdp_finish(); #endif zebra_ptm_finish(); + list_delete_all_node (zebrad.client_list); + + if (retain_mode) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + { + zvrf = vrf->info; + if (zvrf) + SET_FLAG (zvrf->flags, ZEBRA_VRF_RETAIN); + } + vrf_terminate (); zns = zebra_ns_lookup (NS_DEFAULT); zebra_ns_disable (0, (void **)&zns); + + access_list_reset (); + prefix_list_reset (); + route_map_finish (); + cmd_terminate (); + vty_terminate (); + zprivs_terminate (&zserv_privs); + list_delete (zebrad.client_list); + work_queue_free (zebrad.ribq); + if (zebrad.lsp_process_q) + work_queue_free (zebrad.lsp_process_q); + meta_queue_free (zebrad.mq); + thread_master_free (zebrad.master); + if (zlog_default) + closezlog (zlog_default); + exit (0); } diff --git a/zebra/redistribute.c b/zebra/redistribute.c index c74485bb3..9c7ef5f12 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -262,13 +262,13 @@ zebra_redistribute_add (int command, struct zserv *client, int length, if (! redist_check_instance (&client->mi_redist[afi][type], instance)) { redist_add_instance (&client->mi_redist[afi][type], instance); - zebra_redistribute (client, type, instance, zvrf->vrf_id); + zebra_redistribute (client, type, instance, zvrf_id (zvrf)); } } else { - if (! vrf_bitmap_check (client->redist[afi][type], zvrf->vrf_id)) + if (! vrf_bitmap_check (client->redist[afi][type], zvrf_id (zvrf))) { - vrf_bitmap_set (client->redist[afi][type], zvrf->vrf_id); - zebra_redistribute (client, type, 0, zvrf->vrf_id); + vrf_bitmap_set (client->redist[afi][type], zvrf_id (zvrf)); + zebra_redistribute (client, type, 0, zvrf_id (zvrf)); } } } @@ -296,22 +296,22 @@ zebra_redistribute_delete (int command, struct zserv *client, int length, if (instance) redist_del_instance (&client->mi_redist[afi][type], instance); else - vrf_bitmap_unset (client->redist[afi][type], zvrf->vrf_id); + vrf_bitmap_unset (client->redist[afi][type], zvrf_id (zvrf)); } void zebra_redistribute_default_add (int command, struct zserv *client, int length, struct zebra_vrf *zvrf) { - vrf_bitmap_set (client->redist_default, zvrf->vrf_id); - zebra_redistribute_default (client, zvrf->vrf_id); + vrf_bitmap_set (client->redist_default, zvrf_id (zvrf)); + zebra_redistribute_default (client, zvrf_id (zvrf)); } void zebra_redistribute_default_delete (int command, struct zserv *client, int length, struct zebra_vrf *zvrf) { - vrf_bitmap_unset (client->redist_default, zvrf->vrf_id); + vrf_bitmap_unset (client->redist_default, zvrf_id (zvrf)); } /* Interface up information. */ diff --git a/zebra/rib.h b/zebra/rib.h index c95a9ba0c..30929f1be 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -366,13 +366,14 @@ extern void rib_update (vrf_id_t, rib_update_event_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); extern void rib_queue_add (struct route_node *rn); +extern void meta_queue_free (struct meta_queue *mq); extern struct route_table *rib_table_ipv6; +extern void rib_unlink (struct route_node *, struct rib *); extern int rib_gc_dest (struct route_node *rn); extern struct route_table *rib_tables_iter_next (rib_tables_iter_t *iter); diff --git a/zebra/router-id.c b/zebra/router-id.c index 23b8cc743..b1e786d0c 100644 --- a/zebra/router-id.c +++ b/zebra/router-id.c @@ -138,7 +138,7 @@ router_id_add_address (struct connected *ifc) if (router_id_bad_address (ifc)) return; - router_id_get (&before, zvrf->vrf_id); + router_id_get (&before, zvrf_id (zvrf)); if (!strncmp (ifc->ifp->name, "lo", 2) || !strncmp (ifc->ifp->name, "dummy", 5)) @@ -149,13 +149,13 @@ router_id_add_address (struct connected *ifc) if (!router_id_find_node (l, ifc)) listnode_add_sort (l, ifc); - router_id_get (&after, zvrf->vrf_id); + router_id_get (&after, zvrf_id (zvrf)); if (prefix_same (&before, &after)) return; for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client)) - zsend_router_id_update (client, &after, zvrf->vrf_id); + zsend_router_id_update (client, &after, zvrf_id (zvrf)); } void @@ -172,7 +172,7 @@ router_id_del_address (struct connected *ifc) if (router_id_bad_address (ifc)) return; - router_id_get (&before, zvrf->vrf_id); + router_id_get (&before, zvrf_id (zvrf)); if (!strncmp (ifc->ifp->name, "lo", 2) || !strncmp (ifc->ifp->name, "dummy", 5)) @@ -183,33 +183,33 @@ router_id_del_address (struct connected *ifc) if ((c = router_id_find_node (l, ifc))) listnode_delete (l, c); - router_id_get (&after, zvrf->vrf_id); + router_id_get (&after, zvrf_id (zvrf)); if (prefix_same (&before, &after)) return; for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client)) - zsend_router_id_update (client, &after, zvrf->vrf_id); + zsend_router_id_update (client, &after, zvrf_id (zvrf)); } void router_id_write (struct vty *vty) { + struct vrf *vrf; 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) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) if (zvrf->rid_user_assigned.u.prefix4.s_addr) { - if (zvrf->vrf_id == VRF_DEFAULT) + if (zvrf_id (zvrf) == 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 %s%s", inet_ntoa (zvrf->rid_user_assigned.u.prefix4), - zvrf->name, + zvrf_name (zvrf), VTY_NEWLINE); } } diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 90d71e635..f168ef395 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -99,16 +99,16 @@ Pending: create an efficient table_id (in a tree/hash) based lookup) static vrf_id_t vrf_lookup_by_table (u_int32_t table_id) { + struct vrf *vrf; struct zebra_vrf *zvrf; - vrf_iter_t iter; - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - if ((zvrf = vrf_iter2info (iter)) == NULL || + if ((zvrf = vrf->info) == NULL || (zvrf->table_id != table_id)) continue; - return zvrf->vrf_id; + return zvrf_id (zvrf); } return VRF_DEFAULT; @@ -1069,7 +1069,7 @@ _netlink_route_debug( zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s", routedesc, nl_msg_type_to_str (cmd), - prefix2str (p, buf, sizeof(buf)), zvrf->vrf_id, + prefix2str (p, buf, sizeof(buf)), zvrf_id (zvrf), (nexthop) ? nexthop_type_to_str (nexthop->type) : "UNK"); } } diff --git a/zebra/rtadv.c b/zebra/rtadv.c index dcf31ff45..0d4ce9313 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -374,7 +374,7 @@ static int rtadv_timer (struct thread *thread) { struct zebra_ns *zns = THREAD_ARG (thread); - vrf_iter_t iter; + struct vrf *vrf; struct listnode *node, *nnode; struct interface *ifp; struct zebra_if *zif; @@ -392,8 +392,8 @@ rtadv_timer (struct thread *thread) rtadv_event (zns, RTADV_TIMER_MSEC, 10 /* 10 ms */); } - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - for (ALL_LIST_ELEMENTS (vrf_iter2iflist (iter), node, nnode, ifp)) + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) + for (ALL_LIST_ELEMENTS (vrf->iflist, node, nnode, ifp)) { if (if_is_loopback (ifp) || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK) || @@ -827,7 +827,7 @@ zebra_interface_radv_set (struct zserv *client, int sock, u_short length, if (IS_ZEBRA_DEBUG_EVENT) zlog_debug("%u: IF %u RA %s from client %s, interval %ds", - zvrf->vrf_id, ifindex, enable ? "enable" : "disable", + zvrf_id (zvrf), ifindex, enable ? "enable" : "disable", zebra_route_string(client->proto), ra_interval); /* Locate interface and check VRF match. */ @@ -835,14 +835,14 @@ zebra_interface_radv_set (struct zserv *client, int sock, u_short length, if (!ifp) { zlog_warn("%u: IF %u RA %s client %s - interface unknown", - zvrf->vrf_id, ifindex, enable ? "enable" : "disable", + zvrf_id (zvrf), ifindex, enable ? "enable" : "disable", zebra_route_string(client->proto)); return; } - if (ifp->vrf_id != zvrf->vrf_id) + if (ifp->vrf_id != zvrf_id (zvrf)) { zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u", - zvrf->vrf_id, ifindex, enable ? "enable" : "disable", + zvrf_id (zvrf), ifindex, enable ? "enable" : "disable", zebra_route_string(client->proto), ifp->vrf_id); return; } diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index 7e8b8682d..80512c71f 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -348,7 +348,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->zvrf->vrf_id != 0) + if (zvrf_id (info->zvrf) != 0) return 0; if (info->safi != SAFI_UNICAST) diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index f2cba1094..a09008b39 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)->vrf_id; + ri->rtm_table = zvrf_id (rib_dest_vrf (dest)); ri->rtm_protocol = RTPROT_UNSPEC; /* diff --git a/zebra/zebra_memory.h b/zebra/zebra_memory.h index fbd8f3261..c1ac4fe95 100644 --- a/zebra/zebra_memory.h +++ b/zebra/zebra_memory.h @@ -35,6 +35,5 @@ DECLARE_MTYPE(STATIC_ROUTE) DECLARE_MTYPE(RIB_DEST) DECLARE_MTYPE(RIB_TABLE_INFO) DECLARE_MTYPE(RNH) -DECLARE_MTYPE(NETLINK_NAME) #endif /* _QUAGGA_ZEBRA_MEMORY_H */ diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 3b19a5da0..3333b7226 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -1267,7 +1267,7 @@ mpls_ftn_update (int add, struct zebra_vrf *zvrf, enum lsp_types_t type, struct nexthop *nexthop; /* Lookup table. */ - table = zebra_vrf_table (family2afi(prefix->family), SAFI_UNICAST, zvrf->vrf_id); + table = zebra_vrf_table (family2afi(prefix->family), SAFI_UNICAST, zvrf_id (zvrf)); if (! table) return -1; @@ -1501,7 +1501,7 @@ mpls_ldp_ftn_uninstall_all (struct zebra_vrf *zvrf, int afi) int update; /* Process routes of interested address-families. */ - table = zebra_vrf_table (afi, SAFI_UNICAST, zvrf->vrf_id); + table = zebra_vrf_table (afi, SAFI_UNICAST, zvrf_id (zvrf)); if (!table) return; @@ -1828,7 +1828,7 @@ zebra_mpls_print_lsp_table (struct vty *vty, struct zebra_vrf *zvrf, vty_out (vty, "%s", VTY_NEWLINE); } - list_delete_all_node(lsp_list); + list_delete (lsp_list); } /* @@ -1868,7 +1868,7 @@ zebra_mpls_write_lsp_config (struct vty *vty, struct zebra_vrf *zvrf) } } - list_delete_all_node(slsp_list); + list_delete (slsp_list); return (zvrf->slsp_table->count ? 1 : 0); } @@ -1880,9 +1880,11 @@ zebra_mpls_write_lsp_config (struct vty *vty, struct zebra_vrf *zvrf) void zebra_mpls_close_tables (struct zebra_vrf *zvrf) { - if (!zvrf) - return; hash_iterate(zvrf->lsp_table, lsp_uninstall_from_kernel, NULL); + hash_clean(zvrf->lsp_table, NULL); + hash_free(zvrf->lsp_table); + hash_clean(zvrf->slsp_table, NULL); + hash_free(zvrf->slsp_table); } /* diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index 41034e198..642d2700a 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -32,7 +32,6 @@ #include "zebra_memory.h" DEFINE_MTYPE(ZEBRA, ZEBRA_NS, "Zebra Name Space") -DEFINE_MTYPE(ZEBRA, NETLINK_NAME, "Netlink name") struct zebra_ns *dzns; @@ -46,24 +45,11 @@ int zebra_ns_enable (ns_id_t ns_id, void **info) { struct zebra_ns *zns = (struct zebra_ns *) (*info); -#ifdef HAVE_NETLINK - char nl_name[64]; -#endif #if defined (HAVE_RTADV) rtadv_init (zns); #endif -#ifdef HAVE_NETLINK - /* Initialize netlink sockets */ - snprintf (nl_name, 64, "netlink-listen (NS %u)", ns_id); - zns->netlink.sock = -1; - zns->netlink.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name); - - snprintf (nl_name, 64, "netlink-cmd (NS %u)", ns_id); - zns->netlink_cmd.sock = -1; - zns->netlink_cmd.name = XSTRDUP (MTYPE_NETLINK_NAME, nl_name); -#endif zns->if_table = route_table_init (); kernel_init (zns); interface_list (zns); @@ -77,6 +63,7 @@ zebra_ns_disable (ns_id_t ns_id, void **info) { struct zebra_ns *zns = (struct zebra_ns *) (*info); + route_table_finish (zns->if_table); #if defined (HAVE_RTADV) rtadv_terminate (zns); #endif diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h index 8a821c465..c50f9249d 100644 --- a/zebra/zebra_ns.h +++ b/zebra/zebra_ns.h @@ -32,7 +32,7 @@ struct nlsock int sock; int seq; struct sockaddr_nl snl; - const char *name; + char name[64]; }; #endif diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index ebae1bd4b..e6d13b507 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -140,6 +140,8 @@ zebra_ptm_finish(void) buffer_flush_all(ptm_cb.wb, ptm_cb.ptm_sock); + free (ptm_hdl); + if (ptm_cb.out_data) free(ptm_cb.out_data); @@ -256,15 +258,15 @@ DEFUN (zebra_ptm_enable, "ptm-enable", "Enable neighbor check with specified topology\n") { + struct vrf *vrf; struct listnode *i; struct interface *ifp; struct zebra_if *if_data; - vrf_iter_t iter; ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_ON; - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - for (ALL_LIST_ELEMENTS_RO (vrf_iter2iflist (iter), i, ifp)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + for (ALL_LIST_ELEMENTS_RO (vrf->iflist, i, ifp)) if (!ifp->ptm_enable) { if_data = (struct zebra_if *)ifp->info; @@ -766,9 +768,9 @@ zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length, ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD, tmp_buf); - if (zvrf->vrf_id != VRF_DEFAULT) + if (zvrf_id (zvrf) != VRF_DEFAULT) ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_VRF_NAME_FIELD, - zvrf->name); + zvrf_name (zvrf)); } else { @@ -913,9 +915,9 @@ zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, u_short length, ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); } #endif /* HAVE_IPV6 */ - if (zvrf->vrf_id != VRF_DEFAULT) + if (zvrf_id (zvrf) != VRF_DEFAULT) ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_VRF_NAME_FIELD, - zvrf->name); + zvrf_name (zvrf)); } else { @@ -1110,13 +1112,13 @@ zebra_ptm_send_status_req(void) void zebra_ptm_reset_status(int ptm_disable) { + struct vrf *vrf; struct listnode *i; struct interface *ifp; int send_linkup; - vrf_iter_t iter; - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - for (ALL_LIST_ELEMENTS_RO (vrf_iter2iflist (iter), i, ifp)) + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) + for (ALL_LIST_ELEMENTS_RO (vrf->iflist, i, ifp)) { send_linkup = 0; if (ifp->ptm_enable) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 8b36eb806..c573f6bd5 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1303,8 +1303,6 @@ rib_uninstall (struct route_node *rn, struct rib *rib) } } -static void rib_unlink (struct route_node *, struct rib *); - /* * rib_can_delete_dest * @@ -1352,7 +1350,7 @@ rib_gc_dest (struct route_node *rn) zvrf = rib_dest_vrf (dest); if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, zvrf->vrf_id, "removing dest from table"); + rnode_debug (rn, zvrf_id (zvrf), "removing dest from table"); dest->rnode = NULL; XFREE (MTYPE_RIB_DEST, dest); @@ -1385,7 +1383,7 @@ rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, { inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); zlog_debug ("%u:%s/%d: Adding route rn %p, rib %p (type %d)", - zvrf->vrf_id, buf, rn->p.prefixlen, rn, new, new->type); + zvrf_id (zvrf), buf, rn->p.prefixlen, rn, new, new->type); } if (!RIB_SYSTEM_ROUTE (new)) @@ -1394,7 +1392,7 @@ rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, { inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); zlog_warn ("%u:%s/%d: Route install failed", - zvrf->vrf_id, buf, rn->p.prefixlen); + zvrf_id (zvrf), buf, rn->p.prefixlen); } } @@ -1414,7 +1412,7 @@ rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn, { inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); zlog_debug ("%u:%s/%d: Deleting route rn %p, rib %p (type %d)", - zvrf->vrf_id, buf, rn->p.prefixlen, rn, old, old->type); + zvrf_id (zvrf), buf, rn->p.prefixlen, rn, old, old->type); } if (!RIB_SYSTEM_ROUTE (old)) @@ -1463,11 +1461,11 @@ rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn, { if (new != old) zlog_debug ("%u:%s/%d: Updating route rn %p, rib %p (type %d) " - "old %p (type %d)", zvrf->vrf_id, buf, rn->p.prefixlen, + "old %p (type %d)", zvrf_id (zvrf), buf, rn->p.prefixlen, rn, new, new->type, old, old->type); else zlog_debug ("%u:%s/%d: Updating route rn %p, rib %p (type %d)", - zvrf->vrf_id, buf, rn->p.prefixlen, rn, new, new->type); + zvrf_id (zvrf), buf, rn->p.prefixlen, rn, new, new->type); } /* Non-system route should be installed. */ if (!RIB_SYSTEM_ROUTE (new)) @@ -1477,7 +1475,7 @@ rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn, installed = 0; inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); zlog_warn ("%u:%s/%d: Route install failed", - zvrf->vrf_id, buf, rn->p.prefixlen); + zvrf_id (zvrf), buf, rn->p.prefixlen); } } @@ -1511,12 +1509,12 @@ rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn, { if (new != old) zlog_debug ("%u:%s/%d: Deleting route rn %p, rib %p (type %d) " - "old %p (type %d) - %s", zvrf->vrf_id, buf, rn->p.prefixlen, + "old %p (type %d) - %s", zvrf_id (zvrf), buf, rn->p.prefixlen, rn, new, new->type, old, old->type, nh_active ? "install failed" : "nexthop inactive"); else zlog_debug ("%u:%s/%d: Deleting route rn %p, rib %p (type %d) - %s", - zvrf->vrf_id, buf, rn->p.prefixlen, rn, new, new->type, + zvrf_id (zvrf), buf, rn->p.prefixlen, rn, new, new->type, nh_active ? "install failed" : "nexthop inactive"); } @@ -1626,7 +1624,7 @@ rib_process (struct route_node *rn) if (dest) { zvrf = rib_dest_vrf (dest); - vrf_id = zvrf->vrf_id; + vrf_id = zvrf_id (zvrf); } if (IS_ZEBRA_DEBUG_RIB) @@ -2026,7 +2024,7 @@ process_subq (struct list * subq, u_char qindex) { inet_ntop (rnode->p.family, &rnode->p.u.prefix, buf, INET6_ADDRSTRLEN); zlog_debug ("%u:%s/%d: rn %p dequeued from sub-queue %u", - zvrf ? zvrf->vrf_id : 0, buf, rnode->p.prefixlen, rnode, qindex); + zvrf ? zvrf_id (zvrf) : 0, buf, rnode->p.prefixlen, rnode, qindex); } if (rnode->info) @@ -2051,24 +2049,24 @@ process_subq (struct list * subq, u_char qindex) static void meta_queue_process_complete (struct work_queue *dummy) { - vrf_iter_t iter; + struct vrf *vrf; struct zebra_vrf *zvrf; /* Evaluate nexthops for those VRFs which underwent route processing. This * should limit the evaluation to the necessary VRFs in most common * situations. */ - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - if (((zvrf = vrf_iter2info (iter)) != NULL) && - (zvrf->flags & ZEBRA_VRF_RIB_SCHEDULED)) - { - zvrf->flags &= ~ZEBRA_VRF_RIB_SCHEDULED; - zebra_evaluate_rnh(zvrf->vrf_id, AF_INET, 0, RNH_NEXTHOP_TYPE, NULL); - zebra_evaluate_rnh(zvrf->vrf_id, AF_INET, 0, RNH_IMPORT_CHECK_TYPE, NULL); - zebra_evaluate_rnh(zvrf->vrf_id, AF_INET6, 0, RNH_NEXTHOP_TYPE, NULL); - zebra_evaluate_rnh(zvrf->vrf_id, AF_INET6, 0, RNH_IMPORT_CHECK_TYPE, NULL); - } + zvrf = vrf->info; + if (zvrf == NULL || !(zvrf->flags & ZEBRA_VRF_RIB_SCHEDULED)) + continue; + + zvrf->flags &= ~ZEBRA_VRF_RIB_SCHEDULED; + zebra_evaluate_rnh(zvrf_id (zvrf), AF_INET, 0, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf_id (zvrf), AF_INET, 0, RNH_IMPORT_CHECK_TYPE, NULL); + zebra_evaluate_rnh(zvrf_id (zvrf), AF_INET6, 0, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf_id (zvrf), AF_INET6, 0, RNH_IMPORT_CHECK_TYPE, NULL); } /* Schedule LSPs for processing, if needed. */ @@ -2076,7 +2074,7 @@ meta_queue_process_complete (struct work_queue *dummy) if (mpls_should_lsps_be_processed(zvrf)) { if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("%u: Scheduling all LSPs upon RIB completion", zvrf->vrf_id); + zlog_debug ("%u: Scheduling all LSPs upon RIB completion", zvrf_id (zvrf)); zebra_mpls_lsp_schedule (zvrf); mpls_unmark_lsps_for_processing(zvrf); } @@ -2151,7 +2149,7 @@ rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn) rnode_debug (rn, rib->vrf_id, "queued rn %p into sub-queue %u", (void *)rn, qindex); - zvrf = zebra_vrf_lookup (rib->vrf_id); + zvrf = zebra_vrf_lookup_by_id (rib->vrf_id); if (zvrf) zvrf->flags |= ZEBRA_VRF_RIB_SCHEDULED; } @@ -2215,6 +2213,17 @@ meta_queue_new (void) return new; } +void +meta_queue_free (struct meta_queue *mq) +{ + unsigned i; + + for (i = 0; i < MQ_SIZE; i++) + list_delete (mq->subq[i]); + + XFREE (MTYPE_WORK_QUEUE, mq); +} + /* initialise zebra rib work queue */ static void rib_queue_init (struct zebra_t *zebra) @@ -2350,7 +2359,7 @@ rib_addnode (struct route_node *rn, struct rib *rib, int process) * rib_gc_dest() at some point. This allows a rib_dest_t that is no * longer required to be deleted. */ -static void +void rib_unlink (struct route_node *rn, struct rib *rib) { rib_dest_t *dest; @@ -3036,11 +3045,11 @@ rib_weed_table (struct route_table *table) void rib_weed_tables (void) { - vrf_iter_t iter; + struct vrf *vrf; struct zebra_vrf *zvrf; - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - if ((zvrf = vrf_iter2info (iter)) != NULL) + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) + if ((zvrf = vrf->info) != NULL) { rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]); rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); @@ -3077,11 +3086,11 @@ rib_sweep_table (struct route_table *table) void rib_sweep_route (void) { - vrf_iter_t iter; + struct vrf *vrf; struct zebra_vrf *zvrf; - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) - if ((zvrf = vrf_iter2info (iter)) != NULL) + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) + if ((zvrf = vrf->info) != NULL) { rib_sweep_table (zvrf->table[AFI_IP][SAFI_UNICAST]); rib_sweep_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); @@ -3117,12 +3126,12 @@ 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) { - vrf_iter_t iter; + struct vrf *vrf; 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) + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) + if ((zvrf = vrf->info) != 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]); @@ -3152,43 +3161,6 @@ rib_close_table (struct route_table *table) } } -/* Close all RIB tables. */ -void -rib_close (void) -{ - vrf_iter_t iter; - struct zebra_vrf *zvrf; - struct listnode *node; - struct interface *ifp; - u_int32_t table_id; - - 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); - } - - /* If we do multiple tables per vrf, need to move this to loop above */ - zvrf = vrf_info_lookup (VRF_DEFAULT); - - for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++) - { - if (zvrf->other_table[AFI_IP][table_id]) - rib_close_table (zvrf->other_table[AFI_IP][table_id]); - - if (zvrf->other_table[AFI_IP6][table_id]) - rib_close_table (zvrf->other_table[AFI_IP6][table_id]); - } - - zebra_mpls_close_tables(zvrf); - -} - /* Routing information base initialize. */ void rib_init (void) @@ -3206,17 +3178,16 @@ rib_init (void) static inline int vrf_id_get_next (vrf_id_t vrf_id, vrf_id_t *next_id_p) { - 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)); + struct vrf *vrf; - if (zvrf) + vrf = vrf_lookup_by_id (vrf_id); + if (vrf) { - *next_id_p = zvrf->vrf_id; - return 1; + vrf = RB_NEXT (vrf_id_head, &vrfs_by_id, vrf); + if (vrf) { + *next_id_p = vrf->vrf_id; + return 1; + } } return 0; diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 062f9d383..c4c11f98d 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -56,7 +56,7 @@ static void copy_state(struct rnh *rnh, struct rib *rib, ({ \ struct zebra_vrf *zvrf; \ struct route_table *t = NULL; \ - zvrf = zebra_vrf_lookup(v); \ + zvrf = zebra_vrf_lookup_by_id(v); \ if (zvrf) \ t = zvrf->rnh_table[family2afi(f)]; \ t; \ @@ -76,7 +76,7 @@ static inline struct route_table *get_rnh_table(vrf_id_t vrfid, int family, struct zebra_vrf *zvrf; struct route_table *t = NULL; - zvrf = zebra_vrf_lookup(vrfid); + zvrf = zebra_vrf_lookup_by_id(vrfid); if (zvrf) switch (type) { @@ -163,6 +163,16 @@ zebra_lookup_rnh (struct prefix *p, vrf_id_t vrfid, rnh_type_t type) } void +zebra_free_rnh (struct rnh *rnh) +{ + rnh->flags |= ZEBRA_NHT_DELETED; + list_free (rnh->client_list); + list_free (rnh->zebra_static_route_list); + free_state (rnh->vrf_id, rnh->state, rnh->node); + XFREE (MTYPE_RNH, rnh); +} + +void zebra_delete_rnh (struct rnh *rnh, rnh_type_t type) { struct route_node *rn; @@ -177,14 +187,9 @@ zebra_delete_rnh (struct rnh *rnh, rnh_type_t type) rnh->vrf_id, rnh_str(rnh, buf, sizeof (buf)), type); } - rnh->flags |= ZEBRA_NHT_DELETED; - list_free(rnh->client_list); - list_free(rnh->zebra_static_route_list); - free_state(rnh->vrf_id, rnh->state, rn); - XFREE(MTYPE_RNH, rn->info); + zebra_free_rnh (rnh); rn->info = NULL; route_unlock_node (rn); - return; } void diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index 3a57ef1bc..4394fde4f 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -59,6 +59,7 @@ 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, vrf_id_t vrfid, rnh_type_t type); +extern void zebra_free_rnh (struct rnh *rnh); 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, vrf_id_t vrfid); diff --git a/zebra/zebra_rnh_null.c b/zebra/zebra_rnh_null.c index a5e6b3562..286290a52 100644 --- a/zebra/zebra_rnh_null.c +++ b/zebra/zebra_rnh_null.c @@ -27,6 +27,10 @@ int zebra_rnh_ip_default_route = 0; int zebra_rnh_ipv6_default_route = 0; +void +zebra_free_rnh (struct rnh *rnh) +{} + void zebra_evaluate_rnh (vrf_id_t vrfid, int family, int force, rnh_type_t type, struct prefix *p) {} diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 28f09fea0..54aaef674 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -345,7 +345,7 @@ DEFUN (set_src, struct interface *pif = NULL; int family; struct prefix p; - vrf_iter_t iter; + struct vrf *vrf; if (inet_pton(AF_INET, argv[idx_ip]->arg, &src.ipv4) != 1) { @@ -372,14 +372,14 @@ DEFUN (set_src, return CMD_WARNING; } - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { if (family == AF_INET) pif = if_lookup_exact_address_vrf ((void *)&src.ipv4, AF_INET, - vrf_iter2id (iter)); + vrf->vrf_id); else if (family == AF_INET6) pif = if_lookup_exact_address_vrf ((void *)&src.ipv6, AF_INET6, - vrf_iter2id (iter)); + vrf->vrf_id); if (pif != NULL) break; diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c index 7dc6cbaaa..e6ae9c71d 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -130,7 +130,7 @@ static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ro rib->metric = 0; rib->mtu = 0; rib->vrf_id = si->vrf_id; - rib->table = si->vrf_id ? (zebra_vrf_lookup(si->vrf_id))->table_id : zebrad.rtm_table_default; + rib->table = si->vrf_id ? (zebra_vrf_lookup_by_id(si->vrf_id))->table_id : zebrad.rtm_table_default; rib->nexthop_num = 0; rib->tag = si->tag; @@ -423,7 +423,7 @@ static_add_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, si->distance = distance; si->flags = flags; si->tag = tag; - si->vrf_id = zvrf->vrf_id; + si->vrf_id = zvrf_id (zvrf); si->ifindex = ifindex; if (si->ifindex) strcpy(si->ifname, ifname); diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 8db89b1e4..d06b0c03d 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -23,6 +23,7 @@ #include "log.h" #include "linklist.h" +#include "command.h" #include "memory.h" #include "vty.h" @@ -30,13 +31,14 @@ #include "zebra/zserv.h" #include "zebra/rib.h" #include "zebra/zebra_vrf.h" +#include "zebra/zebra_rnh.h" #include "zebra/router-id.h" #include "zebra/zebra_memory.h" #include "zebra/zebra_static.h" +#include "zebra/interface.h" #include "zebra/zebra_mpls.h" extern struct zebra_t zebrad; -struct list *zvrf_list; /* VRF information update. */ static void @@ -46,7 +48,7 @@ zebra_vrf_add_update (struct zebra_vrf *zvrf) struct zserv *client; if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_VRF_ADD %s", zvrf->name); + zlog_debug ("MESSAGE: ZEBRA_VRF_ADD %s", zvrf_name (zvrf)); for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) zsend_vrf_add (client, zvrf); @@ -59,7 +61,7 @@ zebra_vrf_delete_update (struct zebra_vrf *zvrf) struct zserv *client; if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf->name); + zlog_debug ("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf_name (zvrf)); for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) zsend_vrf_delete (client, zvrf); @@ -69,44 +71,28 @@ void zebra_vrf_update_all (struct zserv *client) { struct vrf *vrf; - vrf_iter_t iter; - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - if ((vrf = vrf_iter2vrf (iter)) && vrf->vrf_id) + if (vrf->vrf_id) zsend_vrf_add (client, vrf_info_lookup (vrf->vrf_id)); } } /* Callback upon creating a new VRF. */ static int -zebra_vrf_new (vrf_id_t vrf_id, const char *name, void **info) +zebra_vrf_new (struct vrf *vrf) { - struct zebra_vrf *zvrf = *info; + struct zebra_vrf *zvrf; if (IS_ZEBRA_DEBUG_EVENT) - zlog_info ("ZVRF %s with id %u", name, vrf_id); + zlog_info ("ZVRF %s with id %u", vrf->name, vrf->vrf_id); - if (! zvrf) - { - zvrf = zebra_vrf_list_lookup_by_name (name); - if (!zvrf) - { - zvrf = zebra_vrf_alloc (vrf_id, name); - zvrf->zns = zebra_ns_lookup (NS_DEFAULT); /* Point to the global (single) NS */ - *info = (void *)zvrf; - router_id_init (zvrf); - listnode_add_sort (zvrf_list, zvrf); - } - else - { - *info = (void *)zvrf; - router_id_init (zvrf); - } - } - - if (zvrf->vrf_id == VRF_UNKNOWN) - zvrf->vrf_id = vrf_id; + zvrf = zebra_vrf_alloc (); + zvrf->zns = zebra_ns_lookup (NS_DEFAULT); /* Point to the global (single) NS */ + router_id_init (zvrf); + vrf->info = zvrf; + zvrf->vrf = vrf; return 0; } @@ -123,7 +109,7 @@ zebra_vrf_static_route_interface_fixup (struct interface *ifp) { afi_t afi; safi_t safi; - struct zebra_vrf *zvrf = zebra_vrf_lookup (ifp->vrf_id); + struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id (ifp->vrf_id); struct route_table *stable = NULL; struct route_node *rn = NULL; struct static_route *si = NULL; @@ -157,13 +143,13 @@ zebra_vrf_static_route_interface_fixup (struct interface *ifp) /* Callback upon enabling a VRF. */ static int -zebra_vrf_enable (vrf_id_t vrf_id, const char *name, void **info) +zebra_vrf_enable (struct vrf *vrf) { - struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info); - struct route_table *stable = NULL; - struct route_node *rn = NULL; - struct static_route *si = NULL; - struct interface *ifp = NULL; + struct zebra_vrf *zvrf = vrf->info; + struct route_table *stable; + struct route_node *rn; + struct static_route *si; + struct interface *ifp; afi_t afi; safi_t safi; @@ -172,85 +158,145 @@ zebra_vrf_enable (vrf_id_t vrf_id, const char *name, void **info) zebra_vrf_add_update (zvrf); for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - stable = zvrf->stable[afi][safi]; - if (stable) + for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) + { + stable = zvrf->stable[afi][safi]; + if (! stable) + continue; + + for (rn = route_top (stable); rn; rn = route_next (rn)) + for (si = rn->info; si; si = si->next) { - for (rn = route_top (stable); rn; rn = route_next (rn)) + si->vrf_id = vrf->vrf_id; + if (si->ifindex) { - if (rn->info) - { - si = rn->info; - si->vrf_id = vrf_id; - if (si->ifindex) - { - ifp = if_lookup_by_name_vrf (si->ifname, si->vrf_id); - if (ifp) - si->ifindex = ifp->ifindex; - else - continue; - } - static_install_route (afi, safi, &rn->p, si); - } + ifp = if_lookup_by_name_vrf (si->ifname, si->vrf_id); + if (ifp) + si->ifindex = ifp->ifindex; + else + continue; } + static_install_route (afi, safi, &rn->p, si); } - } - } + } + return 0; } /* Callback upon disabling a VRF. */ static int -zebra_vrf_disable (vrf_id_t vrf_id, const char *name, void **info) +zebra_vrf_disable (struct vrf *vrf) { - struct zebra_vrf *zvrf = (struct zebra_vrf *)(*info); - struct route_table *stable = NULL; - struct route_node *rn = NULL; + struct zebra_vrf *zvrf = vrf->info; + struct route_table *stable; + struct route_node *rn; + struct static_route *si; afi_t afi; safi_t safi; if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug ("VRF %s id %u is now disabled.", - zvrf->name, zvrf->vrf_id); + zvrf_name (zvrf), zvrf_id (zvrf)); for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - stable = zvrf->stable[afi][safi]; - if (stable) - { - for (rn = route_top (stable); rn; rn = route_next (rn)) - { - if (rn->info) - static_uninstall_route(afi, safi, &rn->p, rn->info); - } - } - } - } + for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) + { + stable = zvrf->stable[afi][safi]; + if (! stable) + continue; + + for (rn = route_top (stable); rn; rn = route_next (rn)) + for (si = rn->info; si; si = si->next) + static_uninstall_route(afi, safi, &rn->p, si); + } + return 0; } static int -zebra_vrf_delete (vrf_id_t vrf_id, const char *name, void **info) +zebra_vrf_delete (struct vrf *vrf) { - struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info); + struct zebra_vrf *zvrf = vrf->info; + struct route_table *table; + u_int32_t table_id; + afi_t afi; + safi_t safi; + unsigned i; assert (zvrf); zebra_vrf_delete_update (zvrf); - rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]); - rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); + /* uninstall everything */ + if (! CHECK_FLAG (zvrf->flags, ZEBRA_VRF_RETAIN)) + { + struct listnode *node; + struct interface *ifp; + for (afi = AFI_IP; afi <= AFI_IP6; afi++) + { + for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) + rib_close_table (zvrf->table[afi][safi]); + + if (vrf->vrf_id == VRF_DEFAULT) + for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++) + if (zvrf->other_table[afi][table_id]) + rib_close_table (zvrf->other_table[afi][table_id]); + } + + zebra_mpls_close_tables (zvrf); + + for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp)) + if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp); + } + + /* clean-up work queues */ + for (i = 0; i < MQ_SIZE; i++) + { + struct listnode *lnode, *nnode; + struct route_node *rnode; + rib_dest_t *dest; + + for (ALL_LIST_ELEMENTS (zebrad.mq->subq[i], lnode, nnode, rnode)) + { + dest = rib_dest_from_rnode (rnode); + if (dest && rib_dest_vrf (dest) == zvrf) + { + route_unlock_node (rnode); + list_delete_node (zebrad.mq->subq[i], lnode); + } + } + } + + /* release allocated memory */ + for (afi = AFI_IP; afi <= AFI_IP6; afi++) + { + for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) + { + table = zvrf->table[afi][safi]; + XFREE (MTYPE_RIB_TABLE_INFO, table->info); + route_table_finish (table); + + table = zvrf->stable[afi][safi]; + route_table_finish (table); + } + + for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++) + if (zvrf->other_table[afi][table_id]) + { + table = zvrf->other_table[afi][table_id]; + XFREE (MTYPE_RIB_TABLE_INFO, table->info); + route_table_finish (table); + } + + route_table_finish (zvrf->rnh_table[afi]); + route_table_finish (zvrf->import_check_table[afi]); + } list_delete_all_node (zvrf->rid_all_sorted_list); list_delete_all_node (zvrf->rid_lo_sorted_list); + XFREE (MTYPE_ZEBRA_VRF, zvrf); + vrf->info = NULL; - zvrf->vrf_id = VRF_UNKNOWN; - - *info = NULL; return 0; } @@ -280,6 +326,62 @@ zebra_vrf_table_with_table_id (afi_t afi, safi_t safi, return table; } +static void +zebra_rtable_node_destroy (route_table_delegate_t *delegate, + struct route_table *table, struct route_node *node) +{ + struct rib *rib, *next; + + RNODE_FOREACH_RIB_SAFE (node, rib, next) + rib_unlink (node, rib); + + if (node->info) + XFREE (MTYPE_RIB_DEST, node->info); + + route_node_destroy (delegate, table, node); +} + +static void +zebra_stable_node_destroy (route_table_delegate_t *delegate, + struct route_table *table, struct route_node *node) +{ + struct static_route *si, *next; + + if (node->info) + for (si = node->info; si; si = next) + { + next = si->next; + XFREE (MTYPE_STATIC_ROUTE, si); + } + + route_node_destroy (delegate, table, node); +} + +static void +zebra_rnhtable_node_destroy (route_table_delegate_t *delegate, + struct route_table *table, struct route_node *node) +{ + if (node->info) + zebra_free_rnh (node->info); + + route_node_destroy (delegate, table, node); +} + +route_table_delegate_t zebra_rtable_delegate = { + .create_node = route_node_create, + .destroy_node = zebra_rtable_node_destroy +}; + +route_table_delegate_t zebra_stable_delegate = { + .create_node = route_node_create, + .destroy_node = zebra_stable_node_destroy +}; + +route_table_delegate_t zebra_rnhtable_delegate = { + .create_node = route_node_create, + .destroy_node = zebra_rnhtable_node_destroy +}; + /* * Create a routing table for the specific AFI/SAFI in the given VRF. */ @@ -291,7 +393,7 @@ zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi) assert (!zvrf->table[afi][safi]); - table = route_table_init (); + table = route_table_init_with_delegate (&zebra_rtable_delegate); zvrf->table[afi][safi] = table; info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info)); @@ -303,35 +405,27 @@ zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi) /* Allocate new zebra VRF. */ struct zebra_vrf * -zebra_vrf_alloc (vrf_id_t vrf_id, const char *name) +zebra_vrf_alloc (void) { struct zebra_vrf *zvrf; + afi_t afi; + safi_t safi; 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; - - if (name) + for (afi = AFI_IP; afi <= AFI_IP6; afi++) { - strncpy (zvrf->name, name, strlen(name)); - zvrf->name[strlen(name)] = '\0'; + for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) + { + zebra_vrf_table_create (zvrf, afi, safi); + zvrf->stable[afi][safi] = + route_table_init_with_delegate (&zebra_stable_delegate); + } + + zvrf->rnh_table[afi] = + route_table_init_with_delegate (&zebra_rnhtable_delegate); + zvrf->import_check_table[afi] = + route_table_init_with_delegate (&zebra_rnhtable_delegate); } zebra_mpls_init_tables (zvrf); @@ -341,26 +435,24 @@ zebra_vrf_alloc (vrf_id_t vrf_id, const char *name) /* Lookup VRF by identifier. */ struct zebra_vrf * -zebra_vrf_lookup (vrf_id_t vrf_id) +zebra_vrf_lookup_by_id (vrf_id_t vrf_id) { return vrf_info_lookup (vrf_id); } -/* Lookup the zvrf in the zvrf_list. */ +/* Lookup VRF by name. */ struct zebra_vrf * -zebra_vrf_list_lookup_by_name (const char *name) +zebra_vrf_lookup_by_name (const char *name) { - struct listnode *node; - struct zebra_vrf *zvrf; + struct vrf *vrf; if (!name) name = VRF_DEFAULT_NAME; - for (ALL_LIST_ELEMENTS_RO (zvrf_list, node, zvrf)) - { - if (strcmp(name, zvrf->name) == 0) - return zvrf; - } + vrf = vrf_lookup_by_name (name); + if (vrf) + return ((struct zebra_vrf *) vrf->info); + return NULL; } @@ -428,6 +520,51 @@ zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, vrf_id_t vrf_id) return zvrf->table[afi][SAFI_UNICAST]; } +/* Wrapper hook point for zebra daemon so that ifindex can be set + * DEFUN macro not used as extract.pl HAS to ignore this + * See also interface_cmd in lib/if.c + */ +DEFUN_NOSH (zebra_vrf, + zebra_vrf_cmd, + "vrf NAME", + "Select a VRF to configure\n" + "VRF's name\n") +{ + // VTY_DECLVAR_CONTEXT (vrf, vrfp); + int ret; + + /* Call lib vrf() */ + if ((ret = vrf_cmd.func (self, vty, argc, argv)) != CMD_SUCCESS) + return ret; + + return ret; +} + +static int +vrf_config_write (struct vty *vty) +{ + struct vrf *vrf; + struct zebra_vrf *zvrf; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + { + zvrf = vrf->info; + if (! zvrf || strcmp (zvrf_name (zvrf), VRF_DEFAULT_NAME)) + { + vty_out (vty, "vrf %s%s", zvrf_name (zvrf), VTY_NEWLINE); + vty_out (vty, "!%s", VTY_NEWLINE); + } + } + return 0; +} + +struct cmd_node vrf_node = +{ + VRF_NODE, + "%s(config-vrf)# ", + 1 +}; + /* Zebra VRF initialization. */ void zebra_vrf_init (void) @@ -437,7 +574,10 @@ zebra_vrf_init (void) vrf_add_hook (VRF_DISABLE_HOOK, zebra_vrf_disable); vrf_add_hook (VRF_DELETE_HOOK, zebra_vrf_delete); - zvrf_list = list_new (); - vrf_init (); + + install_node (&vrf_node, vrf_config_write); + install_default (VRF_NODE); + install_element (CONFIG_NODE, &zebra_vrf_cmd); + install_element (CONFIG_NODE, &no_vrf_cmd); } diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index 0baddc1b6..96d631d64 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -28,11 +28,8 @@ /* Routing table instance. */ struct zebra_vrf { - /* Identifier. */ - vrf_id_t vrf_id; - - /* Routing table name. */ - char name[VRF_NAMSIZ]; + /* Back pointer */ + struct vrf *vrf; /* Description. */ char *desc; @@ -43,6 +40,7 @@ struct zebra_vrf /* Flags. */ u_int16_t flags; #define ZEBRA_VRF_RIB_SCHEDULED (1 << 0) +#define ZEBRA_VRF_RETAIN (2 << 0) u_int32_t table_id; @@ -86,7 +84,17 @@ struct zebra_vrf #define MPLS_FLAG_SCHEDULE_LSPS (1 << 0) }; -extern struct list *zvrf_list; +static inline vrf_id_t +zvrf_id (struct zebra_vrf *zvrf) +{ + return zvrf->vrf->vrf_id; +} + +static inline const char * +zvrf_name (struct zebra_vrf *zvrf) +{ + return zvrf->vrf->name; +} struct route_table * zebra_vrf_table_with_table_id (afi_t afi, safi_t safi, @@ -94,9 +102,9 @@ zebra_vrf_table_with_table_id (afi_t afi, safi_t safi, extern void zebra_vrf_static_route_interface_fixup (struct interface *ifp); extern void zebra_vrf_update_all (struct zserv *client); -extern struct zebra_vrf *zebra_vrf_lookup (vrf_id_t vrf_id); -extern struct zebra_vrf *zebra_vrf_list_lookup_by_name (const char *); -extern struct zebra_vrf *zebra_vrf_alloc (vrf_id_t, const char *); +extern struct zebra_vrf *zebra_vrf_lookup_by_id (vrf_id_t vrf_id); +extern struct zebra_vrf *zebra_vrf_lookup_by_name (const char *); +extern struct zebra_vrf *zebra_vrf_alloc (void); 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, struct zebra_vrf *zvrf); extern struct route_table *zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 05356b3d0..16a667469 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -107,7 +107,7 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, tag = atol(tag_str); /* VRF id */ - zvrf = zebra_vrf_list_lookup_by_name (vrf_id_str); + zvrf = zebra_vrf_lookup_by_name (vrf_id_str); if (!zvrf) { @@ -183,7 +183,7 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, ret = inet_aton (gate_str, &gate); if (!ret) { - struct interface *ifp = if_lookup_by_name_vrf (gate_str, zvrf->vrf_id); + struct interface *ifp = if_lookup_by_name_vrf (gate_str, zvrf_id (zvrf)); if (!ifp) { vty_out (vty, "%% Unknown interface: %s%s", gate_str, VTY_NEWLINE); @@ -811,7 +811,7 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast) if (rib->vrf_id != VRF_DEFAULT) { zvrf = vrf_info_lookup(rib->vrf_id); - vty_out (vty, ", vrf %s", zvrf->name); + vty_out (vty, ", vrf %s", zvrf_name (zvrf)); } if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) vty_out (vty, ", best"); @@ -1215,7 +1215,7 @@ do_show_ip_route (struct vty *vty, const char *vrf_name, safi_t safi, json_object *json = NULL; json_object *json_prefix = NULL; - if (!(zvrf = zebra_vrf_list_lookup_by_name (vrf_name))) + if (!(zvrf = zebra_vrf_lookup_by_name (vrf_name))) { if (use_json) vty_out (vty, "{}%s", VTY_NEWLINE); @@ -1224,7 +1224,7 @@ do_show_ip_route (struct vty *vty, const char *vrf_name, safi_t safi, return CMD_SUCCESS; } - if (zvrf->vrf_id == VRF_UNKNOWN) + if (zvrf_id (zvrf) == VRF_UNKNOWN) { if (use_json) vty_out (vty, "{}%s", VTY_NEWLINE); @@ -1233,7 +1233,7 @@ do_show_ip_route (struct vty *vty, const char *vrf_name, safi_t safi, return CMD_SUCCESS; } - table = zebra_vrf_table (AFI_IP, safi, zvrf->vrf_id); + table = zebra_vrf_table (AFI_IP, safi, zvrf_id (zvrf)); if (! table) { if (use_json) @@ -1328,14 +1328,14 @@ DEFUN (show_ip_nht_vrf_all, "IP nexthop tracking table\n" VRF_ALL_CMD_HELP_STR) { + struct vrf *vrf; 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) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) { - vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); - zebra_print_rnh_table(zvrf->vrf_id, AF_INET, vty, RNH_NEXTHOP_TYPE); + vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf_name (zvrf), VTY_NEWLINE); + zebra_print_rnh_table(zvrf_id (zvrf), AF_INET, vty, RNH_NEXTHOP_TYPE); } return CMD_SUCCESS; @@ -1368,14 +1368,14 @@ DEFUN (show_ipv6_nht_vrf_all, "IPv6 nexthop tracking table\n" VRF_ALL_CMD_HELP_STR) { + struct vrf *vrf; 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) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) { - vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); - zebra_print_rnh_table(zvrf->vrf_id, AF_INET6, vty, RNH_NEXTHOP_TYPE); + vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf_name (zvrf), VTY_NEWLINE); + zebra_print_rnh_table(zvrf_id (zvrf), AF_INET6, vty, RNH_NEXTHOP_TYPE); } return CMD_SUCCESS; @@ -1819,7 +1819,7 @@ vty_show_ip_route_summary (struct vty *vty, struct route_table *table) vty_out (vty, "%-20s %-20s %s (vrf %s)%s", "Route Source", "Routes", "FIB", - ((rib_table_info_t *)table->info)->zvrf->name, + zvrf_name (((rib_table_info_t *)table->info)->zvrf), VTY_NEWLINE); for (i = 0; i < ZEBRA_ROUTE_MAX; i++) @@ -1900,7 +1900,7 @@ vty_show_ip_route_summary_prefix (struct vty *vty, struct route_table *table) vty_out (vty, "%-20s %-20s %s (vrf %s)%s", "Route Source", "Prefix Routes", "FIB", - ((rib_table_info_t *)table->info)->zvrf->name, + zvrf_name (((rib_table_info_t *)table->info)->zvrf), VTY_NEWLINE); for (i = 0; i < ZEBRA_ROUTE_MAX; i++) @@ -1992,14 +1992,14 @@ DEFUN (show_ip_route_vrf_all, struct route_table *table; struct route_node *rn; struct rib *rib; + struct vrf *vrf; struct zebra_vrf *zvrf; - vrf_iter_t iter; int first = 1; int vrf_header = 1; - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if ((zvrf = vrf_iter2info (iter)) == NULL || + if ((zvrf = vrf->info) == NULL || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) continue; @@ -2015,7 +2015,7 @@ DEFUN (show_ip_route_vrf_all, if (vrf_header) { - vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); + vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf_name (zvrf), VTY_NEWLINE); vrf_header = 0; } vty_show_ip_route (vty, rn, rib, NULL); @@ -2040,8 +2040,8 @@ DEFUN (show_ip_route_vrf_all_tag, struct route_table *table; struct route_node *rn; struct rib *rib; + struct vrf *vrf; struct zebra_vrf *zvrf; - vrf_iter_t iter; int first = 1; int vrf_header = 1; route_tag_t tag = 0; @@ -2049,9 +2049,9 @@ DEFUN (show_ip_route_vrf_all_tag, if (argv[idx_number]->arg) tag = atol(argv[idx_number]->arg); - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if ((zvrf = vrf_iter2info (iter)) == NULL || + if ((zvrf = vrf->info) == NULL || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) continue; @@ -2070,7 +2070,7 @@ DEFUN (show_ip_route_vrf_all_tag, if (vrf_header) { - vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); + vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf_name (zvrf), VTY_NEWLINE); vrf_header = 0; } vty_show_ip_route (vty, rn, rib, NULL); @@ -2095,8 +2095,8 @@ DEFUN (show_ip_route_vrf_all_prefix_longer, struct route_node *rn; struct rib *rib; struct prefix p; + struct vrf *vrf; struct zebra_vrf *zvrf; - vrf_iter_t iter; int ret; int first = 1; int vrf_header = 1; @@ -2108,9 +2108,9 @@ DEFUN (show_ip_route_vrf_all_prefix_longer, return CMD_WARNING; } - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if ((zvrf = vrf_iter2info (iter)) == NULL || + if ((zvrf = vrf->info) == NULL || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) continue; @@ -2127,7 +2127,7 @@ DEFUN (show_ip_route_vrf_all_prefix_longer, if (vrf_header) { - vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); + vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf_name (zvrf), VTY_NEWLINE); vrf_header = 0; } vty_show_ip_route (vty, rn, rib, NULL); @@ -2150,15 +2150,15 @@ DEFUN (show_ip_route_vrf_all_supernets, struct route_table *table; struct route_node *rn; struct rib *rib; + struct vrf *vrf; struct zebra_vrf *zvrf; - vrf_iter_t iter; u_int32_t addr; int first = 1; int vrf_header = 1; - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if ((zvrf = vrf_iter2info (iter)) == NULL || + if ((zvrf = vrf->info) == NULL || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) continue; @@ -2179,7 +2179,7 @@ DEFUN (show_ip_route_vrf_all_supernets, } if (vrf_header) { - vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); + vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf_name (zvrf), VTY_NEWLINE); vrf_header = 0; } vty_show_ip_route (vty, rn, rib, NULL); @@ -2204,8 +2204,8 @@ DEFUN (show_ip_route_vrf_all_protocol, struct route_table *table; struct route_node *rn; struct rib *rib; + struct vrf *vrf; struct zebra_vrf *zvrf; - vrf_iter_t iter; int first = 1; int vrf_header = 1; @@ -2216,9 +2216,9 @@ DEFUN (show_ip_route_vrf_all_protocol, return CMD_WARNING; } - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if ((zvrf = vrf_iter2info (iter)) == NULL || + if ((zvrf = vrf->info) == NULL || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) continue; @@ -2235,7 +2235,7 @@ DEFUN (show_ip_route_vrf_all_protocol, if (vrf_header) { - vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); + vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf_name (zvrf), VTY_NEWLINE); vrf_header = 0; } vty_show_ip_route (vty, rn, rib, NULL); @@ -2260,8 +2260,8 @@ DEFUN (show_ip_route_vrf_all_addr, struct prefix_ipv4 p; struct route_table *table; struct route_node *rn; + struct vrf *vrf; struct zebra_vrf *zvrf; - vrf_iter_t iter; ret = str2prefix_ipv4 (argv[idx_ipv4]->arg, &p); if (ret <= 0) @@ -2270,9 +2270,9 @@ DEFUN (show_ip_route_vrf_all_addr, return CMD_WARNING; } - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if ((zvrf = vrf_iter2info (iter)) == NULL || + if ((zvrf = vrf->info) == NULL || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) continue; @@ -2302,8 +2302,8 @@ DEFUN (show_ip_route_vrf_all_prefix, struct prefix_ipv4 p; struct route_table *table; struct route_node *rn; + struct vrf *vrf; struct zebra_vrf *zvrf; - vrf_iter_t iter; ret = str2prefix_ipv4 (argv[idx_ipv4_prefixlen]->arg, &p); if (ret <= 0) @@ -2312,9 +2312,9 @@ DEFUN (show_ip_route_vrf_all_prefix, return CMD_WARNING; } - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if ((zvrf = vrf_iter2info (iter)) == NULL || + if ((zvrf = vrf->info) == NULL || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) continue; @@ -2344,11 +2344,11 @@ DEFUN (show_ip_route_vrf_all_summary, VRF_ALL_CMD_HELP_STR "Summary of all routes\n") { + struct vrf *vrf; 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) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) vty_show_ip_route_summary (vty, zvrf->table[AFI_IP][SAFI_UNICAST]); return CMD_SUCCESS; @@ -2364,11 +2364,11 @@ DEFUN (show_ip_route_vrf_all_summary_prefix, "Summary of all routes\n" "Prefix routes\n") { + struct vrf *vrf; 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) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) vty_show_ip_route_summary_prefix (vty, zvrf->table[AFI_IP][SAFI_UNICAST]); return CMD_SUCCESS; @@ -2381,13 +2381,15 @@ static_config_ipv4 (struct vty *vty, safi_t safi, const char *cmd) struct route_node *rn; struct static_route *si; struct route_table *stable; + struct vrf *vrf; struct zebra_vrf *zvrf; char buf[BUFSIZ]; int write =0; - struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (zvrf_list, node, zvrf)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + if (!(zvrf = vrf->info)) + continue; if ((stable = zvrf->stable[AFI_IP][safi]) == NULL) continue; @@ -2426,7 +2428,7 @@ static_config_ipv4 (struct vty *vty, safi_t safi, const char *cmd) vty_out (vty, " %d", si->distance); if (si->vrf_id != VRF_DEFAULT) - vty_out (vty, " vrf %s", zvrf ? zvrf->name : ""); + vty_out (vty, " vrf %s", zvrf ? zvrf_name (zvrf) : ""); /* Label information */ if (si->snh_label.num_labels) @@ -2488,7 +2490,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, ret = inet_pton (AF_INET6, gate_str, &gate_addr); /* VRF id */ - zvrf = zebra_vrf_list_lookup_by_name (vrf_id_str); + zvrf = zebra_vrf_lookup_by_name (vrf_id_str); if (!zvrf) { @@ -2559,7 +2561,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, } type = STATIC_IPV6_GATEWAY_IFINDEX; gate = &gate_addr; - ifp = if_lookup_by_name_vrf (ifname, zvrf->vrf_id); + ifp = if_lookup_by_name_vrf (ifname, zvrf_id (zvrf)); if (!ifp) { vty_out (vty, "%% Malformed Interface name %s%s", ifname, VTY_NEWLINE); @@ -2577,7 +2579,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, else { type = STATIC_IFINDEX; - ifp = if_lookup_by_name_vrf (gate_str, zvrf->vrf_id); + ifp = if_lookup_by_name_vrf (gate_str, zvrf_id (zvrf)); if (!ifp) { vty_out (vty, "%% Malformed Interface name %s%s", gate_str, VTY_NEWLINE); @@ -2894,7 +2896,7 @@ DEFUN (show_ipv6_route, if (vrf) { - if (!(zvrf = zebra_vrf_list_lookup_by_name (vrfname))) + if (!(zvrf = zebra_vrf_lookup_by_name (vrfname))) { if (uj) vty_out (vty, "{}%s", VTY_NEWLINE); @@ -2903,7 +2905,7 @@ DEFUN (show_ipv6_route, return CMD_SUCCESS; } - if (zvrf->vrf_id == VRF_UNKNOWN) + if (zvrf_id (zvrf) == VRF_UNKNOWN) { if (uj) vty_out (vty, "{}%s", VTY_NEWLINE); @@ -2912,7 +2914,7 @@ DEFUN (show_ipv6_route, return CMD_SUCCESS; } else - vrf_id = zvrf->vrf_id; + vrf_id = zvrf_id (zvrf); } table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); @@ -3326,14 +3328,14 @@ DEFUN (show_ipv6_route_vrf_all, struct route_table *table; struct route_node *rn; struct rib *rib; + struct vrf *vrf; struct zebra_vrf *zvrf; - vrf_iter_t iter; int first = 1; int vrf_header = 1; - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if ((zvrf = vrf_iter2info (iter)) == NULL || + if ((zvrf = vrf->info) == NULL || (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) continue; @@ -3349,7 +3351,7 @@ DEFUN (show_ipv6_route_vrf_all, if (vrf_header) { - vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); + vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf_name (zvrf), VTY_NEWLINE); vrf_header = 0; } vty_show_ip_route (vty, rn, rib, NULL); @@ -3374,8 +3376,8 @@ DEFUN (show_ipv6_route_vrf_all_tag, struct route_table *table; struct route_node *rn; struct rib *rib; + struct vrf *vrf; struct zebra_vrf *zvrf; - vrf_iter_t iter; int first = 1; int vrf_header = 1; route_tag_t tag = 0; @@ -3383,9 +3385,9 @@ DEFUN (show_ipv6_route_vrf_all_tag, if (argv[idx_number]->arg) tag = atol(argv[idx_number]->arg); - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if ((zvrf = vrf_iter2info (iter)) == NULL || + if ((zvrf = vrf->info) == NULL || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) continue; @@ -3404,7 +3406,7 @@ DEFUN (show_ipv6_route_vrf_all_tag, if (vrf_header) { - vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); + vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf_name (zvrf), VTY_NEWLINE); vrf_header = 0; } vty_show_ip_route (vty, rn, rib, NULL); @@ -3430,8 +3432,8 @@ DEFUN (show_ipv6_route_vrf_all_prefix_longer, struct route_node *rn; struct rib *rib; struct prefix p; + struct vrf *vrf; struct zebra_vrf *zvrf; - vrf_iter_t iter; int ret; int first = 1; int vrf_header = 1; @@ -3443,9 +3445,9 @@ DEFUN (show_ipv6_route_vrf_all_prefix_longer, return CMD_WARNING; } - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if ((zvrf = vrf_iter2info (iter)) == NULL || + if ((zvrf = vrf->info) == NULL || (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) continue; @@ -3462,7 +3464,7 @@ DEFUN (show_ipv6_route_vrf_all_prefix_longer, if (vrf_header) { - vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); + vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf_name (zvrf), VTY_NEWLINE); vrf_header = 0; } vty_show_ip_route (vty, rn, rib, NULL); @@ -3487,8 +3489,8 @@ DEFUN (show_ipv6_route_vrf_all_protocol, struct route_table *table; struct route_node *rn; struct rib *rib; + struct vrf *vrf; struct zebra_vrf *zvrf; - vrf_iter_t iter; int first = 1; int vrf_header = 1; @@ -3499,9 +3501,9 @@ DEFUN (show_ipv6_route_vrf_all_protocol, return CMD_WARNING; } - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if ((zvrf = vrf_iter2info (iter)) == NULL || + if ((zvrf = vrf->info) == NULL || (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) continue; @@ -3518,7 +3520,7 @@ DEFUN (show_ipv6_route_vrf_all_protocol, if (vrf_header) { - vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf->name, VTY_NEWLINE); + vty_out (vty, "%sVRF %s:%s", VTY_NEWLINE, zvrf_name (zvrf), VTY_NEWLINE); vrf_header = 0; } vty_show_ip_route (vty, rn, rib, NULL); @@ -3543,8 +3545,8 @@ DEFUN (show_ipv6_route_vrf_all_addr, struct prefix_ipv6 p; struct route_table *table; struct route_node *rn; + struct vrf *vrf; struct zebra_vrf *zvrf; - vrf_iter_t iter; ret = str2prefix_ipv6 (argv[idx_ipv6]->arg, &p); if (ret <= 0) @@ -3553,9 +3555,9 @@ DEFUN (show_ipv6_route_vrf_all_addr, return CMD_WARNING; } - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if ((zvrf = vrf_iter2info (iter)) == NULL || + if ((zvrf = vrf->info) == NULL || (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) continue; @@ -3585,8 +3587,8 @@ DEFUN (show_ipv6_route_vrf_all_prefix, struct prefix_ipv6 p; struct route_table *table; struct route_node *rn; + struct vrf *vrf; struct zebra_vrf *zvrf; - vrf_iter_t iter; ret = str2prefix_ipv6 (argv[idx_ipv6_prefixlen]->arg, &p); if (ret <= 0) @@ -3595,9 +3597,9 @@ DEFUN (show_ipv6_route_vrf_all_prefix, return CMD_WARNING; } - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if ((zvrf = vrf_iter2info (iter)) == NULL || + if ((zvrf = vrf->info) == NULL || (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) continue; @@ -3627,11 +3629,11 @@ DEFUN (show_ipv6_route_vrf_all_summary, VRF_ALL_CMD_HELP_STR "Summary of all IPv6 routes\n") { + struct vrf *vrf; 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) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) vty_show_ip_route_summary (vty, zvrf->table[AFI_IP6][SAFI_UNICAST]); return CMD_SUCCESS; @@ -3648,13 +3650,13 @@ DEFUN (show_ipv6_mroute_vrf_all, struct route_table *table; struct route_node *rn; struct rib *rib; + struct vrf *vrf; struct zebra_vrf *zvrf; - vrf_iter_t iter; int first = 1; - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if ((zvrf = vrf_iter2info (iter)) == NULL || + if ((zvrf = vrf->info) == NULL || (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) continue; @@ -3683,11 +3685,11 @@ DEFUN (show_ipv6_route_vrf_all_summary_prefix, "Summary of all IPv6 routes\n" "Prefix routes\n") { + struct vrf *vrf; 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) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) vty_show_ip_route_summary_prefix (vty, zvrf->table[AFI_IP6][SAFI_UNICAST]); return CMD_SUCCESS; @@ -3702,11 +3704,13 @@ static_config_ipv6 (struct vty *vty) int write = 0; char buf[PREFIX_STRLEN]; struct route_table *stable; + struct vrf *vrf; struct zebra_vrf *zvrf; - struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (zvrf_list, node, zvrf)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + if (!(zvrf = vrf->info)) + continue; if ((stable = zvrf->stable[AFI_IP6][SAFI_UNICAST]) == NULL) continue; @@ -3750,7 +3754,7 @@ static_config_ipv6 (struct vty *vty) if (si->vrf_id != VRF_DEFAULT) { - vty_out (vty, " vrf %s", zvrf->name); + vty_out (vty, " vrf %s", zvrf_name (zvrf)); } /* Label information */ @@ -3794,19 +3798,21 @@ DEFUN (show_vrf, SHOW_STR "VRF\n") { + struct vrf *vrf; struct zebra_vrf *zvrf; - struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (zvrf_list, node, zvrf)) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if (!zvrf->vrf_id) + if (!(zvrf = vrf->info)) + continue; + if (!zvrf_id (zvrf)) continue; - vty_out (vty, "vrf %s ", zvrf->name); - if (zvrf->vrf_id == VRF_UNKNOWN) + vty_out (vty, "vrf %s ", zvrf_name (zvrf)); + if (zvrf_id (zvrf) == VRF_UNKNOWN) vty_out (vty, "inactive"); else - vty_out (vty, "id %u table %u", zvrf->vrf_id, zvrf->table_id); + vty_out (vty, "id %u table %u", zvrf_id (zvrf), zvrf->table_id); vty_out (vty, "%s", VTY_NEWLINE); } diff --git a/zebra/zserv.c b/zebra/zserv.c index cb396942a..61ea55f47 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -185,7 +185,7 @@ static void zserv_encode_vrf (struct stream *s, struct zebra_vrf *zvrf) { /* Interface information. */ - stream_put (s, zvrf->name, VRF_NAMSIZ); + stream_put (s, zvrf_name (zvrf), VRF_NAMSIZ); /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); @@ -241,7 +241,7 @@ zsend_vrf_add (struct zserv *client, struct zebra_vrf *zvrf) s = client->obuf; stream_reset (s); - zserv_create_header (s, ZEBRA_VRF_ADD, zvrf->vrf_id); + zserv_create_header (s, ZEBRA_VRF_ADD, zvrf_id (zvrf)); zserv_encode_vrf (s, zvrf); client->vrfadd_cnt++; @@ -257,7 +257,7 @@ zsend_vrf_delete (struct zserv *client, struct zebra_vrf *zvrf) s = client->obuf; stream_reset (s); - zserv_create_header (s, ZEBRA_VRF_DELETE, zvrf->vrf_id); + zserv_create_header (s, ZEBRA_VRF_DELETE, zvrf_id (zvrf)); zserv_encode_vrf (s, zvrf); client->vrfdel_cnt++; @@ -850,7 +850,7 @@ zserv_rnh_register (struct zserv *client, int sock, u_short length, p.family); return -1; } - rnh = zebra_add_rnh(&p, zvrf->vrf_id, type); + rnh = zebra_add_rnh(&p, zvrf_id (zvrf), type); if (type == RNH_NEXTHOP_TYPE) { if (flags && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) @@ -866,9 +866,9 @@ zserv_rnh_register (struct zserv *client, int sock, u_short length, UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH); } - zebra_add_rnh_client(rnh, client, type, zvrf->vrf_id); + zebra_add_rnh_client(rnh, client, type, zvrf_id (zvrf)); /* Anything not AF_INET/INET6 has been filtered out above */ - zebra_evaluate_rnh(zvrf->vrf_id, p.family, 1, type, &p); + zebra_evaluate_rnh(zvrf_id (zvrf), p.family, 1, type, &p); } return 0; } @@ -911,7 +911,7 @@ zserv_rnh_unregister (struct zserv *client, int sock, u_short length, p.family); return -1; } - rnh = zebra_lookup_rnh(&p, zvrf->vrf_id, type); + rnh = zebra_lookup_rnh(&p, zvrf_id (zvrf), type); if (rnh) { client->nh_dereg_time = quagga_monotime(); @@ -939,7 +939,7 @@ zsend_ipv4_nexthop_lookup_mrib (struct zserv *client, struct in_addr addr, struc stream_reset (s); /* Fill in result. */ - zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf->vrf_id); + zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf_id (zvrf)); stream_put_in_addr (s, &addr); if (rib) @@ -1005,18 +1005,16 @@ zsend_router_id_update (struct zserv *client, struct prefix *p, static int zread_interface_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) { + struct vrf *vrf; struct listnode *ifnode, *ifnnode; - vrf_iter_t iter; struct interface *ifp; - struct zebra_vrf *zvrf_iter; /* Interface information is needed. */ - vrf_bitmap_set (client->ifinfo, zvrf->vrf_id); + vrf_bitmap_set (client->ifinfo, zvrf_id (zvrf)); - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - zvrf_iter = vrf_iter2info (iter); - for (ALL_LIST_ELEMENTS (vrf_iflist (zvrf_iter->vrf_id), ifnode, ifnnode, ifp)) + for (ALL_LIST_ELEMENTS (vrf->iflist, ifnode, ifnnode, ifp)) { /* Skip pseudo interface. */ if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) @@ -1036,7 +1034,7 @@ zread_interface_add (struct zserv *client, u_short length, struct zebra_vrf *zvr static int zread_interface_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) { - vrf_bitmap_unset (client->ifinfo, zvrf->vrf_id); + vrf_bitmap_unset (client->ifinfo, zvrf_id (zvrf)); return 0; } @@ -1093,7 +1091,7 @@ zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) stream_get (&p.u.prefix4, s, PSIZE (p.prefixlen)); /* VRF ID */ - rib->vrf_id = zvrf->vrf_id; + rib->vrf_id = zvrf_id (zvrf); /* Nexthop parse. */ if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP)) @@ -1245,7 +1243,7 @@ zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) table_id = zvrf->table_id; - rib_delete (AFI_IP, api.safi, zvrf->vrf_id, api.type, api.instance, + rib_delete (AFI_IP, api.safi, zvrf_id (zvrf), api.type, api.instance, api.flags, &p, nexthop_p, ifindex, table_id); client->v4_route_del_cnt++; return 0; @@ -1259,7 +1257,7 @@ zread_ipv4_nexthop_lookup_mrib (struct zserv *client, u_short length, struct zeb struct rib *rib; addr.s_addr = stream_get_ipv4 (client->ibuf); - rib = rib_match_ipv4_multicast (zvrf->vrf_id, addr, NULL); + rib = rib_match_ipv4_multicast (zvrf_id (zvrf), addr, NULL); return zsend_ipv4_nexthop_lookup_mrib (client, addr, rib, zvrf); } @@ -1303,7 +1301,7 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct stream_get (&p.u.prefix4, s, PSIZE (p.prefixlen)); /* VRF ID */ - rib->vrf_id = zvrf->vrf_id; + rib->vrf_id = zvrf_id (zvrf); /* We need to give nh-addr, nh-ifindex with the same next-hop object * to the rib to ensure that IPv6 multipathing works; need to coalesce @@ -1500,7 +1498,7 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) rib->mtu = 0; /* VRF ID */ - rib->vrf_id = zvrf->vrf_id; + rib->vrf_id = zvrf_id (zvrf); rib->table = zvrf->table_id; ret = rib_add_multipath (AFI_IP6, safi, &p, rib); @@ -1584,10 +1582,10 @@ zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) api.tag = 0; if (IN6_IS_ADDR_UNSPECIFIED (&nexthop)) - rib_delete (AFI_IP6, api.safi, zvrf->vrf_id, api.type, api.instance, + rib_delete (AFI_IP6, api.safi, zvrf_id (zvrf), api.type, api.instance, api.flags, &p, NULL, ifindex, client->rtm_table); else - rib_delete (AFI_IP6, api.safi, zvrf->vrf_id, api.type, api.instance, + rib_delete (AFI_IP6, api.safi, zvrf_id (zvrf), api.type, api.instance, api.flags, &p, pnexthop, ifindex, client->rtm_table); client->v6_route_del_cnt++; @@ -1601,18 +1599,18 @@ zread_router_id_add (struct zserv *client, u_short length, struct zebra_vrf *zvr struct prefix p; /* Router-id information is needed. */ - vrf_bitmap_set (client->ridinfo, zvrf->vrf_id); + vrf_bitmap_set (client->ridinfo, zvrf_id (zvrf)); - router_id_get (&p, zvrf->vrf_id); + router_id_get (&p, zvrf_id (zvrf)); - return zsend_router_id_update (client, &p, zvrf->vrf_id); + return zsend_router_id_update (client, &p, zvrf_id (zvrf)); } /* Unregister zebra server router-id information. */ static int zread_router_id_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) { - vrf_bitmap_unset (client->ridinfo, zvrf->vrf_id); + vrf_bitmap_unset (client->ridinfo, zvrf_id (zvrf)); return 0; } @@ -1650,10 +1648,10 @@ zread_vrf_unregister (struct zserv *client, u_short length, struct zebra_vrf *zv for (afi = AFI_IP; afi < AFI_MAX; afi++) for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - vrf_bitmap_unset (client->redist[afi][i], zvrf->vrf_id); - vrf_bitmap_unset (client->redist_default, zvrf->vrf_id); - vrf_bitmap_unset (client->ifinfo, zvrf->vrf_id); - vrf_bitmap_unset (client->ridinfo, zvrf->vrf_id); + vrf_bitmap_unset (client->redist[afi][i], zvrf_id (zvrf)); + vrf_bitmap_unset (client->redist_default, zvrf_id (zvrf)); + vrf_bitmap_unset (client->ifinfo, zvrf_id (zvrf)); + vrf_bitmap_unset (client->ridinfo, zvrf_id (zvrf)); return 0; } @@ -1724,17 +1722,17 @@ zread_mpls_labels (int command, struct zserv *client, u_short length, static void zebra_client_close_cleanup_rnh (struct zserv *client) { - vrf_iter_t iter; + struct vrf *vrf; struct zebra_vrf *zvrf; - for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - if ((zvrf = vrf_iter2info (iter)) != NULL) + if ((zvrf = vrf->info) != NULL) { - zebra_cleanup_rnh_client(zvrf->vrf_id, AF_INET, client, RNH_NEXTHOP_TYPE); - zebra_cleanup_rnh_client(zvrf->vrf_id, AF_INET6, client, RNH_NEXTHOP_TYPE); - zebra_cleanup_rnh_client(zvrf->vrf_id, AF_INET, client, RNH_IMPORT_CHECK_TYPE); - zebra_cleanup_rnh_client(zvrf->vrf_id, AF_INET6, client, RNH_IMPORT_CHECK_TYPE); + zebra_cleanup_rnh_client(zvrf_id (zvrf), AF_INET, client, RNH_NEXTHOP_TYPE); + zebra_cleanup_rnh_client(zvrf_id (zvrf), AF_INET6, client, RNH_NEXTHOP_TYPE); + zebra_cleanup_rnh_client(zvrf_id (zvrf), AF_INET, client, RNH_IMPORT_CHECK_TYPE); + zebra_cleanup_rnh_client(zvrf_id (zvrf), AF_INET6, client, RNH_IMPORT_CHECK_TYPE); if (client->proto == ZEBRA_ROUTE_LDP) { hash_iterate(zvrf->lsp_table, mpls_ldp_lsp_uninstall_all, @@ -1937,7 +1935,7 @@ zebra_client_read (struct thread *thread) client->last_read_time = quagga_monotime(); client->last_read_cmd = command; - zvrf = zebra_vrf_lookup (vrf_id); + zvrf = zebra_vrf_lookup_by_id (vrf_id); if (!zvrf) { if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) |