diff options
Diffstat (limited to 'lib/zclient.c')
| -rw-r--r-- | lib/zclient.c | 306 |
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 |
