diff --git a/README b/README index f1b25d8a92..91a1d8d0fb 100644 --- a/README +++ b/README @@ -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 2f2ea3ae41..60a6475330 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 50ca7eda4c..91eacc9320 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 57168a460b..0a72d09228 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; } @@ -524,17 +530,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); + afi_t afi; - 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); - - 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 @@ -547,29 +550,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]); + afi_t afi; - bgp_table_unlock (bgp->nexthop_cache_table[AFI_IP]); - bgp->nexthop_cache_table[AFI_IP] = 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_IP]); - bgp->connected_table[AFI_IP] = NULL; + bgp_table_unlock (bgp->connected_table[afi]); + bgp->connected_table[afi] = 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]); - - bgp_table_unlock (bgp->nexthop_cache_table[AFI_IP6]); - bgp->nexthop_cache_table[AFI_IP6] = NULL; - - bgp_table_unlock (bgp->connected_table[AFI_IP6]); - bgp->connected_table[AFI_IP6] = 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 9aae3e7b33..1ca0483678 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 9a3b681e72..e53d4493eb 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; + for (ri = rn->info; ri; ri = next) + { + next = ri->next; + if (ri->peer != peer) + continue; - /* 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; - } + 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; + + 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)) { - struct bgp_node *rn; - - 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)) + 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); } } } @@ -6073,7 +6077,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 6bd54aba13..63b18aa2d8 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 913f3d1500..9a103de915 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_vty.c b/bgpd/bgp_vty.c index 4edd09067e..5ba99f1bdf 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -11421,6 +11421,7 @@ community_list_vty (void) /* Community-list. */ install_element (CONFIG_NODE, &ip_community_list_standard_cmd); + install_element (CONFIG_NODE, &ip_community_list_expanded_all_cmd); install_element (CONFIG_NODE, &no_ip_community_list_standard_all_cmd); install_element (CONFIG_NODE, &no_ip_community_list_expanded_all_cmd); install_element (VIEW_NODE, &show_ip_community_list_cmd); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 8ecd025397..3d3bd90f5b 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 50d4126337..6d479e1021 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 dd6a0fdccf..510082fdc2 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 cf352d7204..1bb0837401 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 85053aaa8a..092037bc1d 100644 --- a/lib/command.c +++ b/lib/command.c @@ -2069,21 +2069,6 @@ DEFUN (config_log_syslog, } } -DEFUN_DEPRECATED (config_log_syslog_facility, - config_log_syslog_facility_cmd, - "log syslog facility (kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7)", - "Logging control\n" - "Logging goes to syslog\n" - "(Deprecated) Facility parameter for syslog messages\n" - LOG_FACILITY_DESC) -{ - int facility = facility_match(argv[3]->arg); - - zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); - zlog_default->facility = facility; - return CMD_SUCCESS; -} - DEFUN (no_config_log_syslog, no_config_log_syslog_cmd, "no log syslog [] []", @@ -2483,4 +2468,6 @@ cmd_terminate () XFREE (MTYPE_HOST, host.motdfile); if (host.config) XFREE (MTYPE_HOST, host.config); + + qobj_finish (); } diff --git a/lib/command_match.c b/lib/command_match.c index 13c890fc03..14501c8626 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -27,7 +27,6 @@ #include "command_match.h" #include "memory.h" - #ifdef TRACE_MATCHER #define TM 1 #else @@ -37,8 +36,6 @@ #define trace_matcher(...) \ do { if (TM) fprintf (stderr, __VA_ARGS__); } while (0); -DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command Tokens") - /* matcher helper prototypes */ static int add_nexthops (struct list *, struct graph_node *); @@ -125,12 +122,28 @@ command_match (struct graph *cmdgraph, assert (*el); } +<<<<<<< HEAD if (!*el) { trace_matcher ("No match\n"); } else { trace_matcher ("Matched command\n->string %s\n->desc %s\n", (*el)->string, (*el)->doc); } +||||||| merged common ancestors + if (!*el) { + trace_matcher ("No match"); + } + else { + trace_matcher ("Matched command\n->string %s\n->desc %s\n", (*el)->string, (*el)->doc); + } +======= +#ifdef TRACE_MATCHER + if (!*el) + fprintf (stdout, "No match\n"); + else + fprintf (stdout, "Matched command\n->string %s\n->desc %s\n", (*el)->string, (*el)->doc); +#endif +>>>>>>> osr/master // free the leader token we alloc'd XFREE (MTYPE_TMP, vector_slot (vvline, 0)); @@ -203,26 +216,28 @@ command_match_r (struct graph_node *start, vector vline, unsigned int n) // get the current operating input token char *input_token = vector_slot (vline, n); - trace_matcher ("\"%-20s\" matches \"%-30s\" ? ", input_token, token->text); +#ifdef TRACE_MATCHER + fprintf (stdout, "\"%-20s\" matches \"%-30s\" ? ", input_token, token->text); enum match_type mt = match_token (token, input_token); - trace_matcher ("min: %d - ", minmatch); + fprintf (stdout, "min: %d - ", minmatch); switch (mt) { case trivial_match: - trace_matcher ("trivial_match "); + fprintf (stdout, "trivial_match "); break; case no_match: - trace_matcher ("no_match "); + fprintf (stdout, "no_match "); break; case partly_match: - trace_matcher ("partly_match "); + fprintf (stdout, "partly_match "); break; case exact_match: - trace_matcher ("exact_match "); + fprintf (stdout, "exact_match "); break; } - if (mt >= minmatch) { trace_matcher (" MATCH") }; - trace_matcher ("\n"); + if (mt >= minmatch) fprintf (stdout, " MATCH"); + fprintf (stdout, "\n"); +#endif // if we don't match this node, die if (match_token (token, input_token) < minmatch) @@ -359,8 +374,16 @@ command_complete (struct graph *graph, continue; enum match_type minmatch = min_match_level (token->type); +<<<<<<< HEAD trace_matcher ("\"%s\" matches \"%s\" (%d) ? ", input_token, token->text, token->type); +||||||| merged common ancestors + trace_matcher ("\"%s\" matches \"%s\" (%d) ? ", input_token, token->text, token->type); +======= +#ifdef TRACE_MATCHER + fprintf (stdout, "\"%s\" matches \"%s\" (%d) ? ", input_token, token->text, token->type); +#endif +>>>>>>> osr/master unsigned int last_token = (vector_active (vline) - 1 == idx); enum match_type matchtype = match_token (token, input_token); @@ -368,23 +391,73 @@ command_complete (struct graph *graph, { // occurs when last token is whitespace case trivial_match: +<<<<<<< HEAD trace_matcher ("trivial_match\n"); assert(last_token); listnode_add (next, gn); break; +||||||| merged common ancestors + trace_matcher ("trivial_match\n"); + assert(idx == vector_active (vline) - 1); + listnode_add (next, gn); + break; +======= +#ifdef TRACE_MATCHER + fprintf (stdout, "trivial_match\n"); +#endif +>>>>>>> osr/master case partly_match: +<<<<<<< HEAD trace_matcher ("trivial_match\n"); if (exact_match_exists && !last_token) break; +||||||| merged common ancestors + trace_matcher ("partly_match\n"); + // last token on line is partial and + // not a space + if (idx == vector_active (vline) - 1) + { + listnode_add (next, gn); + break; + } + if (minmatch <= partly_match) + add_nexthops (next, gn); + + break; +======= +#ifdef TRACE_MATCHER + fprintf (stdout, "partly_match\n"); +#endif + if (idx == vector_active (vline) - 1) + { + listnode_add (next, gn); + break; + } + if (minmatch > partly_match) + break; +>>>>>>> osr/master case exact_match: +<<<<<<< HEAD trace_matcher ("exact_match\n"); if (last_token) listnode_add (next, gn); else if (matchtype >= minmatch) add_nexthops (next, gn); +||||||| merged common ancestors + trace_matcher ("exact_match\n"); + add_nexthops (next, gn); + listnode_add (next, gn); +======= +#ifdef TRACE_MATCHER + fprintf (stdout, "exact_match\n"); +#endif + add_nexthops (next, gn); +>>>>>>> osr/master break; default: - trace_matcher ("no_match\n"); +#ifdef TRACE_MATCHER + fprintf (stdout, "no_match\n"); +#endif break; } } diff --git a/lib/if.c b/lib/if.c index c323ae9da2..a1bac2ce81 100644 --- a/lib/if.c +++ b/lib/if.c @@ -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); } @@ -843,72 +838,7 @@ if_cmd_init (void) install_element (INTERFACE_NODE, &no_interface_desc_cmd); } -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; -} - -void -vrf_cmd_init (void) -{ - install_element (CONFIG_NODE, &vrf_cmd); - install_element (CONFIG_NODE, &no_vrf_cmd); - install_default (VRF_NODE); -} - +#if 0 /* For debug purpose. */ DEFUN (show_address, show_address_cmd, @@ -949,24 +879,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)) { @@ -980,6 +908,7 @@ DEFUN (show_address_vrf_all, } return CMD_SUCCESS; } +#endif /* Allocate connected structure. */ struct connected * @@ -1377,14 +1306,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; diff --git a/lib/if.h b/lib/if.h index cf6f3bc006..e8a3b9d7b5 100644 --- a/lib/if.h +++ b/lib/if.h @@ -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); @@ -451,8 +453,6 @@ extern void if_dump_all (void); extern const char *if_flag_dump(unsigned long); extern const char *if_link_type_str (enum zebra_link_type); -extern void vrf_cmd_init (void); - /* Please use ifindex2ifname instead of if_indextoname where possible; ifindex2ifname uses internal interface info, whereas if_indextoname must make a system call. */ diff --git a/lib/ns.c b/lib/ns.c index d8db1e45a1..1673ac0a66 100644 --- a/lib/ns.c +++ b/lib/ns.c @@ -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. */ diff --git a/lib/ns.h b/lib/ns.h index 3fac739861..2a7be1ef8a 100644 --- a/lib/ns.h +++ b/lib/ns.h @@ -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 @@ -59,71 +77,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 (); - * 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 */ diff --git a/lib/qobj.c b/lib/qobj.c index 65b537f961..f64972e32a 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 c480cee0d7..be3ac0e4bf 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 d67b510b66..02f0189345 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 d0e084ead2..5133ef6974 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 e6cdcfef1e..78bf5da748 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 diff --git a/lib/vrf.c b/lib/vrf.c index 63adea4aec..0d0b1cc27d 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -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; - - if (name) - for (ALL_LIST_ELEMENTS_RO (vrf_list, node, vrfp)) - { - if (strcmp(name, vrfp->name) == 0) - return vrfp; - } - return NULL; + struct vrf vrf; + strlcpy (vrf.name, name, sizeof (vrf.name)); + return (RB_FIND (vrf_name_head, &vrfs_by_name, &vrf)); } -/* Build the table key */ -static void -vrf_build_key (vrf_id_t vrf_id, struct prefix *p) +static __inline int +vrf_id_compare (struct vrf *a, struct vrf *b) { - p->family = AF_INET; - p->prefixlen = IPV4_MAX_BITLEN; - p->u.prefix4.s_addr = vrf_id; + return (a->vrf_id - b->vrf_id); +} + +static int +vrf_name_compare (struct vrf *a, struct vrf *b) +{ + 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,73 @@ 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; +} + + +struct cmd_node vrf_node = +{ + VRF_NODE, + "%s(config-vrf)# ", + 1 +}; + /* * Debug CLI for vrf's */ @@ -792,3 +590,12 @@ vrf_install_commands (void) install_element (CONFIG_NODE, &no_vrf_debug_cmd); install_element (ENABLE_NODE, &no_vrf_debug_cmd); } + +void +vrf_cmd_init (int (*writefunc)(struct vty *vty)) +{ + install_element (CONFIG_NODE, &vrf_cmd); + install_element (CONFIG_NODE, &no_vrf_cmd); + install_node (&vrf_node, writefunc); + install_default (VRF_NODE); +} diff --git a/lib/vrf.h b/lib/vrf.h index f1fbad9ff5..96c716a7b8 100644 --- a/lib/vrf.h +++ b/lib/vrf.h @@ -23,8 +23,10 @@ #ifndef _ZEBRA_VRF_H #define _ZEBRA_VRF_H +#include "openbsd-tree.h" #include "linklist.h" #include "qobj.h" +#include "vty.h" /* The default NS ID */ #define NS_DEFAULT 0 @@ -65,18 +67,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 +87,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 +105,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 +117,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; \ @@ -131,34 +130,6 @@ extern vrf_id_t vrf_name_to_id (const char *); (V) = vrf->vrf_id; \ } 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 (); - * 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 */ @@ -201,6 +172,8 @@ extern int vrf_bitmap_check (vrf_bitmap_t, vrf_id_t); extern void vrf_init (void); extern void vrf_terminate (void); +extern void vrf_cmd_init (int (*writefunc)(struct vty *vty)); + /* * VRF utilities */ diff --git a/lib/zclient.c b/lib/zclient.c index 84f7314baa..894e0d19ef 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/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 385232f7f8..f24ee84c8e 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -913,6 +913,7 @@ void ospf6_neighbor_init (void) { install_element (VIEW_NODE, &show_ipv6_ospf6_neighbor_cmd); + install_element (VIEW_NODE, &show_ipv6_ospf6_neighbor_one_cmd); } DEFUN (debug_ospf6_neighbor, diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index a63d73f438..16fb012ea9 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -623,6 +623,7 @@ DEFUN (no_ospf6_distance_ospf6, return CMD_SUCCESS; } +#if 0 DEFUN (ospf6_distance_source, ospf6_distance_source_cmd, "distance (1-255) X:X::X:X/M [WORD]", @@ -653,6 +654,7 @@ DEFUN (no_ospf6_distance_source, return CMD_SUCCESS; } +#endif DEFUN (ospf6_interface_area, ospf6_interface_area_cmd, @@ -834,6 +836,7 @@ DEFUN (no_ospf6_stub_router_admin, return CMD_SUCCESS; } +#if 0 DEFUN (ospf6_stub_router_startup, ospf6_stub_router_startup_cmd, "stub-router on-startup (5-86400)", @@ -879,6 +882,7 @@ DEFUN (no_ospf6_stub_router_shutdown, { return CMD_SUCCESS; } +#endif static void ospf6_show (struct vty *vty, struct ospf6 *o) diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index 6caa38d68b..088123ea24 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 b7ef24409e..72ce5586f6 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_ri.c b/ospfd/ospf_ri.c index 28957e04c6..883ea7cad9 100644 --- a/ospfd/ospf_ri.c +++ b/ospfd/ospf_ri.c @@ -1662,6 +1662,7 @@ ospf_router_info_register_vty (void) install_element (OSPF_NODE, &pce_neighbor_cmd); install_element (OSPF_NODE, &no_pce_neighbor_cmd); install_element (OSPF_NODE, &pce_cap_flag_cmd); + install_element (OSPF_NODE, &no_pce_cap_flag_cmd); return; } diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index f16475f9fa..df989982d1 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -4402,10 +4402,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", @@ -7798,6 +7803,7 @@ DEFUN (ospf_distance_ospf, return CMD_SUCCESS; } +#if 0 DEFUN (ospf_distance_source, ospf_distance_source_cmd, "distance (1-255) A.B.C.D/M", @@ -7879,6 +7885,7 @@ DEFUN (no_ospf_distance_source_access_list, return CMD_SUCCESS; } +#endif DEFUN (ip_ospf_mtu_ignore, ip_ospf_mtu_ignore_addr_cmd, diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index a024e3ae01..231efd0f22 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 f0a1600818..cd29543fa0 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 fe88eba271..fba563a6f8 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 d2d1fb4805..16c4bbe8a3 100644 --- a/render_md.py +++ b/render_md.py @@ -4,11 +4,14 @@ import sys, markdown template = '''