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 493655d7fa..a77e92c17a 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);
+ 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
@@ -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]);
+ 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 6af7aced1f..ade05a2c06 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);
}
}
}
@@ -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 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 c485e61e5c..a95a11b620 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 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 3c429ce1a7..f691cb599a 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 ();
}
diff --git a/lib/if.c b/lib/if.c
index dadf35574e..3ae08abf56 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);
}
@@ -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;
diff --git a/lib/if.h b/lib/if.h
index 7fdd46d3f2..c53b9ff0e7 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);
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..548c03dacd 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,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);
}
diff --git a/lib/vrf.h b/lib/vrf.h
index f1fbad9ff5..eae66599ff 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -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; \
@@ -131,34 +129,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
*/
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/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_vty.c b/ospfd/ospf_vty.c
index 8662eb4259..bc013a83e7 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 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 = '''