diff options
Diffstat (limited to 'bgpd/bgp_zebra.c')
| -rw-r--r-- | bgpd/bgp_zebra.c | 3508 |
1 files changed, 1728 insertions, 1780 deletions
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 72bd081a7e..0700db9fb7 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -47,8 +47,8 @@ Boston, MA 02111-1307, USA. */ #include "bgpd/bgp_nht.h" #include "bgpd/bgp_bfd.h" #if ENABLE_BGP_VNC -# include "bgpd/rfapi/rfapi_backend.h" -# include "bgpd/rfapi/vnc_export_bgp.h" +#include "bgpd/rfapi/rfapi_backend.h" +#include "bgpd/rfapi/vnc_export_bgp.h" #endif /* All information about zebra. */ @@ -72,2092 +72,2040 @@ struct attr_extra attr_extra_cp[MULTIPATH_NUM]; unsigned int attr_index = 0; /* Once per address-family initialization of the attribute array */ -#define BGP_INFO_ATTR_BUF_INIT()\ -do {\ - memset(attr_cp, 0, MULTIPATH_NUM * sizeof(struct attr));\ - memset(attr_extra_cp, 0, MULTIPATH_NUM * sizeof(struct attr_extra));\ - attr_index = 0;\ -} while (0) - -#define BGP_INFO_ATTR_BUF_COPY(info_src, info_dst)\ -do { \ - *info_dst = *info_src; \ - assert(attr_index != multipath_num);\ - attr_cp[attr_index].extra = &attr_extra_cp[attr_index]; \ - bgp_attr_dup (&attr_cp[attr_index], info_src->attr); \ - bgp_attr_deep_dup (&attr_cp[attr_index], info_src->attr); \ - info_dst->attr = &attr_cp[attr_index]; \ - attr_index++;\ -} while (0) - -#define BGP_INFO_ATTR_BUF_FREE(info) \ -do { \ - bgp_attr_deep_free(info->attr); \ -} while (0) +#define BGP_INFO_ATTR_BUF_INIT() \ + do { \ + memset(attr_cp, 0, MULTIPATH_NUM * sizeof(struct attr)); \ + memset(attr_extra_cp, 0, \ + MULTIPATH_NUM * sizeof(struct attr_extra)); \ + attr_index = 0; \ + } while (0) + +#define BGP_INFO_ATTR_BUF_COPY(info_src, info_dst) \ + do { \ + *info_dst = *info_src; \ + assert(attr_index != multipath_num); \ + attr_cp[attr_index].extra = &attr_extra_cp[attr_index]; \ + bgp_attr_dup(&attr_cp[attr_index], info_src->attr); \ + bgp_attr_deep_dup(&attr_cp[attr_index], info_src->attr); \ + info_dst->attr = &attr_cp[attr_index]; \ + attr_index++; \ + } while (0) + +#define BGP_INFO_ATTR_BUF_FREE(info) \ + do { \ + bgp_attr_deep_free(info->attr); \ + } while (0) /* Can we install into zebra? */ -static inline int -bgp_install_info_to_zebra (struct bgp *bgp) +static inline int bgp_install_info_to_zebra(struct bgp *bgp) { - if (zclient->sock <= 0) - return 0; + if (zclient->sock <= 0) + return 0; - if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) - return 0; + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + return 0; - return 1; + return 1; } int zclient_num_connects; /* Router-id update message from zebra. */ -static int -bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int bgp_router_id_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct prefix router_id; + struct prefix router_id; - zebra_router_id_update_read(zclient->ibuf,&router_id); + zebra_router_id_update_read(zclient->ibuf, &router_id); - if (BGP_DEBUG (zebra, ZEBRA)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(&router_id, buf, sizeof(buf)); - zlog_debug("Rx Router Id update VRF %u Id %s", vrf_id, buf); - } + if (BGP_DEBUG(zebra, ZEBRA)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&router_id, buf, sizeof(buf)); + zlog_debug("Rx Router Id update VRF %u Id %s", vrf_id, buf); + } - bgp_router_id_zebra_bump (vrf_id, &router_id); - return 0; + bgp_router_id_zebra_bump(vrf_id, &router_id); + return 0; } /* Nexthop update message from zebra. */ -static int -bgp_read_nexthop_update (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_read_nexthop_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - bgp_parse_nexthop_update(command, vrf_id); - return 0; + bgp_parse_nexthop_update(command, vrf_id); + return 0; } -static int -bgp_read_import_check_update(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_read_import_check_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - bgp_parse_nexthop_update(command, vrf_id); - return 0; + bgp_parse_nexthop_update(command, vrf_id); + return 0; } /* Set or clear interface on which unnumbered neighbor is configured. This * would in turn cause BGP to initiate or turn off IPv6 RAs on this * interface. */ -static void -bgp_update_interface_nbrs (struct bgp *bgp, struct interface *ifp, - struct interface *upd_ifp) +static void bgp_update_interface_nbrs(struct bgp *bgp, struct interface *ifp, + struct interface *upd_ifp) { - struct listnode *node, *nnode; - struct peer *peer; - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->conf_if && - (strcmp (peer->conf_if, ifp->name) == 0)) - { - if (upd_ifp) - { - peer->ifp = upd_ifp; - bgp_zebra_initiate_radv (bgp, peer); - } - else - { - bgp_zebra_terminate_radv (bgp, peer); - peer->ifp = upd_ifp; - } - } - } + struct listnode *node, *nnode; + struct peer *peer; + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->conf_if && (strcmp(peer->conf_if, ifp->name) == 0)) { + if (upd_ifp) { + peer->ifp = upd_ifp; + bgp_zebra_initiate_radv(bgp, peer); + } else { + bgp_zebra_terminate_radv(bgp, peer); + peer->ifp = upd_ifp; + } + } + } } -static void -bgp_start_interface_nbrs (struct bgp *bgp, struct interface *ifp) +static void bgp_start_interface_nbrs(struct bgp *bgp, struct interface *ifp) { - struct listnode *node, *nnode; - struct peer *peer; - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->conf_if && - (strcmp (peer->conf_if, ifp->name) == 0) && - peer->status != Established) - { - if (peer_active(peer)) - BGP_EVENT_ADD (peer, BGP_Stop); - BGP_EVENT_ADD (peer, BGP_Start); - } - } + struct listnode *node, *nnode; + struct peer *peer; + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->conf_if && (strcmp(peer->conf_if, ifp->name) == 0) + && peer->status != Established) { + if (peer_active(peer)) + BGP_EVENT_ADD(peer, BGP_Stop); + BGP_EVENT_ADD(peer, BGP_Start); + } + } } -static void -bgp_nbr_connected_add (struct bgp *bgp, struct nbr_connected *ifc) +static void bgp_nbr_connected_add(struct bgp *bgp, struct nbr_connected *ifc) { - struct listnode *node; - struct connected *connected; - struct interface *ifp; - struct prefix *p; - - /* Kick-off the FSM for any relevant peers only if there is a - * valid local address on the interface. - */ - ifp = ifc->ifp; - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) - { - p = connected->address; - if (p->family == AF_INET6 && - IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6)) - break; - } - if (!connected) - return; - - bgp_start_interface_nbrs (bgp, ifp); + struct listnode *node; + struct connected *connected; + struct interface *ifp; + struct prefix *p; + + /* Kick-off the FSM for any relevant peers only if there is a + * valid local address on the interface. + */ + ifp = ifc->ifp; + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { + p = connected->address; + if (p->family == AF_INET6 + && IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6)) + break; + } + if (!connected) + return; + + bgp_start_interface_nbrs(bgp, ifp); } -static void -bgp_nbr_connected_delete (struct bgp *bgp, struct nbr_connected *ifc, int del) +static void bgp_nbr_connected_delete(struct bgp *bgp, struct nbr_connected *ifc, + int del) { - struct listnode *node, *nnode; - struct peer *peer; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0)) - { - peer->last_reset = PEER_DOWN_NBR_ADDR_DEL; - BGP_EVENT_ADD (peer, BGP_Stop); - } - } - /* Free neighbor also, if we're asked to. */ - if (del) - { - ifp = ifc->ifp; - listnode_delete (ifp->nbr_connected, ifc); - nbr_connected_free (ifc); - } + struct listnode *node, *nnode; + struct peer *peer; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->conf_if + && (strcmp(peer->conf_if, ifc->ifp->name) == 0)) { + peer->last_reset = PEER_DOWN_NBR_ADDR_DEL; + BGP_EVENT_ADD(peer, BGP_Stop); + } + } + /* Free neighbor also, if we're asked to. */ + if (del) { + ifp = ifc->ifp; + listnode_delete(ifp->nbr_connected, ifc); + nbr_connected_free(ifc); + } } /* Inteface addition message from zebra. */ -static int -bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int bgp_interface_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct bgp *bgp; + struct interface *ifp; + struct bgp *bgp; - ifp = zebra_interface_add_read (zclient->ibuf, vrf_id); - if (!ifp) // unexpected - return 0; + ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); + if (!ifp) // unexpected + return 0; - if (BGP_DEBUG (zebra, ZEBRA) && ifp) - zlog_debug("Rx Intf add VRF %u IF %s", vrf_id, ifp->name); + if (BGP_DEBUG(zebra, ZEBRA) && ifp) + zlog_debug("Rx Intf add VRF %u IF %s", vrf_id, ifp->name); - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; - bgp_update_interface_nbrs (bgp, ifp, ifp); - return 0; + bgp_update_interface_nbrs(bgp, ifp, ifp); + return 0; } -static int -bgp_interface_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_interface_delete(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct interface *ifp; - struct bgp *bgp; + struct stream *s; + struct interface *ifp; + struct bgp *bgp; - s = zclient->ibuf; - ifp = zebra_interface_state_read (s, vrf_id); - if (!ifp) /* This may happen if we've just unregistered for a VRF. */ - return 0; + s = zclient->ibuf; + ifp = zebra_interface_state_read(s, vrf_id); + if (!ifp) /* This may happen if we've just unregistered for a VRF. */ + return 0; - ifp->ifindex = IFINDEX_DELETED; + ifp->ifindex = IFINDEX_DELETED; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Rx Intf del VRF %u IF %s", vrf_id, ifp->name); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Rx Intf del VRF %u IF %s", vrf_id, ifp->name); - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; - bgp_update_interface_nbrs (bgp, ifp, NULL); - return 0; + bgp_update_interface_nbrs(bgp, ifp, NULL); + return 0; } -static int -bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int bgp_interface_up(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct interface *ifp; - struct connected *c; - struct nbr_connected *nc; - struct listnode *node, *nnode; - struct bgp *bgp; + struct stream *s; + struct interface *ifp; + struct connected *c; + struct nbr_connected *nc; + struct listnode *node, *nnode; + struct bgp *bgp; - s = zclient->ibuf; - ifp = zebra_interface_state_read (s, vrf_id); + s = zclient->ibuf; + ifp = zebra_interface_state_read(s, vrf_id); - if (! ifp) - return 0; + if (!ifp) + return 0; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Rx Intf up VRF %u IF %s", vrf_id, ifp->name); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Rx Intf up VRF %u IF %s", vrf_id, ifp->name); - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c)) - bgp_connected_add (bgp, c); + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c)) + bgp_connected_add(bgp, c); - for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nc)) - bgp_nbr_connected_add (bgp, nc); + for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc)) + bgp_nbr_connected_add(bgp, nc); - return 0; + return 0; } -static int -bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int bgp_interface_down(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct interface *ifp; - struct connected *c; - struct nbr_connected *nc; - struct listnode *node, *nnode; - struct bgp *bgp; + struct stream *s; + struct interface *ifp; + struct connected *c; + struct nbr_connected *nc; + struct listnode *node, *nnode; + struct bgp *bgp; - s = zclient->ibuf; - ifp = zebra_interface_state_read (s, vrf_id); - if (! ifp) - return 0; + s = zclient->ibuf; + ifp = zebra_interface_state_read(s, vrf_id); + if (!ifp) + return 0; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Rx Intf down VRF %u IF %s", vrf_id, ifp->name); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Rx Intf down VRF %u IF %s", vrf_id, ifp->name); - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c)) - bgp_connected_delete (bgp, c); + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c)) + bgp_connected_delete(bgp, c); - for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nc)) - bgp_nbr_connected_delete (bgp, nc, 1); + for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc)) + bgp_nbr_connected_delete(bgp, nc, 1); - /* Fast external-failover */ - { - struct peer *peer; + /* Fast external-failover */ + { + struct peer *peer; - if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) - return 0; + if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) + return 0; - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { #if defined(HAVE_CUMULUS) - /* Take down directly connected EBGP peers as well as 1-hop BFD - * tracked (directly connected) IBGP peers. - */ - if ((peer->ttl != 1) && (peer->gtsm_hops != 1) && - (!peer->bfd_info || bgp_bfd_is_peer_multihop(peer))) + /* Take down directly connected EBGP peers as well as + * 1-hop BFD + * tracked (directly connected) IBGP peers. + */ + if ((peer->ttl != 1) && (peer->gtsm_hops != 1) + && (!peer->bfd_info + || bgp_bfd_is_peer_multihop(peer))) #else - /* Take down directly connected EBGP peers */ - if ((peer->ttl != 1) && (peer->gtsm_hops != 1)) + /* Take down directly connected EBGP peers */ + if ((peer->ttl != 1) && (peer->gtsm_hops != 1)) #endif - continue; + continue; - if (ifp == peer->nexthop.ifp) - { - BGP_EVENT_ADD (peer, BGP_Stop); - peer->last_reset = PEER_DOWN_IF_DOWN; - } - } - } + if (ifp == peer->nexthop.ifp) { + BGP_EVENT_ADD(peer, BGP_Stop); + peer->last_reset = PEER_DOWN_IF_DOWN; + } + } + } - return 0; + return 0; } -static int -bgp_interface_address_add (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_interface_address_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct connected *ifc; - - ifc = zebra_interface_address_read (command, zclient->ibuf, vrf_id); - - if (ifc == NULL) - return 0; - - if (bgp_debug_zebra(ifc->address)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(ifc->address, buf, sizeof(buf)); - zlog_debug("Rx Intf address add VRF %u IF %s addr %s", - vrf_id, ifc->ifp->name, buf); - } - - if (if_is_operative (ifc->ifp)) - { - struct bgp *bgp; - - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; - - bgp_connected_add (bgp, ifc); - /* If we have learnt of any neighbors on this interface, - * check to kick off any BGP interface-based neighbors, - * but only if this is a link-local address. - */ - if (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6) && - !list_isempty(ifc->ifp->nbr_connected)) - bgp_start_interface_nbrs (bgp, ifc->ifp); - } - - return 0; + struct connected *ifc; + + ifc = zebra_interface_address_read(command, zclient->ibuf, vrf_id); + + if (ifc == NULL) + return 0; + + if (bgp_debug_zebra(ifc->address)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(ifc->address, buf, sizeof(buf)); + zlog_debug("Rx Intf address add VRF %u IF %s addr %s", vrf_id, + ifc->ifp->name, buf); + } + + if (if_is_operative(ifc->ifp)) { + struct bgp *bgp; + + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; + + bgp_connected_add(bgp, ifc); + /* If we have learnt of any neighbors on this interface, + * check to kick off any BGP interface-based neighbors, + * but only if this is a link-local address. + */ + if (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6) + && !list_isempty(ifc->ifp->nbr_connected)) + bgp_start_interface_nbrs(bgp, ifc->ifp); + } + + return 0; } -static int -bgp_interface_address_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_interface_address_delete(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct connected *ifc; - struct bgp *bgp; + struct connected *ifc; + struct bgp *bgp; - ifc = zebra_interface_address_read (command, zclient->ibuf, vrf_id); + ifc = zebra_interface_address_read(command, zclient->ibuf, vrf_id); - if (ifc == NULL) - return 0; + if (ifc == NULL) + return 0; - if (bgp_debug_zebra(ifc->address)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(ifc->address, buf, sizeof(buf)); - zlog_debug("Rx Intf address del VRF %u IF %s addr %s", - vrf_id, ifc->ifp->name, buf); - } + if (bgp_debug_zebra(ifc->address)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(ifc->address, buf, sizeof(buf)); + zlog_debug("Rx Intf address del VRF %u IF %s addr %s", vrf_id, + ifc->ifp->name, buf); + } - if (if_is_operative (ifc->ifp)) - { - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (bgp) - bgp_connected_delete (bgp, ifc); - } + if (if_is_operative(ifc->ifp)) { + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (bgp) + bgp_connected_delete(bgp, ifc); + } - connected_free (ifc); + connected_free(ifc); - return 0; + return 0; } -static int -bgp_interface_nbr_address_add (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_interface_nbr_address_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct nbr_connected *ifc = NULL; - struct bgp *bgp; - - ifc = zebra_interface_nbr_address_read (command, zclient->ibuf, vrf_id); - - if (ifc == NULL) - return 0; - - if (bgp_debug_zebra(ifc->address)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(ifc->address, buf, sizeof(buf)); - zlog_debug("Rx Intf neighbor add VRF %u IF %s addr %s", - vrf_id, ifc->ifp->name, buf); - } - - if (if_is_operative (ifc->ifp)) - { - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (bgp) - bgp_nbr_connected_add (bgp, ifc); - } - - return 0; + struct nbr_connected *ifc = NULL; + struct bgp *bgp; + + ifc = zebra_interface_nbr_address_read(command, zclient->ibuf, vrf_id); + + if (ifc == NULL) + return 0; + + if (bgp_debug_zebra(ifc->address)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(ifc->address, buf, sizeof(buf)); + zlog_debug("Rx Intf neighbor add VRF %u IF %s addr %s", vrf_id, + ifc->ifp->name, buf); + } + + if (if_is_operative(ifc->ifp)) { + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (bgp) + bgp_nbr_connected_add(bgp, ifc); + } + + return 0; } -static int -bgp_interface_nbr_address_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_interface_nbr_address_delete(int command, + struct zclient *zclient, + zebra_size_t length, + vrf_id_t vrf_id) { - struct nbr_connected *ifc = NULL; - struct bgp *bgp; + struct nbr_connected *ifc = NULL; + struct bgp *bgp; - ifc = zebra_interface_nbr_address_read (command, zclient->ibuf, vrf_id); + ifc = zebra_interface_nbr_address_read(command, zclient->ibuf, vrf_id); - if (ifc == NULL) - return 0; + if (ifc == NULL) + return 0; - if (bgp_debug_zebra(ifc->address)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(ifc->address, buf, sizeof(buf)); - zlog_debug("Rx Intf neighbor del VRF %u IF %s addr %s", - vrf_id, ifc->ifp->name, buf); - } + if (bgp_debug_zebra(ifc->address)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(ifc->address, buf, sizeof(buf)); + zlog_debug("Rx Intf neighbor del VRF %u IF %s addr %s", vrf_id, + ifc->ifp->name, buf); + } - if (if_is_operative (ifc->ifp)) - { - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (bgp) - bgp_nbr_connected_delete (bgp, ifc, 0); - } + if (if_is_operative(ifc->ifp)) { + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (bgp) + bgp_nbr_connected_delete(bgp, ifc, 0); + } - nbr_connected_free (ifc); + nbr_connected_free(ifc); - return 0; + return 0; } /* VRF update for an interface. */ -static int -bgp_interface_vrf_update (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int bgp_interface_vrf_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - vrf_id_t new_vrf_id; - struct connected *c; - struct nbr_connected *nc; - struct listnode *node, *nnode; - struct bgp *bgp; + struct interface *ifp; + vrf_id_t new_vrf_id; + struct connected *c; + struct nbr_connected *nc; + struct listnode *node, *nnode; + struct bgp *bgp; - ifp = zebra_interface_vrf_update_read (zclient->ibuf, vrf_id, &new_vrf_id); - if (! ifp) - return 0; + ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id, + &new_vrf_id); + if (!ifp) + return 0; - if (BGP_DEBUG (zebra, ZEBRA) && ifp) - zlog_debug("Rx Intf VRF change VRF %u IF %s NewVRF %u", - vrf_id, ifp->name, new_vrf_id); + if (BGP_DEBUG(zebra, ZEBRA) && ifp) + zlog_debug("Rx Intf VRF change VRF %u IF %s NewVRF %u", vrf_id, + ifp->name, new_vrf_id); - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c)) - bgp_connected_delete (bgp, c); + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c)) + bgp_connected_delete(bgp, c); - for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nc)) - bgp_nbr_connected_delete (bgp, nc, 1); + for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc)) + bgp_nbr_connected_delete(bgp, nc, 1); - /* Fast external-failover */ - { - struct peer *peer; + /* Fast external-failover */ + { + struct peer *peer; - if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) - return 0; + if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) + return 0; - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if ((peer->ttl != 1) && (peer->gtsm_hops != 1)) - continue; + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if ((peer->ttl != 1) && (peer->gtsm_hops != 1)) + continue; - if (ifp == peer->nexthop.ifp) - BGP_EVENT_ADD (peer, BGP_Stop); - } - } + if (ifp == peer->nexthop.ifp) + BGP_EVENT_ADD(peer, BGP_Stop); + } + } - if_update (ifp, ifp->name, strlen (ifp->name), new_vrf_id); + if_update(ifp, ifp->name, strlen(ifp->name), new_vrf_id); - bgp = bgp_lookup_by_vrf_id (new_vrf_id); - if (!bgp) - return 0; + bgp = bgp_lookup_by_vrf_id(new_vrf_id); + if (!bgp) + return 0; - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c)) - bgp_connected_add (bgp, c); + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c)) + bgp_connected_add(bgp, c); - for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nc)) - bgp_nbr_connected_add (bgp, nc); - return 0; + for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc)) + bgp_nbr_connected_add(bgp, nc); + return 0; } /* Zebra route add and delete treatment. */ -static int -zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int zebra_read_ipv4(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; - struct in_addr nexthop; - struct prefix_ipv4 p; - unsigned int ifindex; - int i; - struct bgp *bgp; - - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; - - s = zclient->ibuf; - nexthop.s_addr = 0; - - /* Type, flags, message. */ - api.type = stream_getc (s); - api.instance = stream_getw (s); - api.flags = stream_getl (s); - api.message = stream_getc (s); - - /* IPv4 prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc (s)); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) - { - api.nexthop_num = stream_getc (s); - nexthop.s_addr = stream_get_ipv4 (s); - } - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) - { - api.ifindex_num = stream_getc (s); - ifindex = stream_getl (s); /* ifindex, unused */ - } - else - { - ifindex = 0; - } - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - else - api.metric = 0; - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl (s); - else - api.tag = 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) - { - if (bgp_debug_zebra((struct prefix *)&p)) - { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Rx IPv4 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %"ROUTE_TAG_PRI, - vrf_id, - zebra_route_string(api.type), api.instance, - inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), - p.prefixlen, - inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), - api.metric, - api.tag); + struct stream *s; + struct zapi_ipv4 api; + struct in_addr nexthop; + struct prefix_ipv4 p; + unsigned int ifindex; + int i; + struct bgp *bgp; + + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; + + s = zclient->ibuf; + nexthop.s_addr = 0; + + /* Type, flags, message. */ + api.type = stream_getc(s); + api.instance = stream_getw(s); + api.flags = stream_getl(s); + api.message = stream_getc(s); + + /* IPv4 prefix. */ + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); + stream_get(&p.prefix, s, PSIZE(p.prefixlen)); + + /* Nexthop, ifindex, distance, metric. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + api.nexthop_num = stream_getc(s); + nexthop.s_addr = stream_get_ipv4(s); } - /* - * The ADD message is actually an UPDATE and there is no explicit DEL - * for a prior redistributed route, if any. So, perform an implicit - * DEL processing for the same redistributed route from any other - * source type. - */ - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if (i != api.type) - bgp_redistribute_delete(bgp, (struct prefix *)&p, i, api.instance); - } - - /* Now perform the add/update. */ - bgp_redistribute_add(bgp, (struct prefix *)&p, &nexthop, NULL, ifindex, - api.metric, api.type, api.instance, api.tag); - } - else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) - { - if (bgp_debug_zebra((struct prefix *)&p)) - { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Rx IPv4 route delete VRF %u %s[%d] %s/%d " - "nexthop %s metric %u tag %"ROUTE_TAG_PRI, - vrf_id, - zebra_route_string(api.type), api.instance, - inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), - p.prefixlen, - inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), - api.metric, - api.tag); + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { + api.ifindex_num = stream_getc(s); + ifindex = stream_getl(s); /* ifindex, unused */ + } else { + ifindex = 0; + } + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + api.distance = stream_getc(s); + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + api.metric = stream_getl(s); + else + api.metric = 0; + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getl(s); + else + api.tag = 0; + + if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { + if (bgp_debug_zebra((struct prefix *)&p)) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug( + "Rx IPv4 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %" ROUTE_TAG_PRI, + vrf_id, zebra_route_string(api.type), + api.instance, inet_ntop(AF_INET, &p.prefix, + buf[0], sizeof(buf[0])), + p.prefixlen, inet_ntop(AF_INET, &nexthop, + buf[1], sizeof(buf[1])), + api.metric, api.tag); + } + + /* + * The ADD message is actually an UPDATE and there is no + * explicit DEL + * for a prior redistributed route, if any. So, perform an + * implicit + * DEL processing for the same redistributed route from any + * other + * source type. + */ + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (i != api.type) + bgp_redistribute_delete(bgp, + (struct prefix *)&p, i, + api.instance); + } + + /* Now perform the add/update. */ + bgp_redistribute_add(bgp, (struct prefix *)&p, &nexthop, NULL, + ifindex, api.metric, api.type, + api.instance, api.tag); + } else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) { + if (bgp_debug_zebra((struct prefix *)&p)) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug( + "Rx IPv4 route delete VRF %u %s[%d] %s/%d " + "nexthop %s metric %u tag %" ROUTE_TAG_PRI, + vrf_id, zebra_route_string(api.type), + api.instance, inet_ntop(AF_INET, &p.prefix, + buf[0], sizeof(buf[0])), + p.prefixlen, inet_ntop(AF_INET, &nexthop, + buf[1], sizeof(buf[1])), + api.metric, api.tag); + } + bgp_redistribute_delete(bgp, (struct prefix *)&p, api.type, + api.instance); } - bgp_redistribute_delete(bgp, (struct prefix *)&p, api.type, api.instance); - } - return 0; + return 0; } /* Zebra route add and delete treatment. */ -static int -zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int zebra_read_ipv6(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv6 api; - struct in6_addr nexthop; - struct prefix_ipv6 p, src_p; - unsigned int ifindex; - int i; - struct bgp *bgp; - - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; - - s = zclient->ibuf; - memset (&nexthop, 0, sizeof (struct in6_addr)); - - /* Type, flags, message. */ - api.type = stream_getc (s); - api.instance = stream_getw (s); - api.flags = stream_getl (s); - api.message = stream_getc (s); - - /* IPv6 prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc (s)); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); - - memset (&src_p, 0, sizeof (struct prefix_ipv6)); - src_p.family = AF_INET6; - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_SRCPFX)) - { - src_p.prefixlen = stream_getc (s); - stream_get (&src_p.prefix, s, PSIZE (src_p.prefixlen)); - } - - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ - return 0; - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) - { - api.nexthop_num = stream_getc (s); - stream_get (&nexthop, s, 16); - } - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) - { - api.ifindex_num = stream_getc (s); - ifindex = stream_getl (s); /* ifindex, unused */ - } - else - { - ifindex = 0; - } - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - else - api.distance = 0; - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - else - api.metric = 0; - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl (s); - else - api.tag = 0; - - /* Simply ignore link-local address. */ - if (IN6_IS_ADDR_LINKLOCAL (&p.prefix)) - return 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) - { - if (bgp_debug_zebra((struct prefix *)&p)) - { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Rx IPv6 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %"ROUTE_TAG_PRI, - vrf_id, - zebra_route_string(api.type), api.instance, - inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])), - p.prefixlen, - inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), - api.metric, - api.tag); + struct stream *s; + struct zapi_ipv6 api; + struct in6_addr nexthop; + struct prefix_ipv6 p, src_p; + unsigned int ifindex; + int i; + struct bgp *bgp; + + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; + + s = zclient->ibuf; + memset(&nexthop, 0, sizeof(struct in6_addr)); + + /* Type, flags, message. */ + api.type = stream_getc(s); + api.instance = stream_getw(s); + api.flags = stream_getl(s); + api.message = stream_getc(s); + + /* IPv6 prefix. */ + memset(&p, 0, sizeof(struct prefix_ipv6)); + p.family = AF_INET6; + p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); + stream_get(&p.prefix, s, PSIZE(p.prefixlen)); + + memset(&src_p, 0, sizeof(struct prefix_ipv6)); + src_p.family = AF_INET6; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { + src_p.prefixlen = stream_getc(s); + stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); } - /* - * The ADD message is actually an UPDATE and there is no explicit DEL - * for a prior redistributed route, if any. So, perform an implicit - * DEL processing for the same redistributed route from any other - * source type. - */ - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if (i != api.type) - bgp_redistribute_delete(bgp, (struct prefix *)&p, i, api.instance); - } - - bgp_redistribute_add (bgp, (struct prefix *)&p, NULL, &nexthop, ifindex, - api.metric, api.type, api.instance, api.tag); - } - else if (command == ZEBRA_REDISTRIBUTE_IPV6_DEL) - { - if (bgp_debug_zebra((struct prefix *)&p)) - { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Rx IPv6 route delete VRF %u %s[%d] %s/%d " - "nexthop %s metric %u tag %"ROUTE_TAG_PRI, - vrf_id, - zebra_route_string(api.type), api.instance, - inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])), - p.prefixlen, - inet_ntop(AF_INET6, &nexthop, buf[1], sizeof(buf[1])), - api.metric, - api.tag); + if (src_p.prefixlen) + /* we completely ignore srcdest routes for now. */ + return 0; + + /* Nexthop, ifindex, distance, metric. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + api.nexthop_num = stream_getc(s); + stream_get(&nexthop, s, 16); + } + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { + api.ifindex_num = stream_getc(s); + ifindex = stream_getl(s); /* ifindex, unused */ + } else { + ifindex = 0; + } + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + api.distance = stream_getc(s); + else + api.distance = 0; + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + api.metric = stream_getl(s); + else + api.metric = 0; + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getl(s); + else + api.tag = 0; + + /* Simply ignore link-local address. */ + if (IN6_IS_ADDR_LINKLOCAL(&p.prefix)) + return 0; + + if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) { + if (bgp_debug_zebra((struct prefix *)&p)) { + char buf[2][INET6_ADDRSTRLEN]; + zlog_debug( + "Rx IPv6 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %" ROUTE_TAG_PRI, + vrf_id, zebra_route_string(api.type), + api.instance, inet_ntop(AF_INET6, &p.prefix, + buf[0], sizeof(buf[0])), + p.prefixlen, inet_ntop(AF_INET, &nexthop, + buf[1], sizeof(buf[1])), + api.metric, api.tag); + } + + /* + * The ADD message is actually an UPDATE and there is no + * explicit DEL + * for a prior redistributed route, if any. So, perform an + * implicit + * DEL processing for the same redistributed route from any + * other + * source type. + */ + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (i != api.type) + bgp_redistribute_delete(bgp, + (struct prefix *)&p, i, + api.instance); + } + + bgp_redistribute_add(bgp, (struct prefix *)&p, NULL, &nexthop, + ifindex, api.metric, api.type, + api.instance, api.tag); + } else if (command == ZEBRA_REDISTRIBUTE_IPV6_DEL) { + if (bgp_debug_zebra((struct prefix *)&p)) { + char buf[2][INET6_ADDRSTRLEN]; + zlog_debug( + "Rx IPv6 route delete VRF %u %s[%d] %s/%d " + "nexthop %s metric %u tag %" ROUTE_TAG_PRI, + vrf_id, zebra_route_string(api.type), + api.instance, inet_ntop(AF_INET6, &p.prefix, + buf[0], sizeof(buf[0])), + p.prefixlen, inet_ntop(AF_INET6, &nexthop, + buf[1], sizeof(buf[1])), + api.metric, api.tag); + } + bgp_redistribute_delete(bgp, (struct prefix *)&p, api.type, + api.instance); } - bgp_redistribute_delete (bgp, (struct prefix *) &p, api.type, api.instance); - } - - return 0; + + return 0; } -struct interface * -if_lookup_by_ipv4 (struct in_addr *addr, vrf_id_t vrf_id) +struct interface *if_lookup_by_ipv4(struct in_addr *addr, vrf_id_t vrf_id) { - struct listnode *ifnode; - struct listnode *cnode; - struct interface *ifp; - struct connected *connected; - struct prefix_ipv4 p; - struct prefix *cp; - - p.family = AF_INET; - p.prefix = *addr; - p.prefixlen = IPV4_MAX_BITLEN; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist(vrf_id), ifnode, ifp)) - { - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - cp = connected->address; - - if (cp->family == AF_INET) - if (prefix_match (cp, (struct prefix *)&p)) - return ifp; + struct listnode *ifnode; + struct listnode *cnode; + struct interface *ifp; + struct connected *connected; + struct prefix_ipv4 p; + struct prefix *cp; + + p.family = AF_INET; + p.prefix = *addr; + p.prefixlen = IPV4_MAX_BITLEN; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) { + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + cp = connected->address; + + if (cp->family == AF_INET) + if (prefix_match(cp, (struct prefix *)&p)) + return ifp; + } } - } - return NULL; + return NULL; } -struct interface * -if_lookup_by_ipv4_exact (struct in_addr *addr, vrf_id_t vrf_id) +struct interface *if_lookup_by_ipv4_exact(struct in_addr *addr, vrf_id_t vrf_id) { - struct listnode *ifnode; - struct listnode *cnode; - struct interface *ifp; - struct connected *connected; - struct prefix *cp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist(vrf_id), ifnode, ifp)) - { - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - cp = connected->address; - - if (cp->family == AF_INET) - if (IPV4_ADDR_SAME (&cp->u.prefix4, addr)) - return ifp; + struct listnode *ifnode; + struct listnode *cnode; + struct interface *ifp; + struct connected *connected; + struct prefix *cp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) { + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + cp = connected->address; + + if (cp->family == AF_INET) + if (IPV4_ADDR_SAME(&cp->u.prefix4, addr)) + return ifp; + } } - } - return NULL; + return NULL; } -struct interface * -if_lookup_by_ipv6 (struct in6_addr *addr, ifindex_t ifindex, vrf_id_t vrf_id) +struct interface *if_lookup_by_ipv6(struct in6_addr *addr, ifindex_t ifindex, + vrf_id_t vrf_id) { - struct listnode *ifnode; - struct listnode *cnode; - struct interface *ifp; - struct connected *connected; - struct prefix_ipv6 p; - struct prefix *cp; - - p.family = AF_INET6; - p.prefix = *addr; - p.prefixlen = IPV6_MAX_BITLEN; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist(vrf_id), ifnode, ifp)) - { - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - cp = connected->address; - - if (cp->family == AF_INET6) - if (prefix_match (cp, (struct prefix *)&p)) - { - if (IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6)) - { - if (ifindex == ifp->ifindex) - return ifp; - } - else - return ifp; - } + struct listnode *ifnode; + struct listnode *cnode; + struct interface *ifp; + struct connected *connected; + struct prefix_ipv6 p; + struct prefix *cp; + + p.family = AF_INET6; + p.prefix = *addr; + p.prefixlen = IPV6_MAX_BITLEN; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) { + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + cp = connected->address; + + if (cp->family == AF_INET6) + if (prefix_match(cp, (struct prefix *)&p)) { + if (IN6_IS_ADDR_LINKLOCAL( + &cp->u.prefix6)) { + if (ifindex == ifp->ifindex) + return ifp; + } else + return ifp; + } + } } - } - return NULL; + return NULL; } -struct interface * -if_lookup_by_ipv6_exact (struct in6_addr *addr, ifindex_t ifindex, vrf_id_t vrf_id) +struct interface *if_lookup_by_ipv6_exact(struct in6_addr *addr, + ifindex_t ifindex, vrf_id_t vrf_id) { - struct listnode *ifnode; - struct listnode *cnode; - struct interface *ifp; - struct connected *connected; - struct prefix *cp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist(vrf_id), ifnode, ifp)) - { - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - cp = connected->address; - - if (cp->family == AF_INET6) - if (IPV6_ADDR_SAME (&cp->u.prefix6, addr)) - { - if (IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6)) - { - if (ifindex == ifp->ifindex) - return ifp; - } - else - return ifp; - } + struct listnode *ifnode; + struct listnode *cnode; + struct interface *ifp; + struct connected *connected; + struct prefix *cp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) { + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + cp = connected->address; + + if (cp->family == AF_INET6) + if (IPV6_ADDR_SAME(&cp->u.prefix6, addr)) { + if (IN6_IS_ADDR_LINKLOCAL( + &cp->u.prefix6)) { + if (ifindex == ifp->ifindex) + return ifp; + } else + return ifp; + } + } } - } - return NULL; + return NULL; } -static int -if_get_ipv6_global (struct interface *ifp, struct in6_addr *addr) +static int if_get_ipv6_global(struct interface *ifp, struct in6_addr *addr) { - struct listnode *cnode; - struct connected *connected; - struct prefix *cp; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - cp = connected->address; - - if (cp->family == AF_INET6) - if (! IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6)) - { - memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN); - return 1; - } - } - return 0; + struct listnode *cnode; + struct connected *connected; + struct prefix *cp; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + cp = connected->address; + + if (cp->family == AF_INET6) + if (!IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6)) { + memcpy(addr, &cp->u.prefix6, IPV6_MAX_BYTELEN); + return 1; + } + } + return 0; } -static int -if_get_ipv6_local (struct interface *ifp, struct in6_addr *addr) +static int if_get_ipv6_local(struct interface *ifp, struct in6_addr *addr) { - struct listnode *cnode; - struct connected *connected; - struct prefix *cp; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - cp = connected->address; - - if (cp->family == AF_INET6) - if (IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6)) - { - memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN); - return 1; - } - } - return 0; + struct listnode *cnode; + struct connected *connected; + struct prefix *cp; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + cp = connected->address; + + if (cp->family == AF_INET6) + if (IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6)) { + memcpy(addr, &cp->u.prefix6, IPV6_MAX_BYTELEN); + return 1; + } + } + return 0; } -static int -if_get_ipv4_address (struct interface *ifp, struct in_addr *addr) +static int if_get_ipv4_address(struct interface *ifp, struct in_addr *addr) { - struct listnode *cnode; - struct connected *connected; - struct prefix *cp; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - cp = connected->address; - if ((cp->family == AF_INET) && !ipv4_martian(&(cp->u.prefix4))) - { - *addr = cp->u.prefix4; - return 1; - } - } - return 0; + struct listnode *cnode; + struct connected *connected; + struct prefix *cp; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + cp = connected->address; + if ((cp->family == AF_INET) + && !ipv4_martian(&(cp->u.prefix4))) { + *addr = cp->u.prefix4; + return 1; + } + } + return 0; } -int -bgp_nexthop_set (union sockunion *local, union sockunion *remote, - struct bgp_nexthop *nexthop, struct peer *peer) +int bgp_nexthop_set(union sockunion *local, union sockunion *remote, + struct bgp_nexthop *nexthop, struct peer *peer) { - int ret = 0; - struct interface *ifp = NULL; - - memset (nexthop, 0, sizeof (struct bgp_nexthop)); - - if (!local) - return -1; - if (!remote) - return -1; - - if (local->sa.sa_family == AF_INET) - { - nexthop->v4 = local->sin.sin_addr; - if (peer->update_if) - ifp = if_lookup_by_name (peer->update_if, peer->bgp->vrf_id); - else - ifp = if_lookup_by_ipv4_exact (&local->sin.sin_addr, peer->bgp->vrf_id); - } - if (local->sa.sa_family == AF_INET6) - { - if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr)) - { - if (peer->conf_if || peer->ifname) - ifp = if_lookup_by_name (peer->conf_if ? peer->conf_if : peer->ifname, peer->bgp->vrf_id); + int ret = 0; + struct interface *ifp = NULL; + + memset(nexthop, 0, sizeof(struct bgp_nexthop)); + + if (!local) + return -1; + if (!remote) + return -1; + + if (local->sa.sa_family == AF_INET) { + nexthop->v4 = local->sin.sin_addr; + if (peer->update_if) + ifp = if_lookup_by_name(peer->update_if, + peer->bgp->vrf_id); + else + ifp = if_lookup_by_ipv4_exact(&local->sin.sin_addr, + peer->bgp->vrf_id); } - else if (peer->update_if) - ifp = if_lookup_by_name (peer->update_if, peer->bgp->vrf_id); - else - ifp = if_lookup_by_ipv6_exact (&local->sin6.sin6_addr, - local->sin6.sin6_scope_id, - peer->bgp->vrf_id); - } - - if (!ifp) - return -1; - - nexthop->ifp = ifp; - - /* IPv4 connection, fetch and store IPv6 local address(es) if any. */ - if (local->sa.sa_family == AF_INET) - { - /* IPv6 nexthop*/ - ret = if_get_ipv6_global (ifp, &nexthop->v6_global); - - if (!ret) - { - /* There is no global nexthop. Use link-local address as both the - * global and link-local nexthop. In this scenario, the expectation - * for interop is that the network admin would use a route-map to - * specify the global IPv6 nexthop. - */ - if_get_ipv6_local (ifp, &nexthop->v6_global); - memcpy (&nexthop->v6_local, &nexthop->v6_global, - IPV6_MAX_BYTELEN); - } - else - if_get_ipv6_local (ifp, &nexthop->v6_local); - - if (if_lookup_by_ipv4 (&remote->sin.sin_addr, peer->bgp->vrf_id)) - peer->shared_network = 1; - else - peer->shared_network = 0; - } - - /* IPv6 connection, fetch and store IPv4 local address if any. */ - if (local->sa.sa_family == AF_INET6) - { - struct interface *direct = NULL; - - /* IPv4 nexthop. */ - ret = if_get_ipv4_address(ifp, &nexthop->v4); - if (!ret && peer->local_id.s_addr) - nexthop->v4 = peer->local_id; - - /* Global address*/ - if (! IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr)) - { - memcpy (&nexthop->v6_global, &local->sin6.sin6_addr, - IPV6_MAX_BYTELEN); - - /* If directory connected set link-local address. */ - direct = if_lookup_by_ipv6 (&remote->sin6.sin6_addr, - remote->sin6.sin6_scope_id, peer->bgp->vrf_id); - if (direct) - if_get_ipv6_local (ifp, &nexthop->v6_local); + if (local->sa.sa_family == AF_INET6) { + if (IN6_IS_ADDR_LINKLOCAL(&local->sin6.sin6_addr)) { + if (peer->conf_if || peer->ifname) + ifp = if_lookup_by_name(peer->conf_if + ? peer->conf_if + : peer->ifname, + peer->bgp->vrf_id); + } else if (peer->update_if) + ifp = if_lookup_by_name(peer->update_if, + peer->bgp->vrf_id); + else + ifp = if_lookup_by_ipv6_exact(&local->sin6.sin6_addr, + local->sin6.sin6_scope_id, + peer->bgp->vrf_id); } - else - /* Link-local address. */ - { - ret = if_get_ipv6_global (ifp, &nexthop->v6_global); - - /* If there is no global address. Set link-local address as - global. I know this break RFC specification... */ - /* In this scenario, the expectation for interop is that the - * network admin would use a route-map to specify the global - * IPv6 nexthop. - */ - if (!ret) - memcpy (&nexthop->v6_global, &local->sin6.sin6_addr, - IPV6_MAX_BYTELEN); - /* Always set the link-local address */ - memcpy (&nexthop->v6_local, &local->sin6.sin6_addr, - IPV6_MAX_BYTELEN); + + if (!ifp) + return -1; + + nexthop->ifp = ifp; + + /* IPv4 connection, fetch and store IPv6 local address(es) if any. */ + if (local->sa.sa_family == AF_INET) { + /* IPv6 nexthop*/ + ret = if_get_ipv6_global(ifp, &nexthop->v6_global); + + if (!ret) { + /* There is no global nexthop. Use link-local address as + * both the + * global and link-local nexthop. In this scenario, the + * expectation + * for interop is that the network admin would use a + * route-map to + * specify the global IPv6 nexthop. + */ + if_get_ipv6_local(ifp, &nexthop->v6_global); + memcpy(&nexthop->v6_local, &nexthop->v6_global, + IPV6_MAX_BYTELEN); + } else + if_get_ipv6_local(ifp, &nexthop->v6_local); + + if (if_lookup_by_ipv4(&remote->sin.sin_addr, peer->bgp->vrf_id)) + peer->shared_network = 1; + else + peer->shared_network = 0; } - if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr) || - if_lookup_by_ipv6 (&remote->sin6.sin6_addr, remote->sin6.sin6_scope_id, - peer->bgp->vrf_id)) - peer->shared_network = 1; - else - peer->shared_network = 0; - } + /* IPv6 connection, fetch and store IPv4 local address if any. */ + if (local->sa.sa_family == AF_INET6) { + struct interface *direct = NULL; + + /* IPv4 nexthop. */ + ret = if_get_ipv4_address(ifp, &nexthop->v4); + if (!ret && peer->local_id.s_addr) + nexthop->v4 = peer->local_id; + + /* Global address*/ + if (!IN6_IS_ADDR_LINKLOCAL(&local->sin6.sin6_addr)) { + memcpy(&nexthop->v6_global, &local->sin6.sin6_addr, + IPV6_MAX_BYTELEN); + + /* If directory connected set link-local address. */ + direct = if_lookup_by_ipv6(&remote->sin6.sin6_addr, + remote->sin6.sin6_scope_id, + peer->bgp->vrf_id); + if (direct) + if_get_ipv6_local(ifp, &nexthop->v6_local); + } else + /* Link-local address. */ + { + ret = if_get_ipv6_global(ifp, &nexthop->v6_global); + + /* If there is no global address. Set link-local + address as + global. I know this break RFC specification... */ + /* In this scenario, the expectation for interop is that + * the + * network admin would use a route-map to specify the + * global + * IPv6 nexthop. + */ + if (!ret) + memcpy(&nexthop->v6_global, + &local->sin6.sin6_addr, + IPV6_MAX_BYTELEN); + /* Always set the link-local address */ + memcpy(&nexthop->v6_local, &local->sin6.sin6_addr, + IPV6_MAX_BYTELEN); + } + + if (IN6_IS_ADDR_LINKLOCAL(&local->sin6.sin6_addr) + || if_lookup_by_ipv6(&remote->sin6.sin6_addr, + remote->sin6.sin6_scope_id, + peer->bgp->vrf_id)) + peer->shared_network = 1; + else + peer->shared_network = 0; + } - /* KAME stack specific treatment. */ +/* KAME stack specific treatment. */ #ifdef KAME - if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_global) - && IN6_LINKLOCAL_IFINDEX (nexthop->v6_global)) - { - SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_global, 0); - } - if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_local) - && IN6_LINKLOCAL_IFINDEX (nexthop->v6_local)) - { - SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_local, 0); - } + if (IN6_IS_ADDR_LINKLOCAL(&nexthop->v6_global) + && IN6_LINKLOCAL_IFINDEX(nexthop->v6_global)) { + SET_IN6_LINKLOCAL_IFINDEX(nexthop->v6_global, 0); + } + if (IN6_IS_ADDR_LINKLOCAL(&nexthop->v6_local) + && IN6_LINKLOCAL_IFINDEX(nexthop->v6_local)) { + SET_IN6_LINKLOCAL_IFINDEX(nexthop->v6_local, 0); + } #endif /* KAME */ - /* If we have identified the local interface, there is no error for now. */ - return 0; + /* If we have identified the local interface, there is no error for now. + */ + return 0; } -static struct in6_addr * -bgp_info_to_ipv6_nexthop (struct bgp_info *info) +static struct in6_addr *bgp_info_to_ipv6_nexthop(struct bgp_info *info) { - struct in6_addr *nexthop = NULL; - - /* Only global address nexthop exists. */ - if (info->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) - nexthop = &info->attr->extra->mp_nexthop_global; - - /* If both global and link-local address present. */ - if (info->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) - { - /* Check if route-map is set to prefer global over link-local */ - if (info->attr->extra->mp_nexthop_prefer_global) - nexthop = &info->attr->extra->mp_nexthop_global; - else - { - /* Workaround for Cisco's nexthop bug. */ - if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global) - && info->peer->su_remote->sa.sa_family == AF_INET6) - nexthop = &info->peer->su_remote->sin6.sin6_addr; - else - nexthop = &info->attr->extra->mp_nexthop_local; - } - } - - return nexthop; + struct in6_addr *nexthop = NULL; + + /* Only global address nexthop exists. */ + if (info->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) + nexthop = &info->attr->extra->mp_nexthop_global; + + /* If both global and link-local address present. */ + if (info->attr->extra->mp_nexthop_len + == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { + /* Check if route-map is set to prefer global over link-local */ + if (info->attr->extra->mp_nexthop_prefer_global) + nexthop = &info->attr->extra->mp_nexthop_global; + else { + /* Workaround for Cisco's nexthop bug. */ + if (IN6_IS_ADDR_UNSPECIFIED( + &info->attr->extra->mp_nexthop_global) + && info->peer->su_remote->sa.sa_family == AF_INET6) + nexthop = + &info->peer->su_remote->sin6.sin6_addr; + else + nexthop = &info->attr->extra->mp_nexthop_local; + } + } + + return nexthop; } -static int -bgp_table_map_apply (struct route_map *map, struct prefix *p, - struct bgp_info *info) +static int bgp_table_map_apply(struct route_map *map, struct prefix *p, + struct bgp_info *info) { - if (route_map_apply(map, p, RMAP_BGP, info) != RMAP_DENYMATCH) - return 1; - - if (bgp_debug_zebra(p)) - { - if (p->family == AF_INET) - { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra rmap deny: IPv4 route %s/%d nexthop %s", - inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET, &info->attr->nexthop, buf[1], - sizeof(buf[1]))); - } - if (p->family == AF_INET6) - { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Zebra rmap deny: IPv6 route %s/%d nexthop %s", - inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET6, bgp_info_to_ipv6_nexthop(info), buf[1], - sizeof(buf[1]))); - } - } - return 0; + if (route_map_apply(map, p, RMAP_BGP, info) != RMAP_DENYMATCH) + return 1; + + if (bgp_debug_zebra(p)) { + if (p->family == AF_INET) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug( + "Zebra rmap deny: IPv4 route %s/%d nexthop %s", + inet_ntop(AF_INET, &p->u.prefix4, buf[0], + sizeof(buf[0])), + p->prefixlen, + inet_ntop(AF_INET, &info->attr->nexthop, buf[1], + sizeof(buf[1]))); + } + if (p->family == AF_INET6) { + char buf[2][INET6_ADDRSTRLEN]; + zlog_debug( + "Zebra rmap deny: IPv6 route %s/%d nexthop %s", + inet_ntop(AF_INET6, &p->u.prefix6, buf[0], + sizeof(buf[0])), + p->prefixlen, + inet_ntop(AF_INET6, + bgp_info_to_ipv6_nexthop(info), + buf[1], sizeof(buf[1]))); + } + } + return 0; } -void -bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, - afi_t afi, safi_t safi) +void bgp_zebra_announce(struct prefix *p, struct bgp_info *info, + struct bgp *bgp, afi_t afi, safi_t safi) { - u_int32_t flags; - u_char distance; - struct peer *peer; - struct bgp_info *mpinfo; - size_t oldsize, newsize; - u_int32_t nhcount, metric; - struct bgp_info local_info; - struct bgp_info *info_cp = &local_info; - route_tag_t tag; - - /* Don't try to install if we're not connected to Zebra or Zebra doesn't - * know of this instance. - */ - if (!bgp_install_info_to_zebra (bgp)) - return; - - if ((p->family == AF_INET && - !vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP], bgp->vrf_id)) - || (p->family == AF_INET6 && - !vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP], bgp->vrf_id))) - return; - - if (bgp->main_zebra_update_hold) - return; - - flags = 0; - peer = info->peer; - - if ((info->attr->extra) && (info->attr->extra->tag != 0)) - tag = info->attr->extra->tag; - else - tag = 0; - - /* When we create an aggregate route we must also install a Null0 route in - * the RIB */ - if (info->sub_type == BGP_ROUTE_AGGREGATE) - SET_FLAG (flags, ZEBRA_FLAG_BLACKHOLE); - - if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED || - info->sub_type == BGP_ROUTE_AGGREGATE) - { - SET_FLAG (flags, ZEBRA_FLAG_IBGP); - SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); - } - - if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) - || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) - || bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - - SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); - - nhcount = 1 + bgp_info_mpath_count (info); - - if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)) - { - struct zapi_ipv4 api; - struct in_addr *nexthop; - char buf[2][INET_ADDRSTRLEN]; - int valid_nh_count = 0; - - /* resize nexthop buffer size if necessary */ - if ((oldsize = stream_get_size (bgp_nexthop_buf)) < - (sizeof (struct in_addr *) * nhcount)) - { - newsize = (sizeof (struct in_addr *) * nhcount); - newsize = stream_resize (bgp_nexthop_buf, newsize); - if (newsize == oldsize) - { - zlog_err ("can't resize nexthop buffer"); - return; - } - } - stream_reset (bgp_nexthop_buf); - nexthop = NULL; - - /* Metric is currently based on the best-path only. */ - metric = info->attr->med; - - if (bgp->table_map[afi][safi].name) - { - BGP_INFO_ATTR_BUF_INIT(); - - /* Copy info and attributes, so the route-map apply doesn't modify the - BGP route info. */ - BGP_INFO_ATTR_BUF_COPY(info, info_cp); - if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp)) - { - metric = info_cp->attr->med; - nexthop = &info_cp->attr->nexthop; - - if (info_cp->attr->extra) - tag = info_cp->attr->extra->tag; - } - BGP_INFO_ATTR_BUF_FREE(info_cp); - } - else - { - nexthop = &info->attr->nexthop; - } - - if (nexthop) - { - stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *)); - valid_nh_count++; - } - - for (mpinfo = bgp_info_mpath_first (info); mpinfo; - mpinfo = bgp_info_mpath_next (mpinfo)) - { - nexthop = NULL; - - if (bgp->table_map[afi][safi].name) - { - /* Copy info and attributes, so the route-map apply doesn't modify the - BGP route info. */ - BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp); - if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp)) - nexthop = &info_cp->attr->nexthop; - BGP_INFO_ATTR_BUF_FREE(info_cp); - } - else - { - nexthop = &mpinfo->attr->nexthop; - } - - if (nexthop == NULL) - continue; - - stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *)); - valid_nh_count++; - } - - api.vrf_id = bgp->vrf_id; - api.flags = flags; - api.type = ZEBRA_ROUTE_BGP; - api.instance = 0; - api.message = 0; - api.safi = safi; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - - /* Note that this currently only applies to Null0 routes for aggregates. - * ZEBRA_FLAG_BLACKHOLE signals zapi_ipv4_route to encode a special - * BLACKHOLE nexthop. We want to set api.nexthop_num to zero since we - * do not want to also encode the 0.0.0.0 nexthop for the aggregate route. - */ - if (CHECK_FLAG(flags, ZEBRA_FLAG_BLACKHOLE)) - api.nexthop_num = 0; - else - api.nexthop_num = valid_nh_count; - - api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf); - api.ifindex_num = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = metric; - api.tag = 0; - - if (tag) - { - SET_FLAG (api.message, ZAPI_MESSAGE_TAG); - api.tag = tag; - } - - distance = bgp_distance_apply (p, info, afi, safi, bgp); - if (distance) - { - SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = distance; + u_int32_t flags; + u_char distance; + struct peer *peer; + struct bgp_info *mpinfo; + size_t oldsize, newsize; + u_int32_t nhcount, metric; + struct bgp_info local_info; + struct bgp_info *info_cp = &local_info; + route_tag_t tag; + + /* Don't try to install if we're not connected to Zebra or Zebra doesn't + * know of this instance. + */ + if (!bgp_install_info_to_zebra(bgp)) + return; + + if ((p->family == AF_INET + && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP], + bgp->vrf_id)) + || (p->family == AF_INET6 + && !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP], + bgp->vrf_id))) + return; + + if (bgp->main_zebra_update_hold) + return; + + flags = 0; + peer = info->peer; + + if ((info->attr->extra) && (info->attr->extra->tag != 0)) + tag = info->attr->extra->tag; + else + tag = 0; + + /* When we create an aggregate route we must also install a Null0 route + * in + * the RIB */ + if (info->sub_type == BGP_ROUTE_AGGREGATE) + SET_FLAG(flags, ZEBRA_FLAG_BLACKHOLE); + + if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED + || info->sub_type == BGP_ROUTE_AGGREGATE) { + SET_FLAG(flags, ZEBRA_FLAG_IBGP); + SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); + } + + if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) + || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) + || bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) + + SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); + + nhcount = 1 + bgp_info_mpath_count(info); + + if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)) { + struct zapi_ipv4 api; + struct in_addr *nexthop; + char buf[2][INET_ADDRSTRLEN]; + int valid_nh_count = 0; + + /* resize nexthop buffer size if necessary */ + if ((oldsize = stream_get_size(bgp_nexthop_buf)) + < (sizeof(struct in_addr *) * nhcount)) { + newsize = (sizeof(struct in_addr *) * nhcount); + newsize = stream_resize(bgp_nexthop_buf, newsize); + if (newsize == oldsize) { + zlog_err("can't resize nexthop buffer"); + return; + } + } + stream_reset(bgp_nexthop_buf); + nexthop = NULL; + + /* Metric is currently based on the best-path only. */ + metric = info->attr->med; + + if (bgp->table_map[afi][safi].name) { + BGP_INFO_ATTR_BUF_INIT(); + + /* Copy info and attributes, so the route-map apply + doesn't modify the + BGP route info. */ + BGP_INFO_ATTR_BUF_COPY(info, info_cp); + if (bgp_table_map_apply(bgp->table_map[afi][safi].map, + p, info_cp)) { + metric = info_cp->attr->med; + nexthop = &info_cp->attr->nexthop; + + if (info_cp->attr->extra) + tag = info_cp->attr->extra->tag; + } + BGP_INFO_ATTR_BUF_FREE(info_cp); + } else { + nexthop = &info->attr->nexthop; + } + + if (nexthop) { + stream_put(bgp_nexthop_buf, &nexthop, + sizeof(struct in_addr *)); + valid_nh_count++; + } + + for (mpinfo = bgp_info_mpath_first(info); mpinfo; + mpinfo = bgp_info_mpath_next(mpinfo)) { + nexthop = NULL; + + if (bgp->table_map[afi][safi].name) { + /* Copy info and attributes, so the route-map + apply doesn't modify the + BGP route info. */ + BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp); + if (bgp_table_map_apply( + bgp->table_map[afi][safi].map, p, + info_cp)) + nexthop = &info_cp->attr->nexthop; + BGP_INFO_ATTR_BUF_FREE(info_cp); + } else { + nexthop = &mpinfo->attr->nexthop; + } + + if (nexthop == NULL) + continue; + + stream_put(bgp_nexthop_buf, &nexthop, + sizeof(struct in_addr *)); + valid_nh_count++; + } + + api.vrf_id = bgp->vrf_id; + api.flags = flags; + api.type = ZEBRA_ROUTE_BGP; + api.instance = 0; + api.message = 0; + api.safi = safi; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + + /* Note that this currently only applies to Null0 routes for + * aggregates. + * ZEBRA_FLAG_BLACKHOLE signals zapi_ipv4_route to encode a + * special + * BLACKHOLE nexthop. We want to set api.nexthop_num to zero + * since we + * do not want to also encode the 0.0.0.0 nexthop for the + * aggregate route. + */ + if (CHECK_FLAG(flags, ZEBRA_FLAG_BLACKHOLE)) + api.nexthop_num = 0; + else + api.nexthop_num = valid_nh_count; + + api.nexthop = (struct in_addr **)STREAM_DATA(bgp_nexthop_buf); + api.ifindex_num = 0; + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = metric; + api.tag = 0; + + if (tag) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = tag; + } + + distance = bgp_distance_apply(p, info, afi, safi, bgp); + if (distance) { + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = distance; + } + + if (bgp_debug_zebra(p)) { + int i; + zlog_debug( + "Tx IPv4 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI + " count %d", + (valid_nh_count ? "add" : "delete"), + bgp->vrf_id, inet_ntop(AF_INET, &p->u.prefix4, + buf[0], sizeof(buf[0])), + p->prefixlen, api.metric, api.tag, + api.nexthop_num); + for (i = 0; i < api.nexthop_num; i++) + zlog_debug(" IPv4 [nexthop %d] %s", i + 1, + inet_ntop(AF_INET, api.nexthop[i], + buf[1], sizeof(buf[1]))); + } + + zapi_ipv4_route(valid_nh_count ? ZEBRA_IPV4_ROUTE_ADD + : ZEBRA_IPV4_ROUTE_DELETE, + zclient, (struct prefix_ipv4 *)p, &api); } - if (bgp_debug_zebra(p)) - { - int i; - zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI - " count %d", (valid_nh_count ? "add":"delete"), - bgp->vrf_id, - inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.tag, api.nexthop_num); - for (i = 0; i < api.nexthop_num; i++) - zlog_debug(" IPv4 [nexthop %d] %s", i+1, - inet_ntop(AF_INET, api.nexthop[i], buf[1], sizeof(buf[1]))); - } - - zapi_ipv4_route (valid_nh_count ? ZEBRA_IPV4_ROUTE_ADD: ZEBRA_IPV4_ROUTE_DELETE, - zclient, (struct prefix_ipv4 *) p, &api); - } - - /* We have to think about a IPv6 link-local address curse. */ - if (p->family == AF_INET6 || - (p->family == AF_INET && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))) - { - ifindex_t ifindex; - struct in6_addr *nexthop; - struct zapi_ipv6 api; - int valid_nh_count = 0; - char buf[2][INET6_ADDRSTRLEN]; - - /* resize nexthop buffer size if necessary */ - if ((oldsize = stream_get_size (bgp_nexthop_buf)) < - (sizeof (struct in6_addr *) * nhcount)) - { - newsize = (sizeof (struct in6_addr *) * nhcount); - newsize = stream_resize (bgp_nexthop_buf, newsize); - if (newsize == oldsize) - { - zlog_err ("can't resize nexthop buffer"); - return; - } - } - stream_reset (bgp_nexthop_buf); - - /* resize ifindices buffer size if necessary */ - if ((oldsize = stream_get_size (bgp_ifindices_buf)) < - (sizeof (unsigned int) * nhcount)) - { - newsize = (sizeof (unsigned int) * nhcount); - newsize = stream_resize (bgp_ifindices_buf, newsize); - if (newsize == oldsize) - { - zlog_err ("can't resize nexthop buffer"); - return; - } - } - stream_reset (bgp_ifindices_buf); - - ifindex = 0; - nexthop = NULL; - - assert (info->attr->extra); - - /* Metric is currently based on the best-path only. */ - metric = info->attr->med; - - if (bgp->table_map[afi][safi].name) - { - BGP_INFO_ATTR_BUF_INIT(); - - /* Copy info and attributes, so the route-map apply doesn't modify the - BGP route info. */ - BGP_INFO_ATTR_BUF_COPY(info, info_cp); - if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp)) - { - metric = info_cp->attr->med; - nexthop = bgp_info_to_ipv6_nexthop(info_cp); - - if (info_cp->attr->extra) - tag = info_cp->attr->extra->tag; - } - BGP_INFO_ATTR_BUF_FREE(info_cp); - } - else - { - nexthop = bgp_info_to_ipv6_nexthop(info); - } - - if (nexthop) - { - if (info->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) - if (info->peer->nexthop.ifp) - ifindex = info->peer->nexthop.ifp->ifindex; - - if (!ifindex) - { - if (info->peer->conf_if || info->peer->ifname) - ifindex = if_nametoindex (info->peer->conf_if ? info->peer->conf_if : info->peer->ifname); - else if (info->peer->nexthop.ifp) - ifindex = info->peer->nexthop.ifp->ifindex; - } - stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *)); - stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int)); - valid_nh_count++; - } - - for (mpinfo = bgp_info_mpath_first (info); mpinfo; - mpinfo = bgp_info_mpath_next (mpinfo)) - { - ifindex = 0; - nexthop = NULL; - - if (bgp->table_map[afi][safi].name) - { - /* Copy info and attributes, so the route-map apply doesn't modify the - BGP route info. */ - BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp); - if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp)) - nexthop = bgp_info_to_ipv6_nexthop(info_cp); - BGP_INFO_ATTR_BUF_FREE(info_cp); - } - else - { - nexthop = bgp_info_to_ipv6_nexthop(mpinfo); - } - - if (nexthop == NULL) - continue; - - if (mpinfo->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) - if (mpinfo->peer->nexthop.ifp) - ifindex = mpinfo->peer->nexthop.ifp->ifindex; - - if (!ifindex) - { - if (mpinfo->peer->conf_if || mpinfo->peer->ifname) - ifindex = ifname2ifindex (mpinfo->peer->conf_if ? mpinfo->peer->conf_if : mpinfo->peer->ifname, bgp->vrf_id); - else if (mpinfo->peer->nexthop.ifp) - ifindex = mpinfo->peer->nexthop.ifp->ifindex; - } - if (ifindex == 0) - continue; - - stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *)); - stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int)); - valid_nh_count++; - } - - /* Make Zebra API structure. */ - api.vrf_id = bgp->vrf_id; - api.flags = flags; - api.type = ZEBRA_ROUTE_BGP; - api.instance = 0; - api.message = 0; - api.safi = safi; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - - /* Note that this currently only applies to Null0 routes for aggregates. - * ZEBRA_FLAG_BLACKHOLE signals zapi_ipv6_route to encode a special - * BLACKHOLE nexthop. We want to set api.nexthop_num to zero since we - * do not want to also encode the :: nexthop for the aggregate route. - */ - if (CHECK_FLAG(flags, ZEBRA_FLAG_BLACKHOLE)) - api.nexthop_num = 0; - else - api.nexthop_num = valid_nh_count; - - api.nexthop = (struct in6_addr **)STREAM_DATA (bgp_nexthop_buf); - SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = valid_nh_count; - api.ifindex = (ifindex_t *)STREAM_DATA (bgp_ifindices_buf); - SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = metric; - api.tag = 0; - - if (tag) - { - SET_FLAG (api.message, ZAPI_MESSAGE_TAG); - api.tag = tag; - } - - distance = bgp_distance_apply (p, info, afi, safi, bgp); - if (distance) - { - SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = distance; - } - - if (p->family == AF_INET) - { - if (bgp_debug_zebra(p)) - { - int i; - zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI, - valid_nh_count ? "add" : "delete", bgp->vrf_id, - inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.tag); - for (i = 0; i < api.nexthop_num; i++) - zlog_debug(" IPv6 [nexthop %d] %s", i+1, - inet_ntop(AF_INET6, api.nexthop[i], buf[1], sizeof(buf[1]))); - } - - if (valid_nh_count) - zapi_ipv4_route_ipv6_nexthop (ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD, - zclient, (struct prefix_ipv4 *) p, - (struct zapi_ipv6 *)&api); - else - zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, - zclient, (struct prefix_ipv4 *) p, (struct zapi_ipv4 *)&api); - } - else - { - if (bgp_debug_zebra(p)) - { - int i; - zlog_debug("Tx IPv6 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI, - valid_nh_count ? "add" : "delete", bgp->vrf_id, - inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.tag); - for (i = 0; i < api.nexthop_num; i++) - zlog_debug(" IPv6 [nexthop %d] %s", i+1, - inet_ntop(AF_INET6, api.nexthop[i], buf[1], sizeof(buf[1]))); - } - - zapi_ipv6_route (valid_nh_count ? - ZEBRA_IPV6_ROUTE_ADD : ZEBRA_IPV6_ROUTE_DELETE, - zclient, (struct prefix_ipv6 *) p, NULL, &api); - } - } + /* We have to think about a IPv6 link-local address curse. */ + if (p->family == AF_INET6 + || (p->family == AF_INET && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))) { + ifindex_t ifindex; + struct in6_addr *nexthop; + struct zapi_ipv6 api; + int valid_nh_count = 0; + char buf[2][INET6_ADDRSTRLEN]; + + /* resize nexthop buffer size if necessary */ + if ((oldsize = stream_get_size(bgp_nexthop_buf)) + < (sizeof(struct in6_addr *) * nhcount)) { + newsize = (sizeof(struct in6_addr *) * nhcount); + newsize = stream_resize(bgp_nexthop_buf, newsize); + if (newsize == oldsize) { + zlog_err("can't resize nexthop buffer"); + return; + } + } + stream_reset(bgp_nexthop_buf); + + /* resize ifindices buffer size if necessary */ + if ((oldsize = stream_get_size(bgp_ifindices_buf)) + < (sizeof(unsigned int) * nhcount)) { + newsize = (sizeof(unsigned int) * nhcount); + newsize = stream_resize(bgp_ifindices_buf, newsize); + if (newsize == oldsize) { + zlog_err("can't resize nexthop buffer"); + return; + } + } + stream_reset(bgp_ifindices_buf); + + ifindex = 0; + nexthop = NULL; + + assert(info->attr->extra); + + /* Metric is currently based on the best-path only. */ + metric = info->attr->med; + + if (bgp->table_map[afi][safi].name) { + BGP_INFO_ATTR_BUF_INIT(); + + /* Copy info and attributes, so the route-map apply + doesn't modify the + BGP route info. */ + BGP_INFO_ATTR_BUF_COPY(info, info_cp); + if (bgp_table_map_apply(bgp->table_map[afi][safi].map, + p, info_cp)) { + metric = info_cp->attr->med; + nexthop = bgp_info_to_ipv6_nexthop(info_cp); + + if (info_cp->attr->extra) + tag = info_cp->attr->extra->tag; + } + BGP_INFO_ATTR_BUF_FREE(info_cp); + } else { + nexthop = bgp_info_to_ipv6_nexthop(info); + } + + if (nexthop) { + if (info->attr->extra->mp_nexthop_len + == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) + if (info->peer->nexthop.ifp) + ifindex = info->peer->nexthop.ifp + ->ifindex; + + if (!ifindex) { + if (info->peer->conf_if || info->peer->ifname) + ifindex = if_nametoindex( + info->peer->conf_if + ? info->peer->conf_if + : info->peer->ifname); + else if (info->peer->nexthop.ifp) + ifindex = info->peer->nexthop.ifp + ->ifindex; + } + stream_put(bgp_nexthop_buf, &nexthop, + sizeof(struct in6_addr *)); + stream_put(bgp_ifindices_buf, &ifindex, + sizeof(unsigned int)); + valid_nh_count++; + } + + for (mpinfo = bgp_info_mpath_first(info); mpinfo; + mpinfo = bgp_info_mpath_next(mpinfo)) { + ifindex = 0; + nexthop = NULL; + + if (bgp->table_map[afi][safi].name) { + /* Copy info and attributes, so the route-map + apply doesn't modify the + BGP route info. */ + BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp); + if (bgp_table_map_apply( + bgp->table_map[afi][safi].map, p, + info_cp)) + nexthop = bgp_info_to_ipv6_nexthop( + info_cp); + BGP_INFO_ATTR_BUF_FREE(info_cp); + } else { + nexthop = bgp_info_to_ipv6_nexthop(mpinfo); + } + + if (nexthop == NULL) + continue; + + if (mpinfo->attr->extra->mp_nexthop_len + == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) + if (mpinfo->peer->nexthop.ifp) + ifindex = mpinfo->peer->nexthop.ifp + ->ifindex; + + if (!ifindex) { + if (mpinfo->peer->conf_if + || mpinfo->peer->ifname) + ifindex = ifname2ifindex( + mpinfo->peer->conf_if + ? mpinfo->peer->conf_if + : mpinfo->peer->ifname, + bgp->vrf_id); + else if (mpinfo->peer->nexthop.ifp) + ifindex = mpinfo->peer->nexthop.ifp + ->ifindex; + } + if (ifindex == 0) + continue; + + stream_put(bgp_nexthop_buf, &nexthop, + sizeof(struct in6_addr *)); + stream_put(bgp_ifindices_buf, &ifindex, + sizeof(unsigned int)); + valid_nh_count++; + } + + /* Make Zebra API structure. */ + api.vrf_id = bgp->vrf_id; + api.flags = flags; + api.type = ZEBRA_ROUTE_BGP; + api.instance = 0; + api.message = 0; + api.safi = safi; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + + /* Note that this currently only applies to Null0 routes for + * aggregates. + * ZEBRA_FLAG_BLACKHOLE signals zapi_ipv6_route to encode a + * special + * BLACKHOLE nexthop. We want to set api.nexthop_num to zero + * since we + * do not want to also encode the :: nexthop for the aggregate + * route. + */ + if (CHECK_FLAG(flags, ZEBRA_FLAG_BLACKHOLE)) + api.nexthop_num = 0; + else + api.nexthop_num = valid_nh_count; + + api.nexthop = (struct in6_addr **)STREAM_DATA(bgp_nexthop_buf); + SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); + api.ifindex_num = valid_nh_count; + api.ifindex = (ifindex_t *)STREAM_DATA(bgp_ifindices_buf); + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = metric; + api.tag = 0; + + if (tag) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = tag; + } + + distance = bgp_distance_apply(p, info, afi, safi, bgp); + if (distance) { + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = distance; + } + + if (p->family == AF_INET) { + if (bgp_debug_zebra(p)) { + int i; + zlog_debug( + "Tx IPv4 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI, + valid_nh_count ? "add" : "delete", + bgp->vrf_id, + inet_ntop(AF_INET, &p->u.prefix4, + buf[0], sizeof(buf[0])), + p->prefixlen, api.metric, api.tag); + for (i = 0; i < api.nexthop_num; i++) + zlog_debug(" IPv6 [nexthop %d] %s", + i + 1, + inet_ntop(AF_INET6, + api.nexthop[i], + buf[1], + sizeof(buf[1]))); + } + + if (valid_nh_count) + zapi_ipv4_route_ipv6_nexthop( + ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD, + zclient, (struct prefix_ipv4 *)p, + (struct zapi_ipv6 *)&api); + else + zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, + zclient, + (struct prefix_ipv4 *)p, + (struct zapi_ipv4 *)&api); + } else { + if (bgp_debug_zebra(p)) { + int i; + zlog_debug( + "Tx IPv6 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI, + valid_nh_count ? "add" : "delete", + bgp->vrf_id, + inet_ntop(AF_INET6, &p->u.prefix6, + buf[0], sizeof(buf[0])), + p->prefixlen, api.metric, api.tag); + for (i = 0; i < api.nexthop_num; i++) + zlog_debug(" IPv6 [nexthop %d] %s", + i + 1, + inet_ntop(AF_INET6, + api.nexthop[i], + buf[1], + sizeof(buf[1]))); + } + + zapi_ipv6_route( + valid_nh_count ? ZEBRA_IPV6_ROUTE_ADD + : ZEBRA_IPV6_ROUTE_DELETE, + zclient, (struct prefix_ipv6 *)p, NULL, &api); + } + } } /* Announce all routes of a table to zebra */ -void -bgp_zebra_announce_table (struct bgp *bgp, afi_t afi, safi_t safi) +void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) { - struct bgp_node *rn; - struct bgp_table *table; - struct bgp_info *ri; - - /* Don't try to install if we're not connected to Zebra or Zebra doesn't - * know of this instance. - */ - if (!bgp_install_info_to_zebra (bgp)) - return; - - table = bgp->rib[afi][safi]; - if (!table) return; - - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - for (ri = rn->info; ri; ri = ri->next) - if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) - && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_NORMAL) - bgp_zebra_announce (&rn->p, ri, bgp, afi, safi); + struct bgp_node *rn; + struct bgp_table *table; + struct bgp_info *ri; + + /* Don't try to install if we're not connected to Zebra or Zebra doesn't + * know of this instance. + */ + if (!bgp_install_info_to_zebra(bgp)) + return; + + table = bgp->rib[afi][safi]; + if (!table) + return; + + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) + for (ri = rn->info; ri; ri = ri->next) + if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED) + && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_NORMAL) + bgp_zebra_announce(&rn->p, ri, bgp, afi, safi); } -void -bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi) +void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi) { - u_int32_t flags; - struct peer *peer; - - peer = info->peer; - assert(peer); - - /* Don't try to install if we're not connected to Zebra or Zebra doesn't - * know of this instance. - */ - if (!bgp_install_info_to_zebra (peer->bgp)) - return; - - if ((p->family == AF_INET && - !vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP], peer->bgp->vrf_id)) - || (p->family == AF_INET6 && - !vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP], peer->bgp->vrf_id))) - return; - - flags = 0; - - if (peer->sort == BGP_PEER_IBGP) - { - SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); - SET_FLAG (flags, ZEBRA_FLAG_IBGP); - } - - if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) - || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) - || bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); - - if (p->family == AF_INET) - { - struct zapi_ipv4 api; - - api.vrf_id = peer->bgp->vrf_id; - api.flags = flags; - - api.type = ZEBRA_ROUTE_BGP; - api.instance = 0; - api.message = 0; - api.safi = safi; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.nexthop = NULL; - api.ifindex_num = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = info->attr->med; - api.tag = 0; - - if ((info->attr->extra) && (info->attr->extra->tag != 0)) - { - SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = info->attr->extra->tag; - } - - if (bgp_debug_zebra(p)) - { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Tx IPv4 route delete VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI, - peer->bgp->vrf_id, - inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.tag); + u_int32_t flags; + struct peer *peer; + + peer = info->peer; + assert(peer); + + /* Don't try to install if we're not connected to Zebra or Zebra doesn't + * know of this instance. + */ + if (!bgp_install_info_to_zebra(peer->bgp)) + return; + + if ((p->family == AF_INET + && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP], + peer->bgp->vrf_id)) + || (p->family == AF_INET6 + && !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP], + peer->bgp->vrf_id))) + return; + + flags = 0; + + if (peer->sort == BGP_PEER_IBGP) { + SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(flags, ZEBRA_FLAG_IBGP); } - zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, - (struct prefix_ipv4 *) p, &api); - } - /* We have to think about a IPv6 link-local address curse. */ - if (p->family == AF_INET6) - { - struct zapi_ipv6 api; - - assert (info->attr->extra); - - api.vrf_id = peer->bgp->vrf_id; - api.flags = flags; - api.type = ZEBRA_ROUTE_BGP; - api.instance = 0; - api.message = 0; - api.safi = safi; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.nexthop = NULL; - api.ifindex_num = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = info->attr->med; - api.tag = 0; - - if ((info->attr->extra) && (info->attr->extra->tag != 0)) - { - SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = info->attr->extra->tag; - } - - if (bgp_debug_zebra(p)) - { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Tx IPv6 route delete VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI, - peer->bgp->vrf_id, - inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.tag); + if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) + || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) + || bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) + SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); + + if (p->family == AF_INET) { + struct zapi_ipv4 api; + + api.vrf_id = peer->bgp->vrf_id; + api.flags = flags; + + api.type = ZEBRA_ROUTE_BGP; + api.instance = 0; + api.message = 0; + api.safi = safi; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 0; + api.nexthop = NULL; + api.ifindex_num = 0; + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = info->attr->med; + api.tag = 0; + + if ((info->attr->extra) && (info->attr->extra->tag != 0)) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = info->attr->extra->tag; + } + + if (bgp_debug_zebra(p)) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug( + "Tx IPv4 route delete VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI, + peer->bgp->vrf_id, + inet_ntop(AF_INET, &p->u.prefix4, buf[0], + sizeof(buf[0])), + p->prefixlen, api.metric, api.tag); + } + + zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, + (struct prefix_ipv4 *)p, &api); + } + /* We have to think about a IPv6 link-local address curse. */ + if (p->family == AF_INET6) { + struct zapi_ipv6 api; + + assert(info->attr->extra); + + api.vrf_id = peer->bgp->vrf_id; + api.flags = flags; + api.type = ZEBRA_ROUTE_BGP; + api.instance = 0; + api.message = 0; + api.safi = safi; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 0; + api.nexthop = NULL; + api.ifindex_num = 0; + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = info->attr->med; + api.tag = 0; + + if ((info->attr->extra) && (info->attr->extra->tag != 0)) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = info->attr->extra->tag; + } + + if (bgp_debug_zebra(p)) { + char buf[2][INET6_ADDRSTRLEN]; + zlog_debug( + "Tx IPv6 route delete VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI, + peer->bgp->vrf_id, + inet_ntop(AF_INET6, &p->u.prefix6, buf[0], + sizeof(buf[0])), + p->prefixlen, api.metric, api.tag); + } + + zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, + (struct prefix_ipv6 *)p, NULL, &api); } - - zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, - (struct prefix_ipv6 *) p, NULL, &api); - } } -struct bgp_redist * -bgp_redist_lookup (struct bgp *bgp, afi_t afi, u_char type, u_short instance) +struct bgp_redist *bgp_redist_lookup(struct bgp *bgp, afi_t afi, u_char type, + u_short instance) { - struct list *red_list; - struct listnode *node; - struct bgp_redist *red; + struct list *red_list; + struct listnode *node; + struct bgp_redist *red; - red_list = bgp->redist[afi][type]; - if (!red_list) - return(NULL); + red_list = bgp->redist[afi][type]; + if (!red_list) + return (NULL); - for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) - if (red->instance == instance) - return red; + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) + if (red->instance == instance) + return red; - return NULL; + return NULL; } -struct bgp_redist * -bgp_redist_add (struct bgp *bgp, afi_t afi, u_char type, u_short instance) +struct bgp_redist *bgp_redist_add(struct bgp *bgp, afi_t afi, u_char type, + u_short instance) { - struct list *red_list; - struct bgp_redist *red; + struct list *red_list; + struct bgp_redist *red; - red = bgp_redist_lookup(bgp, afi, type, instance); - if (red) - return red; + red = bgp_redist_lookup(bgp, afi, type, instance); + if (red) + return red; - if (!bgp->redist[afi][type]) - bgp->redist[afi][type] = list_new(); + if (!bgp->redist[afi][type]) + bgp->redist[afi][type] = list_new(); - red_list = bgp->redist[afi][type]; - red = (struct bgp_redist *)XCALLOC(MTYPE_BGP_REDIST, sizeof(struct bgp_redist)); - red->instance = instance; + red_list = bgp->redist[afi][type]; + red = (struct bgp_redist *)XCALLOC(MTYPE_BGP_REDIST, + sizeof(struct bgp_redist)); + red->instance = instance; - listnode_add(red_list, red); + listnode_add(red_list, red); - return red; + return red; } -static void -bgp_redist_del (struct bgp *bgp, afi_t afi, u_char type, u_short instance) +static void bgp_redist_del(struct bgp *bgp, afi_t afi, u_char type, + u_short instance) { - struct bgp_redist *red; - - red = bgp_redist_lookup(bgp, afi, type, instance); - - if (red) - { - listnode_delete(bgp->redist[afi][type], red); - XFREE (MTYPE_BGP_REDIST, red); - if (!bgp->redist[afi][type]->count) - { - list_free(bgp->redist[afi][type]); - bgp->redist[afi][type] = NULL; - } - } + struct bgp_redist *red; + + red = bgp_redist_lookup(bgp, afi, type, instance); + + if (red) { + listnode_delete(bgp->redist[afi][type], red); + XFREE(MTYPE_BGP_REDIST, red); + if (!bgp->redist[afi][type]->count) { + list_free(bgp->redist[afi][type]); + bgp->redist[afi][type] = NULL; + } + } } /* Other routes redistribution into BGP. */ -int -bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type, u_short instance) +int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type, u_short instance) { - /* Return if already redistribute flag is set. */ - if (instance) - { - if (redist_check_instance(&zclient->mi_redist[afi][type], instance)) - return CMD_WARNING; + /* Return if already redistribute flag is set. */ + if (instance) { + if (redist_check_instance(&zclient->mi_redist[afi][type], + instance)) + return CMD_WARNING; - redist_add_instance(&zclient->mi_redist[afi][type], instance); - } - else - { - if (vrf_bitmap_check (zclient->redist[afi][type], bgp->vrf_id)) - return CMD_WARNING; + redist_add_instance(&zclient->mi_redist[afi][type], instance); + } else { + if (vrf_bitmap_check(zclient->redist[afi][type], bgp->vrf_id)) + return CMD_WARNING; #if ENABLE_BGP_VNC - if (bgp->vrf_id == VRF_DEFAULT && - type == ZEBRA_ROUTE_VNC_DIRECT) { - vnc_export_bgp_enable(bgp, afi); /* only enables if mode bits cfg'd */ - } + if (bgp->vrf_id == VRF_DEFAULT + && type == ZEBRA_ROUTE_VNC_DIRECT) { + vnc_export_bgp_enable( + bgp, afi); /* only enables if mode bits cfg'd */ + } #endif - vrf_bitmap_set (zclient->redist[afi][type], bgp->vrf_id); - } + vrf_bitmap_set(zclient->redist[afi][type], bgp->vrf_id); + } - /* Don't try to register if we're not connected to Zebra or Zebra doesn't - * know of this instance. - */ - if (!bgp_install_info_to_zebra (bgp)) - return CMD_WARNING; + /* Don't try to register if we're not connected to Zebra or Zebra + * doesn't + * know of this instance. + */ + if (!bgp_install_info_to_zebra(bgp)) + return CMD_WARNING; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Tx redistribute add VRF %u afi %d %s %d", - bgp->vrf_id, afi, - zebra_route_string(type), instance); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Tx redistribute add VRF %u afi %d %s %d", + bgp->vrf_id, afi, zebra_route_string(type), + instance); - /* Send distribute add message to zebra. */ - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, - instance, bgp->vrf_id); + /* Send distribute add message to zebra. */ + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, + instance, bgp->vrf_id); - return CMD_SUCCESS; + return CMD_SUCCESS; } -int -bgp_redistribute_resend (struct bgp *bgp, afi_t afi, int type, u_short instance) +int bgp_redistribute_resend(struct bgp *bgp, afi_t afi, int type, + u_short instance) { - /* Don't try to send if we're not connected to Zebra or Zebra doesn't - * know of this instance. - */ - if (!bgp_install_info_to_zebra (bgp)) - return -1; - - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Tx redistribute del/add VRF %u afi %d %s %d", - bgp->vrf_id, afi, - zebra_route_string(type), instance); - - /* Send distribute add message to zebra. */ - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, type, - instance, bgp->vrf_id); - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, - instance, bgp->vrf_id); - - return 0; + /* Don't try to send if we're not connected to Zebra or Zebra doesn't + * know of this instance. + */ + if (!bgp_install_info_to_zebra(bgp)) + return -1; + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Tx redistribute del/add VRF %u afi %d %s %d", + bgp->vrf_id, afi, zebra_route_string(type), + instance); + + /* Send distribute add message to zebra. */ + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, type, + instance, bgp->vrf_id); + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, + instance, bgp->vrf_id); + + return 0; } /* Redistribute with route-map specification. */ -int -bgp_redistribute_rmap_set (struct bgp_redist *red, const char *name) +int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name) { - if (red->rmap.name - && (strcmp (red->rmap.name, name) == 0)) - return 0; + if (red->rmap.name && (strcmp(red->rmap.name, name) == 0)) + return 0; - if (red->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name); - red->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); - red->rmap.map = route_map_lookup_by_name (name); + if (red->rmap.name) + XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name); + red->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); + red->rmap.map = route_map_lookup_by_name(name); - return 1; + return 1; } /* Redistribute with metric specification. */ -int -bgp_redistribute_metric_set (struct bgp *bgp, struct bgp_redist *red, afi_t afi, - int type, u_int32_t metric) +int bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red, + afi_t afi, int type, u_int32_t metric) { - struct bgp_node *rn; - struct bgp_info *ri; - - if (red->redist_metric_flag - && red->redist_metric == metric) - return 0; - - red->redist_metric_flag = 1; - red->redist_metric = metric; - - for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn)) - { - for (ri = rn->info; ri; ri = ri->next) - { - if (ri->sub_type == BGP_ROUTE_REDISTRIBUTE && - ri->type == type && - ri->instance == red->instance) - { - struct attr *old_attr; - struct attr new_attr; - struct attr_extra new_extra; - - new_attr.extra = &new_extra; - bgp_attr_dup (&new_attr, ri->attr); - new_attr.med = red->redist_metric; - old_attr = ri->attr; - ri->attr = bgp_attr_intern (&new_attr); - bgp_attr_unintern (&old_attr); - - bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED); - bgp_process(bgp, rn, afi, SAFI_UNICAST); - } - } - } - - return 1; + struct bgp_node *rn; + struct bgp_info *ri; + + if (red->redist_metric_flag && red->redist_metric == metric) + return 0; + + red->redist_metric_flag = 1; + red->redist_metric = metric; + + for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; + rn = bgp_route_next(rn)) { + for (ri = rn->info; ri; ri = ri->next) { + if (ri->sub_type == BGP_ROUTE_REDISTRIBUTE + && ri->type == type + && ri->instance == red->instance) { + struct attr *old_attr; + struct attr new_attr; + struct attr_extra new_extra; + + new_attr.extra = &new_extra; + bgp_attr_dup(&new_attr, ri->attr); + new_attr.med = red->redist_metric; + old_attr = ri->attr; + ri->attr = bgp_attr_intern(&new_attr); + bgp_attr_unintern(&old_attr); + + bgp_info_set_flag(rn, ri, + BGP_INFO_ATTR_CHANGED); + bgp_process(bgp, rn, afi, SAFI_UNICAST); + } + } + } + + return 1; } /* Unset redistribution. */ -int -bgp_redistribute_unreg (struct bgp *bgp, afi_t afi, int type, u_short instance) +int bgp_redistribute_unreg(struct bgp *bgp, afi_t afi, int type, + u_short instance) { - struct bgp_redist *red; - - red = bgp_redist_lookup(bgp, afi, type, instance); - if (!red) - return CMD_SUCCESS; - - /* Return if zebra connection is disabled. */ - if (instance) - { - if (!redist_check_instance(&zclient->mi_redist[afi][type], instance)) - return CMD_WARNING; - redist_del_instance(&zclient->mi_redist[afi][type], instance); - } - else - { - if (! vrf_bitmap_check (zclient->redist[afi][type], bgp->vrf_id)) - return CMD_WARNING; - vrf_bitmap_unset (zclient->redist[afi][type], bgp->vrf_id); - } + struct bgp_redist *red; + + red = bgp_redist_lookup(bgp, afi, type, instance); + if (!red) + return CMD_SUCCESS; + + /* Return if zebra connection is disabled. */ + if (instance) { + if (!redist_check_instance(&zclient->mi_redist[afi][type], + instance)) + return CMD_WARNING; + redist_del_instance(&zclient->mi_redist[afi][type], instance); + } else { + if (!vrf_bitmap_check(zclient->redist[afi][type], bgp->vrf_id)) + return CMD_WARNING; + vrf_bitmap_unset(zclient->redist[afi][type], bgp->vrf_id); + } #if ENABLE_BGP_VNC - if (bgp->vrf_id == VRF_DEFAULT && - type == ZEBRA_ROUTE_VNC_DIRECT) { - vnc_export_bgp_disable(bgp, afi); - } + if (bgp->vrf_id == VRF_DEFAULT && type == ZEBRA_ROUTE_VNC_DIRECT) { + vnc_export_bgp_disable(bgp, afi); + } #endif - if (bgp_install_info_to_zebra (bgp)) - { - /* Send distribute delete message to zebra. */ - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Tx redistribute del VRF %u afi %d %s %d", - bgp->vrf_id, afi, zebra_route_string(type), instance); - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, type, instance, - bgp->vrf_id); - } - - /* Withdraw redistributed routes from current BGP's routing table. */ - bgp_redistribute_withdraw (bgp, afi, type, instance); - - return CMD_SUCCESS; + if (bgp_install_info_to_zebra(bgp)) { + /* Send distribute delete message to zebra. */ + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Tx redistribute del VRF %u afi %d %s %d", + bgp->vrf_id, afi, zebra_route_string(type), + instance); + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, + type, instance, bgp->vrf_id); + } + + /* Withdraw redistributed routes from current BGP's routing table. */ + bgp_redistribute_withdraw(bgp, afi, type, instance); + + return CMD_SUCCESS; } /* Unset redistribution. */ -int -bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type, u_short instance) +int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type, + u_short instance) { - struct bgp_redist *red; + struct bgp_redist *red; - red = bgp_redist_lookup(bgp, afi, type, instance); - if (!red) - return CMD_SUCCESS; + red = bgp_redist_lookup(bgp, afi, type, instance); + if (!red) + return CMD_SUCCESS; - bgp_redistribute_unreg(bgp, afi, type, instance); + bgp_redistribute_unreg(bgp, afi, type, instance); - /* Unset route-map. */ - if (red->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name); - red->rmap.name = NULL; - red->rmap.map = NULL; + /* Unset route-map. */ + if (red->rmap.name) + XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name); + red->rmap.name = NULL; + red->rmap.map = NULL; - /* Unset metric. */ - red->redist_metric_flag = 0; - red->redist_metric = 0; + /* Unset metric. */ + red->redist_metric_flag = 0; + red->redist_metric = 0; - bgp_redist_del(bgp, afi, type, instance); + bgp_redist_del(bgp, afi, type, instance); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Update redistribute vrf bitmap during triggers like restart networking or delete/add VRFs */ -void -bgp_update_redist_vrf_bitmaps (struct bgp *bgp, vrf_id_t old_vrf_id) +void bgp_update_redist_vrf_bitmaps(struct bgp *bgp, vrf_id_t old_vrf_id) { - int i; - afi_t afi; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (vrf_bitmap_check (zclient->redist[afi][i], old_vrf_id)) - { - vrf_bitmap_unset (zclient->redist[afi][i], old_vrf_id); - vrf_bitmap_set (zclient->redist[afi][i], bgp->vrf_id); - } - return; + int i; + afi_t afi; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (vrf_bitmap_check(zclient->redist[afi][i], + old_vrf_id)) { + vrf_bitmap_unset(zclient->redist[afi][i], + old_vrf_id); + vrf_bitmap_set(zclient->redist[afi][i], + bgp->vrf_id); + } + return; } -void -bgp_zclient_reset (void) +void bgp_zclient_reset(void) { - zclient_reset (zclient); + zclient_reset(zclient); } /* Register this instance with Zebra. Invoked upon connect (for * default instance) and when other VRFs are learnt (or created and * already learnt). */ -void -bgp_zebra_instance_register (struct bgp *bgp) +void bgp_zebra_instance_register(struct bgp *bgp) { - /* Don't try to register if we're not connected to Zebra */ - if (!zclient || zclient->sock < 0) - return; + /* Don't try to register if we're not connected to Zebra */ + if (!zclient || zclient->sock < 0) + return; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Registering VRF %u", bgp->vrf_id); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Registering VRF %u", bgp->vrf_id); - /* Register for router-id, interfaces, redistributed routes. */ - zclient_send_reg_requests (zclient, bgp->vrf_id); + /* Register for router-id, interfaces, redistributed routes. */ + zclient_send_reg_requests(zclient, bgp->vrf_id); } /* Deregister this instance with Zebra. Invoked upon the instance * being deleted (default or VRF) and it is already registered. */ -void -bgp_zebra_instance_deregister (struct bgp *bgp) +void bgp_zebra_instance_deregister(struct bgp *bgp) { - /* Don't try to deregister if we're not connected to Zebra */ - if (zclient->sock < 0) - return; + /* Don't try to deregister if we're not connected to Zebra */ + if (zclient->sock < 0) + return; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Deregistering VRF %u", bgp->vrf_id); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Deregistering VRF %u", bgp->vrf_id); - /* Deregister for router-id, interfaces, redistributed routes. */ - zclient_send_dereg_requests (zclient, bgp->vrf_id); + /* Deregister for router-id, interfaces, redistributed routes. */ + zclient_send_dereg_requests(zclient, bgp->vrf_id); } -void -bgp_zebra_initiate_radv (struct bgp *bgp, struct peer *peer) +void bgp_zebra_initiate_radv(struct bgp *bgp, struct peer *peer) { - int ra_interval = BGP_UNNUM_DEFAULT_RA_INTERVAL; + int ra_interval = BGP_UNNUM_DEFAULT_RA_INTERVAL; - /* Don't try to initiate if we're not connected to Zebra */ - if (zclient->sock < 0) - return; + /* Don't try to initiate if we're not connected to Zebra */ + if (zclient->sock < 0) + return; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("%u: Initiating RA for peer %s", bgp->vrf_id, peer->host); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%u: Initiating RA for peer %s", bgp->vrf_id, + peer->host); - zclient_send_interface_radv_req (zclient, bgp->vrf_id, peer->ifp, 1, ra_interval); + zclient_send_interface_radv_req(zclient, bgp->vrf_id, peer->ifp, 1, + ra_interval); } -void -bgp_zebra_terminate_radv (struct bgp *bgp, struct peer *peer) +void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer) { - /* Don't try to terminate if we're not connected to Zebra */ - if (zclient->sock < 0) - return; + /* Don't try to terminate if we're not connected to Zebra */ + if (zclient->sock < 0) + return; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("%u: Terminating RA for peer %s", bgp->vrf_id, peer->host); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%u: Terminating RA for peer %s", bgp->vrf_id, + peer->host); - zclient_send_interface_radv_req (zclient, bgp->vrf_id, peer->ifp, 0, 0); + zclient_send_interface_radv_req(zclient, bgp->vrf_id, peer->ifp, 0, 0); } /* BGP has established connection with Zebra. */ -static void -bgp_zebra_connected (struct zclient *zclient) +static void bgp_zebra_connected(struct zclient *zclient) { - struct bgp *bgp; + struct bgp *bgp; - zclient_num_connects++; /* increment even if not responding */ + zclient_num_connects++; /* increment even if not responding */ - /* At this point, we may or may not have BGP instances configured, but - * we're only interested in the default VRF (others wouldn't have learnt - * the VRF from Zebra yet.) - */ - bgp = bgp_get_default(); - if (!bgp) - return; + /* At this point, we may or may not have BGP instances configured, but + * we're only interested in the default VRF (others wouldn't have learnt + * the VRF from Zebra yet.) + */ + bgp = bgp_get_default(); + if (!bgp) + return; - bgp_zebra_instance_register (bgp); + bgp_zebra_instance_register(bgp); - /* Send the client registration */ - bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); + /* Send the client registration */ + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); - /* TODO - What if we have peers and networks configured, do we have to - * kick-start them? - */ + /* TODO - What if we have peers and networks configured, do we have to + * kick-start them? + */ } -void -bgp_zebra_init (struct thread_master *master) +void bgp_zebra_init(struct thread_master *master) { - zclient_num_connects = 0; - - /* Set default values. */ - zclient = zclient_new (master); - zclient_init (zclient, ZEBRA_ROUTE_BGP, 0); - zclient->zebra_connected = bgp_zebra_connected; - zclient->router_id_update = bgp_router_id_update; - zclient->interface_add = bgp_interface_add; - zclient->interface_delete = bgp_interface_delete; - zclient->interface_address_add = bgp_interface_address_add; - zclient->interface_address_delete = bgp_interface_address_delete; - zclient->interface_nbr_address_add = bgp_interface_nbr_address_add; - zclient->interface_nbr_address_delete = bgp_interface_nbr_address_delete; - zclient->interface_vrf_update = bgp_interface_vrf_update; - zclient->redistribute_route_ipv4_add = zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = zebra_read_ipv4; - zclient->interface_up = bgp_interface_up; - zclient->interface_down = bgp_interface_down; - zclient->redistribute_route_ipv6_add = zebra_read_ipv6; - zclient->redistribute_route_ipv6_del = zebra_read_ipv6; - zclient->nexthop_update = bgp_read_nexthop_update; - zclient->import_check_update = bgp_read_import_check_update; - - bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE); - bgp_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE); + zclient_num_connects = 0; + + /* Set default values. */ + zclient = zclient_new(master); + zclient_init(zclient, ZEBRA_ROUTE_BGP, 0); + zclient->zebra_connected = bgp_zebra_connected; + zclient->router_id_update = bgp_router_id_update; + zclient->interface_add = bgp_interface_add; + zclient->interface_delete = bgp_interface_delete; + zclient->interface_address_add = bgp_interface_address_add; + zclient->interface_address_delete = bgp_interface_address_delete; + zclient->interface_nbr_address_add = bgp_interface_nbr_address_add; + zclient->interface_nbr_address_delete = + bgp_interface_nbr_address_delete; + zclient->interface_vrf_update = bgp_interface_vrf_update; + zclient->redistribute_route_ipv4_add = zebra_read_ipv4; + zclient->redistribute_route_ipv4_del = zebra_read_ipv4; + zclient->interface_up = bgp_interface_up; + zclient->interface_down = bgp_interface_down; + zclient->redistribute_route_ipv6_add = zebra_read_ipv6; + zclient->redistribute_route_ipv6_del = zebra_read_ipv6; + zclient->nexthop_update = bgp_read_nexthop_update; + zclient->import_check_update = bgp_read_import_check_update; + + bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE); + bgp_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE); } -void -bgp_zebra_destroy(void) +void bgp_zebra_destroy(void) { - if (zclient == NULL) - return; - zclient_stop(zclient); - zclient_free(zclient); - zclient = NULL; + if (zclient == NULL) + return; + zclient_stop(zclient); + zclient_free(zclient); + zclient = NULL; } -int -bgp_zebra_num_connects(void) +int bgp_zebra_num_connects(void) { - return zclient_num_connects; + return zclient_num_connects; } |
