summaryrefslogtreecommitdiff
path: root/lib/zclient.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/zclient.c')
-rw-r--r--lib/zclient.c306
1 files changed, 183 insertions, 123 deletions
diff --git a/lib/zclient.c b/lib/zclient.c
index 623ca1583f..f1486f4ade 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -164,12 +164,12 @@ zclient_stop (struct zclient *zclient)
void
zclient_reset (struct zclient *zclient)
{
- int afi;
+ afi_t afi;
zclient_stop (zclient);
for (afi = AFI_IP; afi < AFI_MAX; afi++)
- redist_del_instance (&zclient->redist[afi][zclient->redist_default], zclient->instance);
+ redist_del_instance (&zclient->mi_redist[afi][zclient->redist_default], zclient->instance);
zclient_init (zclient, zclient->redist_default, zclient->instance);
}
@@ -322,18 +322,19 @@ zclient_send_message(struct zclient *zclient)
}
void
-zclient_create_header (struct stream *s, uint16_t command)
+zclient_create_header (struct stream *s, uint16_t command, vrf_id_t vrf_id)
{
/* length placeholder, caller can update */
stream_putw (s, ZEBRA_HEADER_SIZE);
stream_putc (s, ZEBRA_HEADER_MARKER);
stream_putc (s, ZSERV_VERSION);
+ stream_putw (s, vrf_id);
stream_putw (s, command);
}
/* Send simple Zebra message. */
static int
-zebra_message_send (struct zclient *zclient, int command)
+zebra_message_send (struct zclient *zclient, int command, vrf_id_t vrf_id)
{
struct stream *s;
@@ -342,7 +343,7 @@ zebra_message_send (struct zclient *zclient, int command)
stream_reset (s);
/* Send very simple command only Zebra message. */
- zclient_create_header (s, command);
+ zclient_create_header (s, command, vrf_id);
return zclient_send_message(zclient);
}
@@ -357,7 +358,8 @@ zebra_hello_send (struct zclient *zclient)
s = zclient->obuf;
stream_reset (s);
- zclient_create_header (s, ZEBRA_HELLO);
+ /* The VRF ID in the HELLO message is always 0. */
+ zclient_create_header (s, ZEBRA_HELLO, VRF_DEFAULT);
stream_putc (s, zclient->redist_default);
stream_putw (s, zclient->instance);
stream_putw_at (s, 0, stream_get_endp (s));
@@ -367,12 +369,71 @@ zebra_hello_send (struct zclient *zclient)
return 0;
}
+/* Send requests to zebra daemon for the information in a VRF. */
+void
+zclient_send_requests (struct zclient *zclient, vrf_id_t vrf_id)
+{
+ int i;
+ afi_t afi;
+
+ /* zclient is disabled. */
+ if (! zclient->enable)
+ return;
+
+ /* If not connected to the zebra yet. */
+ if (zclient->sock < 0)
+ return;
+
+ if (zclient_debug)
+ zlog_debug ("%s: send messages for VRF %u", __func__, vrf_id);
+
+ /* We need router-id information. */
+ zebra_message_send (zclient, ZEBRA_ROUTER_ID_ADD, vrf_id);
+
+ /* We need interface information. */
+ zebra_message_send (zclient, ZEBRA_INTERFACE_ADD, vrf_id);
+
+ /* Set unwanted redistribute route. */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ vrf_bitmap_set (zclient->redist[afi][zclient->redist_default], vrf_id);
+
+ /* Flush all redistribute request. */
+ if (vrf_id == VRF_DEFAULT)
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ if (zclient->mi_redist[afi][i].enabled)
+ {
+ struct listnode *node;
+ u_short *id;
+
+ for (ALL_LIST_ELEMENTS_RO(zclient->mi_redist[afi][i].instances, node, id))
+ if (!(i == zclient->redist_default && *id == zclient->instance))
+ zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, afi, i,
+ *id, VRF_DEFAULT);
+ }
+
+ /* Flush all redistribute request. */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ if (i != zclient->redist_default &&
+ vrf_bitmap_check (zclient->redist[afi][i], vrf_id))
+ zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, afi, i, 0, vrf_id);
+
+ /* If default information is needed. */
+ if (vrf_bitmap_check (zclient->default_information, VRF_DEFAULT))
+ zebra_message_send (zclient, ZEBRA_REDISTRIBUTE_DEFAULT_ADD, vrf_id);
+}
+
/* Make connection to zebra daemon. */
int
zclient_start (struct zclient *zclient)
{
- int i;
- afi_t afi;
+ if (zclient_debug)
+ zlog_info ("zclient_start is called");
+
+ /* zclient is disabled. */
+ if (! zclient->enable)
+ return 0;
/* If already connected to the zebra. */
if (zclient->sock >= 0)
@@ -382,40 +443,33 @@ zclient_start (struct zclient *zclient)
if (zclient->t_connect)
return 0;
- /* Flush all redistribute request. */
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- if (zclient->redist[afi][i].enabled)
- {
- struct listnode *node;
- u_short *id;
-
- for (ALL_LIST_ELEMENTS_RO(zclient->redist[afi][i].instances, node, id))
- if (!(i == zclient->redist_default && *id == zclient->instance))
- zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, afi, i, *id);
- }
+ if (zclient_socket_connect(zclient) < 0)
+ {
+ if (zclient_debug)
+ zlog_debug ("zclient connection fail");
+ zclient->fail++;
+ zclient_event (ZCLIENT_CONNECT, zclient);
+ return -1;
+ }
- /* If default information is needed. */
- if (zclient->default_information)
- zebra_message_send (zclient, ZEBRA_REDISTRIBUTE_DEFAULT_ADD);
+ if (set_nonblocking(zclient->sock) < 0)
+ zlog_warn("%s: set_nonblocking(%d) failed", __func__, zclient->sock);
- return 0;
-}
+ /* Clear fail count. */
+ zclient->fail = 0;
+ if (zclient_debug)
+ zlog_debug ("zclient connect success with socket [%d]", zclient->sock);
-/* This function is a wrapper function for calling zclient_start from
- timer or event thread. */
-static int
-zclient_connect (struct thread *t)
-{
- struct zclient *zclient;
+ /* Create read thread. */
+ zclient_event (ZCLIENT_READ, zclient);
- zclient = THREAD_ARG (t);
- zclient->t_connect = NULL;
+ zebra_hello_send (zclient);
- if (zclient_debug)
- zlog_debug ("zclient_connect is called");
+ /* Inform the successful connection. */
+ if (zclient->zebra_connected)
+ (*zclient->zebra_connected) (zclient);
- return zclient_start (zclient);
+ return 0;
}
/* Initialize zebra client. Argument redist_default is unwanted
@@ -434,7 +488,7 @@ zclient_init (struct zclient *zclient, int redist_default, u_short instance)
/* Clear redistribution flags. */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- memset(&zclient->redist[afi][i], 0, sizeof(struct redist_proto));
+ zclient->redist[afi][i] = vrf_bitmap_init();
/* Set unwanted redistribute route. bgpd does not need BGP route
redistribution. */
@@ -442,47 +496,31 @@ zclient_init (struct zclient *zclient, int redist_default, u_short instance)
zclient->instance = instance;
/* Pending: make afi(s) an arg. */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
- redist_add_instance (&zclient->redist[afi][redist_default], instance);
+ redist_add_instance (&zclient->mi_redist[afi][redist_default], instance);
/* Set default-information redistribute to zero. */
- zclient->default_information = 0;
+ zclient->default_information = vrf_bitmap_init ();;
if (zclient_debug)
zlog_debug ("zclient_start is called");
- /* zclient is disabled. */
- if (! zclient->enable)
- return;
+ zclient_event (ZCLIENT_SCHEDULE, zclient);
+}
- if (zclient_socket_connect(zclient) < 0)
- {
- if (zclient_debug)
- zlog_debug ("zclient connection fail");
- zclient->fail++;
- zclient_event (ZCLIENT_CONNECT, zclient);
- return;
- }
+/* This function is a wrapper function for calling zclient_start from
+ timer or event thread. */
+static int
+zclient_connect (struct thread *t)
+{
+ struct zclient *zclient;
- if (set_nonblocking(zclient->sock) < 0)
- zlog_warn("%s: set_nonblocking(%d) failed", __func__, zclient->sock);
+ zclient = THREAD_ARG (t);
+ zclient->t_connect = NULL;
- /* Clear fail count. */
- zclient->fail = 0;
if (zclient_debug)
- zlog_debug ("zclient connect success with socket [%d]", zclient->sock);
-
- /* Create read thread. */
- zclient_event (ZCLIENT_READ, zclient);
-
- zebra_hello_send (zclient);
-
- /* We need router-id information. */
- zebra_message_send (zclient, ZEBRA_ROUTER_ID_ADD);
-
- /* We need interface information. */
- zebra_message_send (zclient, ZEBRA_INTERFACE_ADD);
+ zlog_debug ("zclient_connect is called");
- zclient_event (ZCLIENT_SCHEDULE, zclient);
+ return zclient_start (zclient);
}
/*
@@ -557,8 +595,8 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p,
/* Reset stream. */
s = zclient->obuf;
stream_reset (s);
-
- zclient_create_header (s, cmd);
+
+ zclient_create_header (s, cmd, api->vrf_id);
/* Put type and nexthop. */
stream_putc (s, api->type);
@@ -640,7 +678,7 @@ zapi_ipv4_route_ipv6_nexthop (u_char cmd, struct zclient *zclient,
s = zclient->obuf;
stream_reset (s);
- zclient_create_header (s, cmd);
+ zclient_create_header (s, cmd, api->vrf_id);
/* Put type and nexthop. */
stream_putc (s, api->type);
@@ -704,7 +742,7 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p,
s = zclient->obuf;
stream_reset (s);
- zclient_create_header (s, cmd);
+ zclient_create_header (s, cmd, api->vrf_id);
/* Put type and nexthop. */
stream_putc (s, api->type);
@@ -765,14 +803,14 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p,
*/
int
zebra_redistribute_send (int command, struct zclient *zclient, afi_t afi, int type,
- u_short instance)
+ u_short instance, vrf_id_t vrf_id)
{
struct stream *s;
s = zclient->obuf;
stream_reset(s);
- zclient_create_header (s, command);
+ zclient_create_header (s, command, vrf_id);
stream_putc (s, afi);
stream_putc (s, type);
stream_putw (s, instance);
@@ -829,7 +867,7 @@ zebra_router_id_update_read (struct stream *s, struct prefix *rid)
*/
struct interface *
-zebra_interface_add_read (struct stream *s)
+zebra_interface_add_read (struct stream *s, vrf_id_t vrf_id)
{
struct interface *ifp;
char ifname_tmp[INTERFACE_NAMSIZ];
@@ -838,7 +876,9 @@ zebra_interface_add_read (struct stream *s)
stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
/* Lookup/create interface by name. */
- ifp = if_get_by_name_len (ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ));
+ ifp = if_get_by_name_len_vrf (ifname_tmp,
+ strnlen (ifname_tmp, INTERFACE_NAMSIZ),
+ vrf_id);
zebra_interface_if_set_value (s, ifp);
@@ -853,7 +893,7 @@ zebra_interface_add_read (struct stream *s)
* is sent at the tail of the message.
*/
struct interface *
-zebra_interface_state_read (struct stream *s)
+zebra_interface_state_read (struct stream *s, vrf_id_t vrf_id)
{
struct interface *ifp;
char ifname_tmp[INTERFACE_NAMSIZ];
@@ -862,8 +902,9 @@ zebra_interface_state_read (struct stream *s)
stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
/* Lookup this by interface index. */
- ifp = if_lookup_by_name_len (ifname_tmp,
- strnlen(ifname_tmp, INTERFACE_NAMSIZ));
+ ifp = if_lookup_by_name_len_vrf (ifname_tmp,
+ strnlen (ifname_tmp, INTERFACE_NAMSIZ),
+ vrf_id);
/* If such interface does not exist, indicate an error */
if (! ifp)
@@ -943,7 +984,7 @@ memconstant(const void *s, int c, size_t n)
struct connected *
-zebra_interface_address_read (int type, struct stream *s)
+zebra_interface_address_read (int type, struct stream *s, vrf_id_t vrf_id)
{
unsigned int ifindex;
struct interface *ifp;
@@ -960,7 +1001,7 @@ zebra_interface_address_read (int type, struct stream *s)
ifindex = stream_getl (s);
/* Lookup index. */
- ifp = if_lookup_by_index (ifindex);
+ ifp = if_lookup_by_index_vrf (ifindex, vrf_id);
if (ifp == NULL)
{
zlog_warn ("zebra_interface_address_read(%s): "
@@ -1040,7 +1081,7 @@ zebra_interface_address_read (int type, struct stream *s)
* +-+-+-+-+-+-+-+-+
*/
struct nbr_connected *
-zebra_interface_nbr_address_read (int type, struct stream *s)
+zebra_interface_nbr_address_read (int type, struct stream *s, vrf_id_t vrf_id)
{
unsigned int ifindex;
struct interface *ifp;
@@ -1098,6 +1139,7 @@ zclient_read (struct thread *thread)
size_t already;
uint16_t length, command;
uint8_t marker, version;
+ vrf_id_t vrf_id;
struct zclient *zclient;
/* Get socket to zebra. */
@@ -1132,6 +1174,7 @@ zclient_read (struct thread *thread)
length = stream_getw (zclient->ibuf);
marker = stream_getc (zclient->ibuf);
version = stream_getc (zclient->ibuf);
+ vrf_id = stream_getw (zclient->ibuf);
command = stream_getw (zclient->ibuf);
if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION)
@@ -1183,97 +1226,97 @@ zclient_read (struct thread *thread)
length -= ZEBRA_HEADER_SIZE;
if (zclient_debug)
- zlog_debug("zclient 0x%p command 0x%x \n", zclient, command);
+ zlog_debug("zclient 0x%p command 0x%x VRF %u\n", (void *)zclient, command, vrf_id);
switch (command)
{
case ZEBRA_ROUTER_ID_UPDATE:
if (zclient->router_id_update)
- (*zclient->router_id_update) (command, zclient, length);
+ (*zclient->router_id_update) (command, zclient, length, vrf_id);
break;
case ZEBRA_INTERFACE_ADD:
if (zclient->interface_add)
- (*zclient->interface_add) (command, zclient, length);
+ (*zclient->interface_add) (command, zclient, length, vrf_id);
break;
case ZEBRA_INTERFACE_DELETE:
if (zclient->interface_delete)
- (*zclient->interface_delete) (command, zclient, length);
+ (*zclient->interface_delete) (command, zclient, length, vrf_id);
break;
case ZEBRA_INTERFACE_ADDRESS_ADD:
if (zclient->interface_address_add)
- (*zclient->interface_address_add) (command, zclient, length);
+ (*zclient->interface_address_add) (command, zclient, length, vrf_id);
break;
case ZEBRA_INTERFACE_ADDRESS_DELETE:
if (zclient->interface_address_delete)
- (*zclient->interface_address_delete) (command, zclient, length);
+ (*zclient->interface_address_delete) (command, zclient, length, vrf_id);
break;
case ZEBRA_INTERFACE_BFD_DEST_UPDATE:
if (zclient->interface_bfd_dest_update)
- (*zclient->interface_bfd_dest_update) (command, zclient, length);
+ (*zclient->interface_bfd_dest_update) (command, zclient, length, vrf_id);
break;
case ZEBRA_INTERFACE_NBR_ADDRESS_ADD:
if (zclient->interface_nbr_address_add)
- (*zclient->interface_nbr_address_add) (command, zclient, length);
+ (*zclient->interface_nbr_address_add) (command, zclient, length, vrf_id);
break;
case ZEBRA_INTERFACE_NBR_ADDRESS_DELETE:
if (zclient->interface_nbr_address_delete)
- (*zclient->interface_nbr_address_delete) (command, zclient, length);
+ (*zclient->interface_nbr_address_delete) (command, zclient, length, vrf_id);
break;
case ZEBRA_INTERFACE_UP:
if (zclient->interface_up)
- (*zclient->interface_up) (command, zclient, length);
+ (*zclient->interface_up) (command, zclient, length, vrf_id);
break;
case ZEBRA_INTERFACE_DOWN:
if (zclient->interface_down)
- (*zclient->interface_down) (command, zclient, length);
+ (*zclient->interface_down) (command, zclient, length, vrf_id);
break;
case ZEBRA_IPV4_ROUTE_ADD:
if (zclient->ipv4_route_add)
- (*zclient->ipv4_route_add) (command, zclient, length);
+ (*zclient->ipv4_route_add) (command, zclient, length, vrf_id);
break;
case ZEBRA_IPV4_ROUTE_DELETE:
if (zclient->ipv4_route_delete)
- (*zclient->ipv4_route_delete) (command, zclient, length);
+ (*zclient->ipv4_route_delete) (command, zclient, length, vrf_id);
break;
case ZEBRA_IPV6_ROUTE_ADD:
if (zclient->ipv6_route_add)
- (*zclient->ipv6_route_add) (command, zclient, length);
+ (*zclient->ipv6_route_add) (command, zclient, length, vrf_id);
break;
case ZEBRA_IPV6_ROUTE_DELETE:
if (zclient->ipv6_route_delete)
- (*zclient->ipv6_route_delete) (command, zclient, length);
+ (*zclient->ipv6_route_delete) (command, zclient, length, vrf_id);
break;
case ZEBRA_NEXTHOP_UPDATE:
if (zclient_debug)
zlog_debug("zclient rcvd nexthop update\n");
if (zclient->nexthop_update)
- (*zclient->nexthop_update) (command, zclient, length);
+ (*zclient->nexthop_update) (command, zclient, length, vrf_id);
break;
case ZEBRA_IMPORT_CHECK_UPDATE:
if (zclient_debug)
zlog_debug("zclient rcvd import check update\n");
if (zclient->import_check_update)
- (*zclient->import_check_update) (command, zclient, length);
+ (*zclient->import_check_update) (command, zclient, length, vrf_id);
break;
case ZEBRA_BFD_DEST_REPLAY:
if (zclient->bfd_dest_replay)
- (*zclient->bfd_dest_replay) (command, zclient, length);
+ (*zclient->bfd_dest_replay) (command, zclient, length, vrf_id);
break;
case ZEBRA_REDISTRIBUTE_IPV4_ADD:
if (zclient->redistribute_route_ipv4_add)
- (*zclient->redistribute_route_ipv4_add) (command, zclient, length);
+ (*zclient->redistribute_route_ipv4_add) (command, zclient, length, vrf_id);
break;
case ZEBRA_REDISTRIBUTE_IPV4_DEL:
if (zclient->redistribute_route_ipv4_del)
- (*zclient->redistribute_route_ipv4_del) (command, zclient, length);
+ (*zclient->redistribute_route_ipv4_del) (command, zclient, length, vrf_id);
break;
case ZEBRA_REDISTRIBUTE_IPV6_ADD:
if (zclient->redistribute_route_ipv6_add)
- (*zclient->redistribute_route_ipv6_add) (command, zclient, length);
+ (*zclient->redistribute_route_ipv6_add) (command, zclient, length, vrf_id);
break;
case ZEBRA_REDISTRIBUTE_IPV6_DEL:
if (zclient->redistribute_route_ipv6_del)
- (*zclient->redistribute_route_ipv6_del) (command, zclient, length);
+ (*zclient->redistribute_route_ipv6_del) (command, zclient, length, vrf_id);
break;
default:
break;
@@ -1292,46 +1335,63 @@ zclient_read (struct thread *thread)
void
zclient_redistribute (int command, struct zclient *zclient, afi_t afi, int type,
- u_short instance)
+ u_short instance, vrf_id_t vrf_id)
{
- if (command == ZEBRA_REDISTRIBUTE_ADD)
- {
- if (redist_check_instance(&zclient->redist[afi][type], instance))
- return;
- redist_add_instance(&zclient->redist[afi][type], instance);
- }
- else
- {
- if (!redist_check_instance(&zclient->redist[afi][type], instance))
- return;
- redist_del_instance(&zclient->redist[afi][type], instance);
- }
+ if (instance) {
+ if (command == ZEBRA_REDISTRIBUTE_ADD)
+ {
+ if (redist_check_instance(&zclient->mi_redist[afi][type], instance))
+ return;
+ redist_add_instance(&zclient->mi_redist[afi][type], instance);
+ }
+ else
+ {
+ if (!redist_check_instance(&zclient->mi_redist[afi][type], instance))
+ return;
+ redist_del_instance(&zclient->mi_redist[afi][type], instance);
+ }
+
+ } else {
+ if (command == ZEBRA_REDISTRIBUTE_ADD)
+ {
+ if (vrf_bitmap_check (zclient->redist[afi][type], vrf_id))
+ return;
+ vrf_bitmap_set (zclient->redist[afi][type], vrf_id);
+ }
+ else
+ {
+ if (!vrf_bitmap_check (zclient->redist[afi][type], vrf_id))
+ return;
+ vrf_bitmap_unset (zclient->redist[afi][type], vrf_id);
+ }
+ }
if (zclient->sock > 0)
- zebra_redistribute_send (command, zclient, afi, type, instance);
+ zebra_redistribute_send (command, zclient, afi, type, instance, vrf_id);
}
void
-zclient_redistribute_default (int command, struct zclient *zclient)
+zclient_redistribute_default (int command, struct zclient *zclient,
+ vrf_id_t vrf_id)
{
if (command == ZEBRA_REDISTRIBUTE_DEFAULT_ADD)
{
- if (zclient->default_information)
+ if (vrf_bitmap_check (zclient->default_information, vrf_id))
return;
- zclient->default_information = 1;
+ vrf_bitmap_set (zclient->default_information, vrf_id);
}
else
{
- if (!zclient->default_information)
+ if (!vrf_bitmap_check (zclient->default_information, vrf_id))
return;
- zclient->default_information = 0;
+ vrf_bitmap_unset (zclient->default_information, vrf_id);
}
if (zclient->sock > 0)
- zebra_message_send (zclient, command);
+ zebra_message_send (zclient, command, vrf_id);
}
static void