#include "filter.h"
#include "plist.h"
#include "log.h"
+#include "lib/bfd.h"
+#include "nexthop.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_interface.h"
#include "ospfd/ospf_lsa.h"
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_route.h"
+#include "ospfd/ospf_lsdb.h"
+#include "ospfd/ospf_neighbor.h"
+#include "ospfd/ospf_nsm.h"
#include "ospfd/ospf_zebra.h"
#ifdef HAVE_SNMP
#include "ospfd/ospf_snmp.h"
#endif /* HAVE_SNMP */
+#include "ospfd/ospf_te.h"
/* Zebra structure to hold current status. */
struct zclient *zclient = NULL;
struct in_addr router_id_zebra;
/* Router-id update message from zebra. */
-int
+static int
ospf_router_id_update_zebra (int command, struct zclient *zclient,
- zebra_size_t length)
+ zebra_size_t length, vrf_id_t vrf_id)
{
struct ospf *ospf;
struct prefix router_id;
zebra_router_id_update_read(zclient->ibuf,&router_id);
+ if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+ {
+ char buf[PREFIX2STR_BUFFER];
+ prefix2str(&router_id, buf, sizeof(buf));
+ zlog_debug("Zebra rcvd: router id update %s", buf);
+ }
+
router_id_zebra = router_id.u.prefix4;
ospf = ospf_lookup ();
+
if (ospf != NULL)
- {
- if (ospf->t_router_id_update == NULL)
- OSPF_TIMER_ON (ospf->t_router_id_update, ospf_router_id_update_timer,
- OSPF_ROUTER_ID_UPDATE_DELAY);
- }
+ ospf_router_id_update (ospf);
+
return 0;
}
/* Inteface addition message from zebra. */
-int
-ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length)
+static int
+ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length,
+ vrf_id_t vrf_id)
{
struct interface *ifp;
- struct ospf *ospf;
- ifp = zebra_interface_add_read (zclient->ibuf);
+ ifp = zebra_interface_add_read (zclient->ibuf, vrf_id);
if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
- zlog_info ("Zebra: interface add %s index %d flags %ld metric %d mtu %d",
- ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
+ zlog_debug ("Zebra: interface add %s[%u] index %d flags %llx metric %d mtu %d",
+ ifp->name, ifp->vrf_id, ifp->ifindex, (unsigned long long)ifp->flags,
+ ifp->metric, ifp->mtu);
assert (ifp->info);
if (!OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type))
{
SET_IF_PARAM (IF_DEF_PARAMS (ifp), type);
- IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_BROADCAST;
-
- if (if_is_broadcast (ifp))
- IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_BROADCAST;
- else if (if_is_pointopoint (ifp))
- IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_POINTOPOINT;
- else if (if_is_loopback (ifp))
- IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_LOOPBACK;
+ IF_DEF_PARAMS (ifp)->type = ospf_default_iftype(ifp);
}
- ospf = ospf_lookup ();
- if (ospf != NULL)
- ospf_if_update (ospf);
+ ospf_if_update (NULL, ifp);
#ifdef HAVE_SNMP
ospf_snmp_if_update (ifp);
return 0;
}
-int
+static int
ospf_interface_delete (int command, struct zclient *zclient,
- zebra_size_t length)
+ zebra_size_t length, vrf_id_t vrf_id)
{
struct interface *ifp;
struct stream *s;
s = zclient->ibuf;
/* zebra_interface_state_read() updates interface structure in iflist */
- ifp = zebra_interface_state_read (s);
+ ifp = zebra_interface_state_read (s, vrf_id);
if (ifp == NULL)
return 0;
ifp->name);
if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
- zlog_info
- ("Zebra: interface delete %s index %d flags %ld metric %d mtu %d",
- ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
+ zlog_debug
+ ("Zebra: interface delete %s[%u] index %d flags %llx metric %d mtu %d",
+ ifp->name, ifp->vrf_id, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
#ifdef HAVE_SNMP
ospf_snmp_if_delete (ifp);
if (rn->info)
ospf_if_free ((struct ospf_interface *) rn->info);
+ ifp->ifindex = IFINDEX_DELETED;
return 0;
}
-struct interface *
-zebra_interface_if_lookup (struct stream *s)
+static struct interface *
+zebra_interface_if_lookup (struct stream *s, vrf_id_t vrf_id)
{
- struct interface *ifp;
- u_char ifname_tmp[INTERFACE_NAMSIZ];
+ char ifname_tmp[INTERFACE_NAMSIZ];
/* Read interface name. */
stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
- /* Lookup this by interface index. */
- ifp = if_lookup_by_name ((char *) ifname_tmp);
-
- /* If such interface does not exist, indicate an error */
- if (!ifp)
- return NULL;
-
- return ifp;
+ /* And look it up. */
+ return if_lookup_by_name_len(ifname_tmp,
+ strnlen(ifname_tmp, INTERFACE_NAMSIZ));
}
-int
+static int
ospf_interface_state_up (int command, struct zclient *zclient,
- zebra_size_t length)
+ zebra_size_t length, vrf_id_t vrf_id)
{
struct interface *ifp;
- struct interface if_tmp;
struct ospf_interface *oi;
struct route_node *rn;
- ifp = zebra_interface_if_lookup (zclient->ibuf);
+ ifp = zebra_interface_if_lookup (zclient->ibuf, vrf_id);
if (ifp == NULL)
return 0;
if (if_is_operative (ifp))
{
/* Temporarily keep ifp values. */
+ struct interface if_tmp;
memcpy (&if_tmp, ifp, sizeof (struct interface));
zebra_interface_if_set_value (zclient->ibuf, ifp);
if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
- zlog_info ("Zebra: Interface[%s] state update.", ifp->name);
+ zlog_debug ("Zebra: Interface[%s] state update.", ifp->name);
if (if_tmp.bandwidth != ifp->bandwidth)
{
if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
- zlog_info ("Zebra: Interface[%s] bandwidth change %d -> %d.",
+ zlog_debug ("Zebra: Interface[%s] bandwidth change %d -> %d.",
ifp->name, if_tmp.bandwidth, ifp->bandwidth);
ospf_if_recalculate_output_cost (ifp);
}
+
+ if (if_tmp.mtu != ifp->mtu)
+ {
+ if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+ zlog_debug ("Zebra: Interface[%s] MTU change %u -> %u.",
+ ifp->name, if_tmp.mtu, ifp->mtu);
+
+ /* Must reset the interface (simulate down/up) when MTU changes. */
+ ospf_if_reset(ifp);
+ }
return 0;
}
zebra_interface_if_set_value (zclient->ibuf, ifp);
if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
- zlog_info ("Zebra: Interface[%s] state change to up.", ifp->name);
+ zlog_debug ("Zebra: Interface[%s] state change to up.", ifp->name);
for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
{
return 0;
}
-int
+static int
ospf_interface_state_down (int command, struct zclient *zclient,
- zebra_size_t length)
+ zebra_size_t length, vrf_id_t vrf_id)
{
struct interface *ifp;
struct ospf_interface *oi;
struct route_node *node;
- ifp = zebra_interface_state_read (zclient->ibuf);
+ ifp = zebra_interface_state_read (zclient->ibuf, vrf_id);
if (ifp == NULL)
return 0;
if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
- zlog_info ("Zebra: Interface[%s] state change to down.", ifp->name);
+ zlog_debug ("Zebra: Interface[%s] state change to down.", ifp->name);
for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node))
{
return 0;
}
-int
+static int
ospf_interface_address_add (int command, struct zclient *zclient,
- zebra_size_t length)
+ zebra_size_t length, vrf_id_t vrf_id)
{
- struct ospf *ospf;
struct connected *c;
- c = zebra_interface_address_read (command, zclient->ibuf);
+ c = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
if (c == NULL)
return 0;
- ospf = ospf_lookup ();
- if (ospf != NULL)
- ospf_if_update (ospf);
+ if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+ {
+ char buf[PREFIX2STR_BUFFER];
+ prefix2str(c->address, buf, sizeof(buf));
+ zlog_debug("Zebra: interface %s address add %s", c->ifp->name, buf);
+ }
+
+ ospf_if_update (NULL, c->ifp);
#ifdef HAVE_SNMP
ospf_snmp_if_update (c->ifp);
return 0;
}
-int
+static int
ospf_interface_address_delete (int command, struct zclient *zclient,
- zebra_size_t length)
+ zebra_size_t length, vrf_id_t vrf_id)
{
- struct ospf *ospf;
struct connected *c;
struct interface *ifp;
struct ospf_interface *oi;
struct route_node *rn;
struct prefix p;
- c = zebra_interface_address_read (command, zclient->ibuf);
+ c = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
if (c == NULL)
return 0;
+ if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+ {
+ char buf[PREFIX2STR_BUFFER];
+ prefix2str(c->address, buf, sizeof(buf));
+ zlog_debug("Zebra: interface %s address delete %s", c->ifp->name, buf);
+ }
+
ifp = c->ifp;
p = *c->address;
p.prefixlen = IPV4_MAX_PREFIXLEN;
rn = route_node_lookup (IF_OIFS (ifp), &p);
if (!rn)
- return 0;
+ {
+ connected_free (c);
+ return 0;
+ }
assert (rn->info);
oi = rn->info;
+ route_unlock_node (rn);
/* Call interface hook functions to clean up */
ospf_if_free (oi);
connected_free (c);
- ospf = ospf_lookup ();
- if (ospf != NULL)
- ospf_if_update (ospf);
+ return 0;
+}
+
+static int
+ospf_interface_link_params (int command, struct zclient *zclient,
+ zebra_size_t length)
+{
+ struct interface *ifp;
+
+ ifp = zebra_interface_link_params_read (zclient->ibuf);
+
+ if (ifp == NULL)
+ return 0;
+
+ /* Update TE TLV */
+ ospf_mpls_te_update_if (ifp);
return 0;
}
+
void
ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or)
{
struct stream *s;
struct ospf_path *path;
struct listnode *node;
+ struct ospf *ospf = ospf_lookup ();
- if (zclient->redist[ZEBRA_ROUTE_OSPF])
+ if ((ospf->instance &&
+ redist_check_instance(&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], ospf->instance))
+ ||
+ vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
{
message = 0;
flags = 0;
if (distance)
SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
+ /* Check if path type is ASE and use only 16bit tags */
+ if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL) ||
+ (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)) &&
+ (or->u.ext.tag > 0) && (or->u.ext.tag < UINT16_MAX))
+ SET_FLAG (message, ZAPI_MESSAGE_TAG);
+
/* Make packet. */
s = zclient->obuf;
stream_reset (s);
- /* Length place holder. */
- stream_putw (s, 0);
-
/* Put command, type, flags, message. */
- stream_putc (s, ZEBRA_IPV4_ROUTE_ADD);
+ zclient_create_header (s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT);
stream_putc (s, ZEBRA_ROUTE_OSPF);
+ stream_putw (s, ospf->instance);
stream_putc (s, flags);
stream_putc (s, message);
+ stream_putw (s, SAFI_UNICAST);
/* Put prefix information. */
psize = PSIZE (p->prefixlen);
stream_putc (s, or->paths->count);
/* Nexthop, ifindex, distance and metric information. */
- for (node = listhead (or->paths); node; nextnode (node))
+ for (ALL_LIST_ELEMENTS_RO (or->paths, node, path))
{
- path = getdata (node);
-
- if (path->nexthop.s_addr != INADDR_ANY)
+#ifdef HAVE_NETLINK
+ if (path->unnumbered ||
+ (path->nexthop.s_addr != INADDR_ANY &&
+ path->ifindex != 0))
+ {
+ stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX);
+ stream_put_in_addr (s, &path->nexthop);
+ stream_putl (s, path->ifindex);
+ }
+ else if (path->nexthop.s_addr != INADDR_ANY)
+ {
+ stream_putc (s, NEXTHOP_TYPE_IPV4);
+ stream_put_in_addr (s, &path->nexthop);
+ }
+ else
+ {
+ stream_putc (s, NEXTHOP_TYPE_IFINDEX);
+ if (path->ifindex)
+ stream_putl (s, path->ifindex);
+ else
+ stream_putl (s, 0);
+ }
+#else /* HAVE_NETLINK */
+ if (path->nexthop.s_addr != INADDR_ANY &&
+ path->ifindex != 0)
{
- stream_putc (s, ZEBRA_NEXTHOP_IPV4);
+ stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX);
+ stream_put_in_addr (s, &path->nexthop);
+ stream_putl (s, path->ifindex);
+ }
+ else if (path->nexthop.s_addr != INADDR_ANY)
+ {
+ stream_putc (s, NEXTHOP_TYPE_IPV4);
stream_put_in_addr (s, &path->nexthop);
}
else
{
- stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
- if (path->oi)
- stream_putl (s, path->oi->ifp->ifindex);
+ stream_putc (s, NEXTHOP_TYPE_IFINDEX);
+ if (path->ifindex)
+ stream_putl (s, path->ifindex);
else
stream_putl (s, 0);
}
+#endif /* HAVE_NETLINK */
if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
{
- zlog_info ("Zebra: Route add %s/%d nexthop %s",
- inet_ntoa (p->prefix),
- p->prefixlen, inet_ntoa (path->nexthop));
+ char buf[2][INET_ADDRSTRLEN];
+ zlog_debug("Zebra: Route add %s/%d nexthop %s, ifindex=%d",
+ inet_ntop(AF_INET, &p->prefix,
+ buf[0], sizeof(buf[0])),
+ p->prefixlen,
+ inet_ntop(AF_INET, &path->nexthop,
+ buf[1], sizeof(buf[1])),
+ path->ifindex);
}
}
stream_putl (s, or->cost);
}
+ if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG))
+ stream_putw (s, (u_short)or->u.ext.tag);
+
stream_putw_at (s, 0, stream_get_endp (s));
- writen (zclient->sock, s->data, stream_get_endp (s));
+ zclient_send_message(zclient);
}
}
void
ospf_zebra_delete (struct prefix_ipv4 *p, struct ospf_route *or)
{
- struct zapi_ipv4 api;
+ u_char message;
+ u_char distance;
+ u_char flags;
+ int psize;
+ struct stream *s;
struct ospf_path *path;
- struct in_addr *nexthop;
struct listnode *node;
+ struct ospf *ospf = ospf_lookup ();
- if (zclient->redist[ZEBRA_ROUTE_OSPF])
+ if ((ospf->instance &&
+ redist_check_instance(&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], ospf->instance))
+ ||
+ vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
{
- api.type = ZEBRA_ROUTE_OSPF;
- api.flags = 0;
- api.message = 0;
- api.ifindex_num = 0;
- api.nexthop_num = 0;
+ message = 0;
+ flags = 0;
+ /* Distance value. */
+ distance = ospf_distance_apply (p, or);
+ /* Make packet. */
+ s = zclient->obuf;
+ stream_reset (s);
- for (node = listhead (or->paths); node; nextnode (node))
- {
- path = getdata (node);
+ /* Put command, type, flags, message. */
+ zclient_create_header (s, ZEBRA_IPV4_ROUTE_DELETE, VRF_DEFAULT);
+ stream_putc (s, ZEBRA_ROUTE_OSPF);
+ stream_putw (s, ospf->instance);
+ stream_putc (s, flags);
+ stream_putc (s, message);
+ stream_putw (s, SAFI_UNICAST);
- if (path->nexthop.s_addr != INADDR_ANY)
- {
- SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
- api.nexthop_num = 1;
- nexthop = &path->nexthop;
- api.nexthop = &nexthop;
- }
- else if (ospf_if_exists(path->oi) && (path->oi->ifp))
- {
- SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
- api.ifindex_num = 1;
- api.ifindex = &path->oi->ifp->ifindex;
- }
- else if ( IS_DEBUG_OSPF(zebra,ZEBRA_REDISTRIBUTE) )
- {
- zlog_info("Zebra: no ifp %s %d",
- inet_ntoa(p->prefix),
- p->prefixlen);
- }
+ /* Put prefix information. */
+ psize = PSIZE (p->prefixlen);
+ stream_putc (s, p->prefixlen);
+ stream_write (s, (u_char *) & p->prefix, psize);
+
+ /* Nexthop count. */
+ stream_putc (s, or->paths->count);
- zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
+ /* Nexthop, ifindex, distance and metric information. */
+ for (ALL_LIST_ELEMENTS_RO (or->paths, node, path))
+ {
+ if (path->nexthop.s_addr != INADDR_ANY &&
+ path->ifindex != 0)
+ {
+ stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX);
+ stream_put_in_addr (s, &path->nexthop);
+ stream_putl (s, path->ifindex);
+ }
+ else if (path->nexthop.s_addr != INADDR_ANY)
+ {
+ stream_putc (s, NEXTHOP_TYPE_IPV4);
+ stream_put_in_addr (s, &path->nexthop);
+ }
+ else
+ {
+ stream_putc (s, NEXTHOP_TYPE_IFINDEX);
+ stream_putl (s, path->ifindex);
+ }
+
+ if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
+ {
+ char buf[2][INET_ADDRSTRLEN];
+ zlog_debug("Zebra: Route delete %s/%d nexthop %s",
+ inet_ntop(AF_INET, &p->prefix,
+ buf[0], sizeof(buf[0])),
+ p->prefixlen,
+ inet_ntop(AF_INET, &path->nexthop,
+ buf[1], sizeof(buf[1])));
+ }
+ }
- if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE) && api.nexthop_num)
- {
- zlog_info ("Zebra: Route delete %s/%d nexthop %s",
- inet_ntoa (p->prefix),
- p->prefixlen, inet_ntoa (**api.nexthop));
- }
- if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE) && api.ifindex_num)
- {
- zlog_info ("Zebra: Route delete %s/%d ifindex %d",
- inet_ntoa (p->prefix),
- p->prefixlen, *api.ifindex);
- }
- }
+ if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
+ stream_putc (s, distance);
+ if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
+ {
+ if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
+ stream_putl (s, or->cost + or->u.ext.type2_cost);
+ else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
+ stream_putl (s, or->u.ext.type2_cost);
+ else
+ stream_putl (s, or->cost);
+ }
+
+ stream_putw_at (s, 0, stream_get_endp (s));
+
+ zclient_send_message(zclient);
}
}
ospf_zebra_add_discard (struct prefix_ipv4 *p)
{
struct zapi_ipv4 api;
+ struct ospf *ospf = ospf_lookup ();
- if (zclient->redist[ZEBRA_ROUTE_OSPF])
+ if ((ospf->instance &&
+ redist_check_instance(&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], ospf->instance))
+ ||
+ vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
{
+ api.vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_OSPF;
+ api.instance = ospf->instance;
api.flags = ZEBRA_FLAG_BLACKHOLE;
api.message = 0;
+ api.safi = SAFI_UNICAST;
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = 0;
api.ifindex_num = 0;
+ api.tag = 0;
zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api);
+
+ if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
+ zlog_debug ("Zebra: Route add discard %s/%d",
+ inet_ntoa (p->prefix), p->prefixlen);
}
}
ospf_zebra_delete_discard (struct prefix_ipv4 *p)
{
struct zapi_ipv4 api;
+ struct ospf *ospf = ospf_lookup ();
- if (zclient->redist[ZEBRA_ROUTE_OSPF])
+ if ((ospf->instance &&
+ redist_check_instance(&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], ospf->instance))
+ ||
+ vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], VRF_DEFAULT))
{
+ api.vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_OSPF;
+ api.instance = ospf->instance;
api.flags = ZEBRA_FLAG_BLACKHOLE;
api.message = 0;
+ api.safi = SAFI_UNICAST;
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = 0;
api.ifindex_num = 0;
+ api.tag = 0;
zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
- zlog_info ("Zebra: Route delete discard %s/%d",
+ zlog_debug ("Zebra: Route delete discard %s/%d",
inet_ntoa (p->prefix), p->prefixlen);
}
}
+struct ospf_external *
+ospf_external_lookup (u_char type, u_short instance)
+{
+ struct list *ext_list;
+ struct listnode *node;
+ struct ospf_external *ext;
+
+ ext_list = om->external[type];
+ if (!ext_list)
+ return(NULL);
+
+ for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext))
+ if (ext->instance == instance)
+ return ext;
+
+ return NULL;
+}
+
+struct ospf_external *
+ospf_external_add (u_char type, u_short instance)
+{
+ struct list *ext_list;
+ struct ospf_external *ext;
+
+ ext = ospf_external_lookup(type, instance);
+ if (ext)
+ return ext;
+
+ if (!om->external[type])
+ om->external[type] = list_new();
+
+ ext_list = om->external[type];
+ ext = (struct ospf_external *)calloc (1, sizeof(struct ospf_external));
+ ext->instance = instance;
+ EXTERNAL_INFO (ext) = route_table_init ();
+
+ listnode_add(ext_list, ext);
+
+ return ext;
+}
+
+void
+ospf_external_del (u_char type, u_short instance)
+{
+ struct ospf_external *ext;
+
+ ext = ospf_external_lookup(type, instance);
+
+ if (ext)
+ {
+ if (EXTERNAL_INFO (ext))
+ route_table_finish(EXTERNAL_INFO (ext));
+
+ listnode_delete(om->external[type], ext);
+ if (!om->external[type]->count)
+ {
+ list_free(om->external[type]);
+ om->external[type] = NULL;
+ }
+ }
+}
+
+struct ospf_redist *
+ospf_redist_lookup (struct ospf *ospf, u_char type, u_short instance)
+{
+ struct list *red_list;
+ struct listnode *node;
+ struct ospf_redist *red;
+
+ red_list = ospf->redist[type];
+ if (!red_list)
+ return(NULL);
+
+ for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
+ if (red->instance == instance)
+ return red;
+
+ return NULL;
+}
+
+struct ospf_redist *
+ospf_redist_add (struct ospf *ospf, u_char type, u_short instance)
+{
+ struct list *red_list;
+ struct ospf_redist *red;
+
+ red = ospf_redist_lookup(ospf, type, instance);
+ if (red)
+ return red;
+
+ if (!ospf->redist[type])
+ ospf->redist[type] = list_new();
+
+ red_list = ospf->redist[type];
+ red = (struct ospf_redist *)calloc (1, sizeof(struct ospf_redist));
+ red->instance = instance;
+ red->dmetric.type = -1;
+ red->dmetric.value = -1;
+
+ listnode_add(red_list, red);
+
+ return red;
+}
+
+void
+ospf_redist_del (struct ospf *ospf, u_char type, u_short instance)
+{
+ struct ospf_redist *red;
+
+ red = ospf_redist_lookup(ospf, type, instance);
+
+ if (red)
+ {
+ listnode_delete(ospf->redist[type], red);
+ if (!ospf->redist[type]->count)
+ {
+ list_free(ospf->redist[type]);
+ ospf->redist[type] = NULL;
+ }
+ }
+}
+
+
int
-ospf_is_type_redistributed (int type)
+ospf_is_type_redistributed (int type, u_short instance)
{
- return (DEFAULT_ROUTE_TYPE (type)) ?
- zclient->default_information : zclient->redist[type];
+ return (DEFAULT_ROUTE_TYPE (type) ?
+ vrf_bitmap_check (zclient->default_information, VRF_DEFAULT) :
+ ((instance && redist_check_instance(&zclient->mi_redist[AFI_IP][type], instance))
+ || (!instance && vrf_bitmap_check (zclient->redist[AFI_IP][type], VRF_DEFAULT))));
}
int
-ospf_redistribute_set (struct ospf *ospf, int type, int mtype, int mvalue)
+ospf_redistribute_set (struct ospf *ospf, int type, u_short instance, int mtype,
+ int mvalue)
{
int force = 0;
+ struct ospf_redist *red;
- if (ospf_is_type_redistributed (type))
+ red = ospf_redist_lookup(ospf, type, instance);
+ if (ospf_is_type_redistributed (type, instance))
{
- if (mtype != ospf->dmetric[type].type)
+ if (mtype != red->dmetric.type)
{
- ospf->dmetric[type].type = mtype;
+ red->dmetric.type = mtype;
force = LSA_REFRESH_FORCE;
}
- if (mvalue != ospf->dmetric[type].value)
+ if (mvalue != red->dmetric.value)
{
- ospf->dmetric[type].value = mvalue;
+ red->dmetric.value = mvalue;
force = LSA_REFRESH_FORCE;
}
- ospf_external_lsa_refresh_type (ospf, type, force);
+ ospf_external_lsa_refresh_type (ospf, type, instance, force);
if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
- zlog_info ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
- LOOKUP (ospf_redistributed_proto, type),
- metric_type (ospf, type), metric_value (ospf, type));
+ zlog_debug ("Redistribute[%s][%d]: Refresh Type[%d], Metric[%d]",
+ ospf_redist_string(type), instance,
+ metric_type (ospf, type, instance),
+ metric_value (ospf, type, instance));
return CMD_SUCCESS;
}
- ospf->dmetric[type].type = mtype;
- ospf->dmetric[type].value = mvalue;
+ red->dmetric.type = mtype;
+ red->dmetric.value = mvalue;
+
+ ospf_external_add(type, instance);
- zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
+ zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type,
+ instance, VRF_DEFAULT);
if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
- zlog_info ("Redistribute[%s]: Start Type[%d], Metric[%d]",
- LOOKUP (ospf_redistributed_proto, type),
- metric_type (ospf, type), metric_value (ospf, type));
+ zlog_debug ("Redistribute[%s][%d]: Start Type[%d], Metric[%d]",
+ ospf_redist_string(type), instance,
+ metric_type (ospf, type, instance), metric_value (ospf, type, instance));
ospf_asbr_status_update (ospf, ++ospf->redistribute);
}
int
-ospf_redistribute_unset (struct ospf *ospf, int type)
+ospf_redistribute_unset (struct ospf *ospf, int type, u_short instance)
{
- if (type == zclient->redist_default)
+ if (type == zclient->redist_default && instance == zclient->instance)
return CMD_SUCCESS;
- if (!ospf_is_type_redistributed (type))
+ if (!ospf_is_type_redistributed (type, instance))
return CMD_SUCCESS;
- zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
+ zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, type,
+ instance, VRF_DEFAULT);
if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
- zlog_info ("Redistribute[%s]: Stop",
- LOOKUP (ospf_redistributed_proto, type));
+ zlog_debug ("Redistribute[%s][%d]: Stop",
+ ospf_redist_string(type), instance);
- ospf->dmetric[type].type = -1;
- ospf->dmetric[type].value = -1;
+ ospf_redist_del (ospf, type, instance);
/* Remove the routes from OSPF table. */
- ospf_redistribute_withdraw (type);
+ ospf_redistribute_withdraw (ospf, type, instance);
+
+ ospf_external_del(type, instance);
ospf_asbr_status_update (ospf, --ospf->redistribute);
ospf_redistribute_default_set (struct ospf *ospf, int originate,
int mtype, int mvalue)
{
- int force = 0;
+ struct ospf_redist *red;
- if (ospf_is_type_redistributed (DEFAULT_ROUTE))
- {
- if (mtype != ospf->dmetric[DEFAULT_ROUTE].type)
- {
- ospf->dmetric[DEFAULT_ROUTE].type = mtype;
- force = 1;
- }
- if (mvalue != ospf->dmetric[DEFAULT_ROUTE].value)
- {
- force = 1;
- ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
- }
+ ospf->default_originate = originate;
+
+ red = ospf_redist_add(ospf, DEFAULT_ROUTE, 0);
+ red->dmetric.type = mtype;
+ red->dmetric.value = mvalue;
+
+ ospf_external_add(DEFAULT_ROUTE, 0);
+ if (ospf_is_type_redistributed (DEFAULT_ROUTE, 0))
+ {
+ /* if ospf->default_originate changes value, is calling
+ ospf_external_lsa_refresh_default sufficient to implement
+ the change? */
ospf_external_lsa_refresh_default (ospf);
if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
- zlog_info ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
- LOOKUP (ospf_redistributed_proto, DEFAULT_ROUTE),
- metric_type (ospf, DEFAULT_ROUTE),
- metric_value (ospf, DEFAULT_ROUTE));
+ zlog_debug ("Redistribute[%s]: Refresh Type[%d], Metric[%d]",
+ ospf_redist_string(DEFAULT_ROUTE),
+ metric_type (ospf, DEFAULT_ROUTE, 0),
+ metric_value (ospf, DEFAULT_ROUTE, 0));
return CMD_SUCCESS;
}
- ospf->default_originate = originate;
- ospf->dmetric[DEFAULT_ROUTE].type = mtype;
- ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
-
- zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient);
+ zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient,
+ VRF_DEFAULT);
if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
- zlog_info ("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]",
- metric_type (ospf, DEFAULT_ROUTE),
- metric_value (ospf, DEFAULT_ROUTE));
+ zlog_debug ("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]",
+ metric_type (ospf, DEFAULT_ROUTE, 0),
+ metric_value (ospf, DEFAULT_ROUTE, 0));
if (ospf->router_id.s_addr == 0)
ospf->external_origin |= (1 << DEFAULT_ROUTE);
else
- thread_add_timer (master, ospf_default_originate_timer,
- &ospf->default_originate, 1);
+ thread_add_timer (master, ospf_default_originate_timer, ospf, 1);
ospf_asbr_status_update (ospf, ++ospf->redistribute);
int
ospf_redistribute_default_unset (struct ospf *ospf)
{
- if (!ospf_is_type_redistributed (DEFAULT_ROUTE))
+ if (!ospf_is_type_redistributed (DEFAULT_ROUTE, 0))
return CMD_SUCCESS;
ospf->default_originate = DEFAULT_ORIGINATE_NONE;
- ospf->dmetric[DEFAULT_ROUTE].type = -1;
- ospf->dmetric[DEFAULT_ROUTE].value = -1;
+ ospf_redist_del(ospf, DEFAULT_ROUTE, 0);
- zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient);
+ zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient,
+ VRF_DEFAULT);
if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
- zlog_info ("Redistribute[DEFAULT]: Stop");
+ zlog_debug ("Redistribute[DEFAULT]: Stop");
+
+ //Pending: how does the external_info cleanup work in this case?
ospf_asbr_status_update (ospf, --ospf->redistribute);
return CMD_SUCCESS;
}
-int
+static int
ospf_external_lsa_originate_check (struct ospf *ospf,
struct external_info *ei)
{
if (is_prefix_default (&ei->p))
if (ospf->default_originate == DEFAULT_ORIGINATE_NONE)
{
- zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-exntenal-LSA "
+ zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-external-LSA "
"for default");
return 0;
}
int
ospf_distribute_check_connected (struct ospf *ospf, struct external_info *ei)
{
- struct route_node *rn;
+ struct listnode *node;
+ struct ospf_interface *oi;
- for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
- if (rn->info != NULL)
- if (prefix_match (&rn->p, (struct prefix *) &ei->p))
- {
- route_unlock_node (rn);
- return 0;
- }
+ for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
+ if (prefix_match (oi->address, (struct prefix *) &ei->p))
+ return 0;
return 1;
}
{
struct route_map_set_values save_values;
struct prefix_ipv4 *p = &ei->p;
+ struct ospf_redist *red;
u_char type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
+ u_short instance = is_prefix_default (&ei->p) ? 0 : ei->instance;
if (changed)
*changed = 0;
if (access_list_apply (DISTRIBUTE_LIST (ospf, type), p) == FILTER_DENY)
{
if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
- zlog_info ("Redistribute[%s]: %s/%d filtered by ditribute-list.",
- LOOKUP (ospf_redistributed_proto, type),
+ zlog_debug ("Redistribute[%s]: %s/%d filtered by ditribute-list.",
+ ospf_redist_string(type),
inet_ntoa (p->prefix), p->prefixlen);
return 0;
}
ospf_reset_route_map_set_values (&ei->route_map_set);
/* apply route-map if needed */
- if (ROUTEMAP_NAME (ospf, type))
+ red = ospf_redist_lookup (ospf, type, instance);
+ if (red && ROUTEMAP_NAME(red))
{
int ret;
- ret = route_map_apply (ROUTEMAP (ospf, type), (struct prefix *) p,
+ ret = route_map_apply (ROUTEMAP (red), (struct prefix *) p,
RMAP_OSPF, ei);
if (ret == RMAP_DENYMATCH)
{
ei->route_map_set = save_values;
if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
- zlog_info ("Redistribute[%s]: %s/%d filtered by route-map.",
- LOOKUP (ospf_redistributed_proto, type),
+ zlog_debug ("Redistribute[%s]: %s/%d filtered by route-map.",
+ ospf_redist_string(type),
inet_ntoa (p->prefix), p->prefixlen);
return 0;
}
/* OSPF route-map set for redistribution */
void
-ospf_routemap_set (struct ospf *ospf, int type, char *name)
+ospf_routemap_set (struct ospf_redist *red, const char *name)
{
- if (ROUTEMAP_NAME (ospf, type))
- free (ROUTEMAP_NAME (ospf, type));
+ if (ROUTEMAP_NAME (red))
+ free (ROUTEMAP_NAME (red));
- ROUTEMAP_NAME (ospf, type) = strdup (name);
- ROUTEMAP (ospf, type) = route_map_lookup_by_name (name);
+ ROUTEMAP_NAME (red) = strdup (name);
+ ROUTEMAP (red) = route_map_lookup_by_name (name);
}
void
-ospf_routemap_unset (struct ospf *ospf, int type)
+ospf_routemap_unset (struct ospf_redist *red)
{
- if (ROUTEMAP_NAME (ospf, type))
- free (ROUTEMAP_NAME (ospf, type));
+ if (ROUTEMAP_NAME (red))
+ free (ROUTEMAP_NAME (red));
- ROUTEMAP_NAME (ospf, type) = NULL;
- ROUTEMAP (ospf, type) = NULL;
+ ROUTEMAP_NAME (red) = NULL;
+ ROUTEMAP (red) = NULL;
}
/* Zebra route add and delete treatment. */
-int
+static int
ospf_zebra_read_ipv4 (int command, struct zclient *zclient,
- zebra_size_t length)
+ zebra_size_t length, vrf_id_t vrf_id)
{
struct stream *s;
struct zapi_ipv4 api;
struct prefix_ipv4 p;
struct external_info *ei;
struct ospf *ospf;
+ int i;
s = zclient->ibuf;
ifindex = 0;
/* Type, flags, message. */
api.type = stream_getc (s);
+ api.instance = stream_getw (s);
api.flags = stream_getc (s);
api.message = stream_getc (s);
/* IPv4 prefix. */
memset (&p, 0, sizeof (struct prefix_ipv4));
p.family = AF_INET;
- p.prefixlen = stream_getc (s);
+ p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc (s));
stream_get (&p.prefix, s, PSIZE (p.prefixlen));
if (IPV4_NET127(ntohl(p.prefix.s_addr)))
api.distance = stream_getc (s);
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
api.metric = stream_getl (s);
+ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG))
+ api.tag = stream_getw (s);
+ else
+ api.tag = 0;
ospf = ospf_lookup ();
if (ospf == NULL)
return 0;
- if (command == ZEBRA_IPV4_ROUTE_ADD)
+ if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD)
{
/* XXX|HACK|TODO|FIXME:
* Maybe we should ignore reject/blackhole routes? Testing shows that
* || CHECK_FLAG (api.flags, ZEBRA_FLAG_REJECT))
* return 0;
*/
-
- ei = ospf_external_info_add (api.type, p, ifindex, nexthop);
+ /* Protocol tag overwrites all other tag value send by zebra */
+ if (ospf->dtag[api.type] > 0)
+ api.tag = ospf->dtag[api.type];
+
+ /*
+ * Given zebra sends update for a prefix via ADD message, it should
+ * be considered as an implicit DEL for that prefix with other source
+ * types.
+ */
+ for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ if (i != api.type)
+ ospf_external_info_delete(i, api.instance, p);
+
+ ei = ospf_external_info_add (api.type, api.instance, p, ifindex,
+ nexthop, api.tag);
+ if (ei == NULL)
+ {
+ /* Nothing has changed, so nothing to do; return */
+ return 0;
+ }
if (ospf->router_id.s_addr == 0)
/* Set flags to generate AS-external-LSA originate event
for each redistributed protocols later. */
current = ospf_external_info_find_lsa (ospf, &ei->p);
if (!current)
ospf_external_lsa_originate (ospf, ei);
- else if (IS_LSA_MAXAGE (current))
- ospf_external_lsa_refresh (ospf, current,
- ei, LSA_REFRESH_FORCE);
else
- zlog_warn ("ospf_zebra_read_ipv4() : %s already exists",
- inet_ntoa (p.prefix));
+ {
+ if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
+ zlog_debug ("ospf_zebra_read_ipv4() : %s refreshing LSA",
+ inet_ntoa (p.prefix));
+ ospf_external_lsa_refresh (ospf, current,
+ ei, LSA_REFRESH_FORCE);
+ }
}
}
}
}
- else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */
+ else /* if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) */
{
- ospf_external_info_delete (api.type, p);
+ ospf_external_info_delete (api.type, api.instance, p);
if (is_prefix_default (&p))
ospf_external_lsa_refresh_default (ospf);
else
- ospf_external_lsa_flush (ospf, api.type, &p, ifindex, nexthop);
+ ospf_external_lsa_flush (ospf, api.type, &p, ifindex /*, nexthop */);
}
return 0;
}
-\f
+
int
-ospf_distribute_list_out_set (struct ospf *ospf, int type, char *name)
+ospf_distribute_list_out_set (struct ospf *ospf, int type, const char *name)
{
/* Lookup access-list for distribute-list. */
DISTRIBUTE_LIST (ospf, type) = access_list_lookup (AFI_IP, name);
/* If access-list have been set, schedule update timer. */
if (DISTRIBUTE_LIST (ospf, type))
- ospf_distribute_list_update (ospf, type);
+ ospf_distribute_list_update (ospf, type, 0);
return CMD_SUCCESS;
}
int
-ospf_distribute_list_out_unset (struct ospf *ospf, int type, char *name)
+ospf_distribute_list_out_unset (struct ospf *ospf, int type, const char *name)
{
/* Schedule update timer. */
if (DISTRIBUTE_LIST (ospf, type))
- ospf_distribute_list_update (ospf, type);
+ ospf_distribute_list_update (ospf, type, 0);
/* Unset distribute-list. */
DISTRIBUTE_LIST (ospf, type) = NULL;
}
/* distribute-list update timer. */
-int
+static int
ospf_distribute_list_update_timer (struct thread *thread)
{
struct route_node *rn;
struct external_info *ei;
struct route_table *rt;
struct ospf_lsa *lsa;
- u_char type;
+ int type, default_refresh = 0;
struct ospf *ospf;
- type = (int) THREAD_ARG (thread);
- rt = EXTERNAL_INFO (type);
-
ospf = ospf_lookup ();
if (ospf == NULL)
return 0;
zlog_info ("Zebra[Redistribute]: distribute-list update timer fired!");
/* foreach all external info. */
- if (rt)
- for (rn = route_top (rt); rn; rn = route_next (rn))
- if ((ei = rn->info) != NULL)
+ for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
+ {
+ struct list *ext_list;
+ struct listnode *node;
+ struct ospf_external *ext;
+
+ ext_list = om->external[type];
+ if (!ext_list)
+ continue;
+
+ for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext))
{
- if (is_prefix_default (&ei->p))
- ospf_external_lsa_refresh_default (ospf);
- else if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p)))
- ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_IF_CHANGED);
- else
- ospf_external_lsa_originate (ospf, ei);
+ rt = ext->external_info;
+ if (!rt)
+ continue;
+ for (rn = route_top (rt); rn; rn = route_next (rn))
+ if ((ei = rn->info) != NULL)
+ {
+ if (is_prefix_default (&ei->p))
+ default_refresh = 1;
+ else if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p)))
+ ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_IF_CHANGED);
+ else
+ ospf_external_lsa_originate (ospf, ei);
+ }
}
+ }
+ if (default_refresh)
+ ospf_external_lsa_refresh_default (ospf);
return 0;
}
-#define OSPF_DISTRIBUTE_UPDATE_DELAY 5
-
/* Update distribute-list and set timer to apply access-list. */
void
-ospf_distribute_list_update (struct ospf *ospf, int type)
+ospf_distribute_list_update (struct ospf *ospf, uintptr_t type,
+ u_short instance)
{
struct route_table *rt;
+ struct ospf_external *ext;
/* External info does not exist. */
- if (!(rt = EXTERNAL_INFO (type)))
+ ext = ospf_external_lookup(type, instance);
+ if (!ext || !(rt = EXTERNAL_INFO (ext)))
return;
- /* If exists previously invoked thread, then cancel it. */
+ /* If exists previously invoked thread, then let it continue. */
if (ospf->t_distribute_update)
- OSPF_TIMER_OFF (ospf->t_distribute_update);
+ return;
/* Set timer. */
ospf->t_distribute_update =
- thread_add_timer (master, ospf_distribute_list_update_timer,
- (void *) type, OSPF_DISTRIBUTE_UPDATE_DELAY);
+ thread_add_timer_msec (master, ospf_distribute_list_update_timer,
+ (void *) type, ospf->min_ls_interval);
}
/* If access-list is updated, apply some check. */
-void
+static void
ospf_filter_update (struct access_list *access)
{
struct ospf *ospf;
struct ospf_area *area;
struct listnode *node;
- /* If OSPF instatnce does not exist, return right now. */
+ /* If OSPF instance does not exist, return right now. */
ospf = ospf_lookup ();
if (ospf == NULL)
return;
/* Update distribute-list, and apply filter. */
- for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
+ for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
{
- if (ROUTEMAP (ospf, type) != NULL)
- {
- /* if route-map is not NULL it may be using this access list */
- ospf_distribute_list_update (ospf, type);
- continue;
- }
+ struct list *red_list;
+ struct listnode *node;
+ struct ospf_redist *red;
+
+ red_list = ospf->redist[type];
+ if (red_list)
+ for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
+ {
+ if (ROUTEMAP (red))
+ {
+ /* if route-map is not NULL it may be using this access list */
+ ospf_distribute_list_update (ospf, type, red->instance);
+ }
+ }
+ /* There is place for route-map for default-information (ZEBRA_ROUTE_MAX),
+ * but no distribute list. */
+ if (type == ZEBRA_ROUTE_MAX)
+ break;
if (DISTRIBUTE_NAME (ospf, type))
{
/* Schedule distribute-list update timer. */
if (DISTRIBUTE_LIST (ospf, type) == NULL ||
strcmp (DISTRIBUTE_NAME (ospf, type), access->name) == 0)
- ospf_distribute_list_update (ospf, type);
+ ospf_distribute_list_update (ospf, type, 0);
}
}
/* Update Area access-list. */
- for (node = listhead (ospf->areas); node; nextnode (node))
- if ((area = getdata (node)) != NULL)
- {
- if (EXPORT_NAME (area))
- {
- EXPORT_LIST (area) = NULL;
- abr_inv++;
- }
+ for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
+ {
+ if (EXPORT_NAME (area))
+ {
+ EXPORT_LIST (area) = NULL;
+ abr_inv++;
+ }
- if (IMPORT_NAME (area))
- {
- IMPORT_LIST (area) = NULL;
- abr_inv++;
- }
- }
+ if (IMPORT_NAME (area))
+ {
+ IMPORT_LIST (area) = NULL;
+ abr_inv++;
+ }
+ }
/* Schedule ABR tasks -- this will be changed -- takada. */
if (IS_OSPF_ABR (ospf) && abr_inv)
/* Update all route-maps which are used as redistribution filters.
* They might use prefix-list.
*/
- for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
+ for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
{
- if (ROUTEMAP (ospf, type) != NULL)
- {
- /* If route-map is not NULL it may be using this prefix list */
- ospf_distribute_list_update (ospf, type);
- continue;
- }
+ struct list *red_list;
+ struct listnode *node;
+ struct ospf_redist *red;
+
+ red_list = ospf->redist[type];
+ if (red_list)
+ for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
+ {
+ if (ROUTEMAP (red))
+ {
+ /* if route-map is not NULL it may be using this prefix list */
+ ospf_distribute_list_update (ospf, type, red->instance);
+ }
+ }
}
/* Update area filter-lists. */
- for (node = listhead (ospf->areas); node; nextnode (node))
- if ((area = getdata (node)) != NULL)
- {
- /* Update filter-list in. */
- if (PREFIX_NAME_IN (area))
- if (strcmp (PREFIX_NAME_IN (area), plist->name) == 0)
- {
- PREFIX_LIST_IN (area) =
- prefix_list_lookup (AFI_IP, PREFIX_NAME_IN (area));
- abr_inv++;
- }
+ for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
+ {
+ /* Update filter-list in. */
+ if (PREFIX_NAME_IN (area))
+ if (strcmp (PREFIX_NAME_IN (area), prefix_list_name (plist)) == 0)
+ {
+ PREFIX_LIST_IN (area) =
+ prefix_list_lookup (AFI_IP, PREFIX_NAME_IN (area));
+ abr_inv++;
+ }
- /* Update filter-list out. */
- if (PREFIX_NAME_OUT (area))
- if (strcmp (PREFIX_NAME_OUT (area), plist->name) == 0)
- {
- PREFIX_LIST_IN (area) =
- prefix_list_lookup (AFI_IP, PREFIX_NAME_OUT (area));
- abr_inv++;
- }
- }
+ /* Update filter-list out. */
+ if (PREFIX_NAME_OUT (area))
+ if (strcmp (PREFIX_NAME_OUT (area), prefix_list_name (plist)) == 0)
+ {
+ PREFIX_LIST_IN (area) =
+ prefix_list_lookup (AFI_IP, PREFIX_NAME_OUT (area));
+ abr_inv++;
+ }
+ }
/* Schedule ABR task. */
if (IS_OSPF_ABR (ospf) && abr_inv)
ospf_schedule_abr_task (ospf);
}
-struct ospf_distance *
-ospf_distance_new ()
+static struct ospf_distance *
+ospf_distance_new (void)
{
- struct ospf_distance *new;
- new = XMALLOC (MTYPE_OSPF_DISTANCE, sizeof (struct ospf_distance));
- memset (new, 0, sizeof (struct ospf_distance));
- return new;
+ return XCALLOC (MTYPE_OSPF_DISTANCE, sizeof (struct ospf_distance));
}
-void
+static void
ospf_distance_free (struct ospf_distance *odistance)
{
XFREE (MTYPE_OSPF_DISTANCE, odistance);
}
int
-ospf_distance_set (struct vty *vty, struct ospf *ospf, char *distance_str,
- char *ip_str, char *access_list_str)
+ospf_distance_set (struct vty *vty, struct ospf *ospf,
+ const char *distance_str,
+ const char *ip_str,
+ const char *access_list_str)
{
int ret;
struct prefix_ipv4 p;
}
int
-ospf_distance_unset (struct vty *vty, struct ospf *ospf, char *distance_str,
- char *ip_str, char *access_list_str)
+ospf_distance_unset (struct vty *vty, struct ospf *ospf,
+ const char *distance_str,
+ const char *ip_str, char
+ const *access_list_str)
{
int ret;
struct prefix_ipv4 p;
- u_char distance;
struct route_node *rn;
struct ospf_distance *odistance;
return CMD_WARNING;
}
- distance = atoi (distance_str);
-
rn = route_node_lookup (ospf->distance_table, (struct prefix *) &p);
if (!rn)
{
return 0;
}
+static void
+ospf_zebra_connected (struct zclient *zclient)
+{
+ /* Send the client registration */
+ bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+
+ zclient_send_reg_requests (zclient, VRF_DEFAULT);
+}
+
void
-ospf_zebra_init ()
+ospf_zebra_init (struct thread_master *master, u_short instance)
{
/* Allocate zebra structure. */
- zclient = zclient_new ();
- zclient_init (zclient, ZEBRA_ROUTE_OSPF);
+ zclient = zclient_new(master);
+ zclient_init (zclient, ZEBRA_ROUTE_OSPF, instance);
+ zclient->zebra_connected = ospf_zebra_connected;
zclient->router_id_update = ospf_router_id_update_zebra;
zclient->interface_add = ospf_interface_add;
zclient->interface_delete = ospf_interface_delete;
zclient->interface_down = ospf_interface_state_down;
zclient->interface_address_add = ospf_interface_address_add;
zclient->interface_address_delete = ospf_interface_address_delete;
- zclient->ipv4_route_add = ospf_zebra_read_ipv4;
- zclient->ipv4_route_delete = ospf_zebra_read_ipv4;
+ zclient->interface_link_params = ospf_interface_link_params;
+
+ zclient->redistribute_route_ipv4_add = ospf_zebra_read_ipv4;
+ zclient->redistribute_route_ipv4_del = ospf_zebra_read_ipv4;
access_list_add_hook (ospf_filter_update);
access_list_delete_hook (ospf_filter_update);