#include "zclient.h"
#include "stream.h"
#include "linklist.h"
+#include "vrf.h"
+#include "isisd/dict.h"
#include "isisd/isis_constants.h"
#include "isisd/isis_common.h"
+#include "isisd/isis_flags.h"
+#include "isisd/isis_misc.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_tlv.h"
+#include "isisd/isisd.h"
#include "isisd/isis_circuit.h"
#include "isisd/isis_csm.h"
+#include "isisd/isis_lsp.h"
#include "isisd/isis_route.h"
#include "isisd/isis_zebra.h"
struct zclient *zclient = NULL;
-extern struct thread_master *master;
-struct in_addr router_id_zebra;
-
/* Router-id update message from zebra. */
-int
+static int
isis_router_id_update_zebra (int command, struct zclient *zclient,
- zebra_size_t length)
+ zebra_size_t length, vrf_id_t vrf_id)
{
+ struct isis_area *area;
+ struct listnode *node;
struct prefix router_id;
- zebra_router_id_update_read (zclient->ibuf,&router_id);
- router_id_zebra = router_id.u.prefix4;
+ zebra_router_id_update_read (zclient->ibuf, &router_id);
+ if (isis->router_id == router_id.u.prefix4.s_addr)
+ return 0;
+
+ isis->router_id = router_id.u.prefix4.s_addr;
+ for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
+ if (listcount (area->area_addrs) > 0)
+ lsp_regenerate_schedule (area, area->is_type, 0);
- /* FIXME: Do we react somehow? */
return 0;
}
-int
-isis_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length)
+static int
+isis_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length,
+ vrf_id_t vrf_id)
{
struct interface *ifp;
- ifp = zebra_interface_add_read (zclient->ibuf);
+ ifp = zebra_interface_add_read (zclient->ibuf, vrf_id);
+ if (isis->debugs & DEBUG_ZEBRA)
+ zlog_debug ("Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
+ ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
- zlog_debug ("Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
- ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
-
- if (if_is_up (ifp))
+ if (if_is_operative (ifp))
isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
return 0;
}
-int
-isis_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length)
+static int
+isis_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length,
+ vrf_id_t vrf_id)
{
struct interface *ifp;
struct stream *s;
s = zclient->ibuf;
- ifp = zebra_interface_state_read (s);
+ ifp = zebra_interface_state_read (s, vrf_id);
if (!ifp)
return 0;
- if (if_is_up (ifp))
+ if (if_is_operative (ifp))
zlog_warn ("Zebra: got delete of %s, but interface is still up",
ifp->name);
- zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
- ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
-
- if_delete (ifp);
+ if (isis->debugs & DEBUG_ZEBRA)
+ zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
+ ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
- return 0;
-}
-
-struct interface *
-zebra_interface_if_lookup (struct stream *s)
-{
- struct interface *ifp;
- u_char ifname_tmp[INTERFACE_NAMSIZ];
+ /* Cannot call if_delete because we should retain the pseudo interface
+ in case there is configuration info attached to it. */
+ if_delete_retain(ifp);
- /* Read interface name. */
- stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
+ ifp->ifindex = IFINDEX_DELETED;
- /* 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;
+ return 0;
}
-int
+static int
isis_zebra_if_state_up (int command, struct zclient *zclient,
- zebra_size_t length)
+ zebra_size_t length, vrf_id_t vrf_id)
{
struct interface *ifp;
- ifp = zebra_interface_if_lookup (zclient->ibuf);
+ ifp = zebra_interface_state_read (zclient->ibuf, vrf_id);
- if (!ifp)
+ if (ifp == NULL)
return 0;
- if (if_is_up (ifp))
- {
- zebra_interface_if_set_value (zclient->ibuf, ifp);
- /* HT: This is wrong actually. We can't assume that circuit exist
- * if we delete circuit during if_state_down event. Needs rethink.
- * TODO */
- isis_circuit_update_params (circuit_scan_by_ifp (ifp), ifp);
- return 0;
- }
-
- zebra_interface_if_set_value (zclient->ibuf, ifp);
isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
return 0;
}
-int
+static int
isis_zebra_if_state_down (int command, struct zclient *zclient,
- zebra_size_t length)
+ zebra_size_t length, vrf_id_t vrf_id)
{
struct interface *ifp;
+ struct isis_circuit *circuit;
- ifp = zebra_interface_if_lookup (zclient->ibuf);
+ ifp = zebra_interface_state_read (zclient->ibuf, vrf_id);
if (ifp == NULL)
return 0;
- if (if_is_up (ifp))
- {
- zebra_interface_if_set_value (zclient->ibuf, ifp);
- isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
- }
+ circuit = isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp),
+ ifp);
+ if (circuit)
+ SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
return 0;
}
-int
+static int
isis_zebra_if_address_add (int command, struct zclient *zclient,
- zebra_size_t length)
+ zebra_size_t length, vrf_id_t vrf_id)
{
struct connected *c;
struct prefix *p;
- char buf[BUFSIZ];
+ char buf[PREFIX2STR_BUFFER];
c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
- zclient->ibuf);
+ zclient->ibuf, vrf_id);
if (c == NULL)
return 0;
p = c->address;
- prefix2str (p, buf, BUFSIZ);
+ prefix2str (p, buf, sizeof (buf));
#ifdef EXTREME_DEBUG
if (p->family == AF_INET)
zlog_debug ("connected IP address %s", buf);
zlog_debug ("connected IPv6 address %s", buf);
#endif /* HAVE_IPV6 */
#endif /* EXTREME_DEBUG */
- isis_circuit_add_addr (circuit_scan_by_ifp (c->ifp), c);
+ if (if_is_operative (c->ifp))
+ isis_circuit_add_addr (circuit_scan_by_ifp (c->ifp), c);
return 0;
}
-int
+static int
isis_zebra_if_address_del (int command, struct zclient *client,
- zebra_size_t length)
+ zebra_size_t length, vrf_id_t vrf_id)
{
struct connected *c;
struct interface *ifp;
#ifdef EXTREME_DEBUG
struct prefix *p;
- u_char buf[BUFSIZ];
+ char buf[PREFIX2STR_BUFFER];
#endif /* EXTREME_DEBUG */
c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE,
- zclient->ibuf);
+ zclient->ibuf, vrf_id);
if (c == NULL)
return 0;
#ifdef EXTREME_DEBUG
p = c->address;
- prefix2str (p, buf, BUFSIZ);
+ prefix2str (p, buf, sizeof (buf));
if (p->family == AF_INET)
zlog_debug ("disconnected IP address %s", buf);
#endif /* HAVE_IPV6 */
#endif /* EXTREME_DEBUG */
- isis_circuit_del_addr (circuit_scan_by_ifp (ifp), c);
+ if (if_is_operative (ifp))
+ isis_circuit_del_addr (circuit_scan_by_ifp (ifp), c);
connected_free (c);
return 0;
}
-void
+static void
isis_zebra_route_add_ipv4 (struct prefix *prefix,
struct isis_route_info *route_info)
{
struct isis_nexthop *nexthop;
struct listnode *node;
- if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
+ if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
return;
- if (zclient->redist[ZEBRA_ROUTE_ISIS])
+ if (vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], VRF_DEFAULT))
{
message = 0;
flags = 0;
stream = zclient->obuf;
stream_reset (stream);
- /* Length place holder. */
- stream_putw (stream, 0);
- /* command */
- stream_putc (stream, ZEBRA_IPV4_ROUTE_ADD);
+ zclient_create_header (stream, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT);
/* type */
stream_putc (stream, ZEBRA_ROUTE_ISIS);
+ /* instance */
+ stream_putw (stream, 0);
/* flags */
stream_putc (stream, flags);
/* message */
stream_putc (stream, message);
+ /* SAFI */
+ stream_putw (stream, SAFI_UNICAST);
/* prefix information */
psize = PSIZE (prefix->prefixlen);
stream_putc (stream, prefix->prefixlen);
stream_putc (stream, listcount (route_info->nexthops));
/* Nexthop, ifindex, distance and metric information */
- for (node = listhead (route_info->nexthops); node; nextnode (node))
+ for (ALL_LIST_ELEMENTS_RO (route_info->nexthops, node, nexthop))
{
- nexthop = getdata (node);
/* FIXME: can it be ? */
if (nexthop->ip.s_addr != INADDR_ANY)
{
stream_putl (stream, route_info->cost);
stream_putw_at (stream, 0, stream_get_endp (stream));
- writen (zclient->sock, stream->data, stream_get_endp (stream));
+ zclient_send_message(zclient);
+ SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
+ UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
}
}
-void
+static void
isis_zebra_route_del_ipv4 (struct prefix *prefix,
struct isis_route_info *route_info)
{
struct zapi_ipv4 api;
struct prefix_ipv4 prefix4;
- if (zclient->redist[ZEBRA_ROUTE_ISIS])
+ if (vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], VRF_DEFAULT))
{
+ api.vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_ISIS;
+ api.instance = 0;
api.flags = 0;
api.message = 0;
+ api.safi = SAFI_UNICAST;
prefix4.family = AF_INET;
prefix4.prefixlen = prefix->prefixlen;
prefix4.prefix = prefix->u.prefix4;
zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, &api);
}
+ UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
return;
}
#ifdef HAVE_IPV6
-void
+static void
isis_zebra_route_add_ipv6 (struct prefix *prefix,
struct isis_route_info *route_info)
{
struct listnode *node;
struct prefix_ipv6 prefix6;
- if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
+ if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
return;
+ api.vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_ISIS;
+ api.instance = 0;
api.flags = 0;
api.message = 0;
+ api.safi = SAFI_UNICAST;
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
/* for each nexthop */
i = 0;
- for (node = listhead (route_info->nexthops6); node; nextnode (node))
+ for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6))
{
- nexthop6 = getdata (node);
-
if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
!IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6))
{
prefix6.prefixlen = prefix->prefixlen;
memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, &prefix6, &api);
- SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
+ SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
+ UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
}
XFREE (MTYPE_ISIS_TMP, nexthop_list);
return;
}
-void
+static void
isis_zebra_route_del_ipv6 (struct prefix *prefix,
struct isis_route_info *route_info)
{
struct listnode *node;
struct prefix_ipv6 prefix6;
- if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
+ if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
return;
+ api.vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_ISIS;
+ api.instance = 0;
api.flags = 0;
api.message = 0;
+ api.safi = SAFI_UNICAST;
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
api.nexthop_num = listcount (route_info->nexthops6);
/* for each nexthop */
i = 0;
- for (node = listhead (route_info->nexthops6); node; nextnode (node))
+ for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6))
{
- nexthop6 = getdata (node);
-
if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
!IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6))
{
prefix6.prefixlen = prefix->prefixlen;
memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6, &api);
- UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
+ UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
}
XFREE (MTYPE_ISIS_TMP, nexthop_list);
if (zclient->sock < 0)
return;
- if (!zclient->redist[ZEBRA_ROUTE_ISIS])
+ if ((prefix->family == AF_INET && !vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], VRF_DEFAULT)) ||
+ (prefix->family == AF_INET6 && !vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_ISIS], VRF_DEFAULT)))
return;
if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE))
return;
}
-int
+static int
isis_zebra_read_ipv4 (int command, struct zclient *zclient,
- zebra_size_t length)
+ zebra_size_t length, vrf_id_t vrf_id)
{
struct stream *stream;
struct zapi_ipv4 api;
struct prefix_ipv4 p;
- unsigned long ifindex;
- struct in_addr nexthop;
stream = zclient->ibuf;
memset (&p, 0, sizeof (struct prefix_ipv4));
- ifindex = 0;
api.type = stream_getc (stream);
+ api.instance = stream_getw (stream);
api.flags = stream_getc (stream);
api.message = stream_getc (stream);
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
{
api.nexthop_num = stream_getc (stream);
- nexthop.s_addr = stream_get_ipv4 (stream);
+ (void)stream_get_ipv4 (stream);
}
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
{
api.ifindex_num = stream_getc (stream);
- ifindex = stream_getl (stream);
+ stream_getl (stream);
}
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc (stream);
else
api.metric = 0;
- if (command == ZEBRA_IPV4_ROUTE_ADD)
+ if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD)
{
- zlog_debug ("IPv4 Route add from Z");
+ if (isis->debugs & DEBUG_ZEBRA)
+ zlog_debug ("IPv4 Route add from Z");
}
return 0;
}
-int
+#ifdef HAVE_IPV6
+static int
isis_zebra_read_ipv6 (int command, struct zclient *zclient,
- zebra_size_t length)
+ zebra_size_t length, vrf_id_t vrf_id)
{
return 0;
}
+#endif
#define ISIS_TYPE_IS_REDISTRIBUTED(T) \
-T == ZEBRA_ROUTE_MAX ? zclient->default_information : zclient->redist[type]
+T == ZEBRA_ROUTE_MAX ? \
+ vrf_bitmap_check (zclient->default_information, VRF_DEFAULT) : \
+ (vrf_bitmap_check (zclient->redist[AFI_IP][type], VRF_DEFAULT) || \
+ vrf_bitmap_check (zclient->redist[AFI_IP6][type], VRF_DEFAULT)
int
isis_distribute_list_update (int routetype)
return 0;
}
-int
+#if 0 /* Not yet. */
+static int
isis_redistribute_default_set (int routetype, int metric_type,
int metric_value)
{
return 0;
}
+#endif /* 0 */
+
+static void
+isis_zebra_connected (struct zclient *zclient)
+{
+ zclient_send_reg_requests (zclient, VRF_DEFAULT);
+}
void
-isis_zebra_init ()
+isis_zebra_init (struct thread_master *master)
{
- zclient = zclient_new ();
- zclient_init (zclient, ZEBRA_ROUTE_ISIS);
+ zclient = zclient_new (master);
+ zclient_init (zclient, ZEBRA_ROUTE_ISIS, 0);
+ zclient->zebra_connected = isis_zebra_connected;
zclient->router_id_update = isis_router_id_update_zebra;
zclient->interface_add = isis_zebra_if_add;
zclient->interface_delete = isis_zebra_if_del;
zclient->interface_address_delete = isis_zebra_if_address_del;
zclient->ipv4_route_add = isis_zebra_read_ipv4;
zclient->ipv4_route_delete = isis_zebra_read_ipv4;
+ zclient->redistribute_route_ipv4_add = isis_zebra_read_ipv4;
+ zclient->redistribute_route_ipv4_del = isis_zebra_read_ipv4;
#ifdef HAVE_IPV6
zclient->ipv6_route_add = isis_zebra_read_ipv6;
zclient->ipv6_route_delete = isis_zebra_read_ipv6;
+ zclient->redistribute_route_ipv6_add = isis_zebra_read_ipv6;
+ zclient->redistribute_route_ipv6_del = isis_zebra_read_ipv6;
#endif /* HAVE_IPV6 */
return;
}
-
-void
-isis_zebra_finish ()
-{
- zclient_stop (zclient);
- zclient_free (zclient);
- zclient = (struct zclient *) NULL;
-
- return;
-}