void ripng_zebra_ipv6_delete (struct prefix_ipv6 *p, struct in6_addr *nexthop, unsigned int ifindex) { struct zapi_ipv6 api; if (zclient->redist[ZEBRA_ROUTE_RIPNG]) { api.type = ZEBRA_ROUTE_RIPNG; api.flags = 0; api.message = 0; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1; api.nexthop = &nexthop; SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); api.ifindex_num = 1; api.ifindex = &ifindex; zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, p, &api); } }
void ripng_zebra_ipv6_add (struct prefix_ipv6 *p, struct in6_addr *nexthop, unsigned int ifindex, u_char metric) { struct zapi_ipv6 api; if (zclient->redist[ZEBRA_ROUTE_RIPNG]) { api.type = ZEBRA_ROUTE_RIPNG; api.flags = 0; api.message = 0; api.safi = SAFI_UNICAST; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1; api.nexthop = &nexthop; SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); api.ifindex_num = 1; api.ifindex = &ifindex; SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = metric; zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, p, &api); } }
void isis_zebra_route_del_ipv6 (struct prefix *prefix, struct isis_route_info *route_info) { struct zapi_ipv6 api; struct in6_addr **nexthop_list; unsigned int *ifindex_list; struct isis_nexthop6 *nexthop6; int i, size; struct listnode *node; struct prefix_ipv6 prefix6; if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC)) return; api.type = ZEBRA_ROUTE_ISIS; api.flags = 0; api.message = 0; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); api.nexthop_num = listcount (route_info->nexthops6); api.ifindex_num = listcount (route_info->nexthops6); /* allocate memory for nexthop_list */ size = sizeof (struct isis_nexthop6 *) * listcount (route_info->nexthops6); nexthop_list = (struct in6_addr **) XMALLOC (MTYPE_ISIS_TMP, size); if (!nexthop_list) { zlog_err ("isis_zebra_route_del_ipv6: out of memory!"); return; } /* allocate memory for ifindex_list */ size = sizeof (unsigned int) * listcount (route_info->nexthops6); ifindex_list = (unsigned int *) XMALLOC (MTYPE_ISIS_TMP, size); if (!ifindex_list) { zlog_err ("isis_zebra_route_del_ipv6: out of memory!"); XFREE (MTYPE_ISIS_TMP, nexthop_list); return; } /* for each nexthop */ i = 0; for (node = listhead (route_info->nexthops6); node; nextnode (node)) { nexthop6 = getdata (node); if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) && !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6)) { api.nexthop_num--; api.ifindex_num--; continue; } nexthop_list[i] = &nexthop6->ip6; ifindex_list[i] = nexthop6->ifindex; i++; } api.nexthop = nexthop_list; api.ifindex = ifindex_list; if (api.nexthop_num && api.ifindex_num) { prefix6.family = AF_INET6; prefix6.prefixlen = prefix->prefixlen; memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr)); zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6, &api); UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC); } XFREE (MTYPE_ISIS_TMP, nexthop_list); XFREE (MTYPE_ISIS_TMP, ifindex_list); }
void bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi) { int flags; struct peer *peer; if (zclient->sock < 0) return; if (! zclient->redist[ZEBRA_ROUTE_BGP]) return; peer = info->peer; 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)) SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); if (p->family == AF_INET) { struct zapi_ipv4 api; struct in_addr *nexthop; api.flags = flags; nexthop = &info->attr->nexthop; api.type = ZEBRA_ROUTE_BGP; api.message = 0; api.safi = safi; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1; api.nexthop = &nexthop; api.ifindex_num = 0; SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; if (BGP_DEBUG(zebra, ZEBRA)) { char buf[2][INET_ADDRSTRLEN]; zlog_debug("Zebra send: IPv4 route delete %s/%d nexthop %s metric %u", inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), p->prefixlen, inet_ntop(AF_INET, nexthop, buf[1], sizeof(buf[1])), api.metric); } zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, (struct prefix_ipv4 *) p, &api); } #ifdef HAVE_IPV6 /* We have to think about a IPv6 link-local address curse. */ if (p->family == AF_INET6) { struct zapi_ipv6 api; unsigned int ifindex; struct in6_addr *nexthop; assert (info->attr->extra); ifindex = 0; nexthop = NULL; /* Only global address nexthop exists. */ if (info->attr->extra->mp_nexthop_len == 16) nexthop = &info->attr->extra->mp_nexthop_global; /* If both global and link-local address present. */ if (info->attr->extra->mp_nexthop_len == 32) { nexthop = &info->attr->extra->mp_nexthop_local; if (info->peer->nexthop.ifp) ifindex = info->peer->nexthop.ifp->ifindex; } if (nexthop == NULL) return; if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex) if (info->peer->ifname) ifindex = if_nametoindex (info->peer->ifname); api.flags = flags; api.type = ZEBRA_ROUTE_BGP; api.message = 0; api.safi = safi; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1; api.nexthop = &nexthop; SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); api.ifindex_num = 1; api.ifindex = &ifindex; SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; if (BGP_DEBUG(zebra, ZEBRA)) { char buf[2][INET6_ADDRSTRLEN]; zlog_debug("Zebra send: IPv6 route delete %s/%d nexthop %s metric %u", inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), p->prefixlen, inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])), api.metric); } zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, (struct prefix_ipv6 *) p, &api); } #endif /* HAVE_IPV6 */ }
void bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, safi_t safi) { int flags; u_char distance; struct peer *peer; struct bgp_info *mpinfo; size_t oldsize, newsize; if (zclient->sock < 0) return; if (! zclient->redist[ZEBRA_ROUTE_BGP]) return; flags = 0; peer = info->peer; if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) { 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)) SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); /* resize nexthop buffer size if necessary */ if ((oldsize = stream_get_size (bgp_nexthop_buf)) < (sizeof (struct in_addr *) * (bgp_info_mpath_count (info) + 1))) { newsize = (sizeof (struct in_addr *) * (bgp_info_mpath_count (info) + 1)); newsize = stream_resize (bgp_nexthop_buf, newsize); if (newsize == oldsize) { zlog_err ("can't resize nexthop buffer"); return; } } stream_reset (bgp_nexthop_buf); if (p->family == AF_INET) { struct zapi_ipv4 api; struct in_addr *nexthop; api.flags = flags; nexthop = &info->attr->nexthop; stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *)); for (mpinfo = bgp_info_mpath_first (info); mpinfo; mpinfo = bgp_info_mpath_next (mpinfo)) { nexthop = &mpinfo->attr->nexthop; stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *)); } api.type = ZEBRA_ROUTE_BGP; api.message = 0; api.safi = safi; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1 + bgp_info_mpath_count (info); api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf); api.ifindex_num = 0; SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; distance = bgp_distance_apply (p, info, bgp); if (distance) { SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); api.distance = distance; } if (BGP_DEBUG(zebra, ZEBRA)) { int i; char buf[2][INET_ADDRSTRLEN]; zlog_debug("Zebra send: IPv4 route add %s/%d nexthop %s metric %u" " count %d", inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), p->prefixlen, inet_ntop(AF_INET, api.nexthop[0], buf[1], sizeof(buf[1])), api.metric, api.nexthop_num); for (i = 1; i < api.nexthop_num; i++) zlog_debug("Zebra send: IPv4 route add [nexthop %d] %s", i, inet_ntop(AF_INET, api.nexthop[i], buf[1], sizeof(buf[1]))); } zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, (struct prefix_ipv4 *) p, &api); } #ifdef HAVE_IPV6 /* We have to think about a IPv6 link-local address curse. */ if (p->family == AF_INET6) { unsigned int ifindex; struct in6_addr *nexthop; struct zapi_ipv6 api; ifindex = 0; nexthop = NULL; assert (info->attr->extra); /* Only global address nexthop exists. */ if (info->attr->extra->mp_nexthop_len == 16) nexthop = &info->attr->extra->mp_nexthop_global; /* If both global and link-local address present. */ if (info->attr->extra->mp_nexthop_len == 32) { /* Workaround for Cisco's nexthop bug. */ if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global) && peer->su_remote->sa.sa_family == AF_INET6) nexthop = &peer->su_remote->sin6.sin6_addr; else nexthop = &info->attr->extra->mp_nexthop_local; if (info->peer->nexthop.ifp) ifindex = info->peer->nexthop.ifp->ifindex; } if (nexthop == NULL) return; if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex) { if (info->peer->ifname) ifindex = if_nametoindex (info->peer->ifname); else if (info->peer->nexthop.ifp) ifindex = info->peer->nexthop.ifp->ifindex; } /* Make Zebra API structure. */ api.flags = flags; api.type = ZEBRA_ROUTE_BGP; api.message = 0; api.safi = safi; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1; api.nexthop = &nexthop; SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); api.ifindex_num = 1; api.ifindex = &ifindex; SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; if (BGP_DEBUG(zebra, ZEBRA)) { char buf[2][INET6_ADDRSTRLEN]; zlog_debug("Zebra send: IPv6 route add %s/%d nexthop %s metric %u", inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), p->prefixlen, inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])), api.metric); } zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, (struct prefix_ipv6 *) p, &api); } #endif /* HAVE_IPV6 */ }
void bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi) { int flags; struct peer *peer; if (zclient->sock < 0) return; if (! vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_BGP], VRF_DEFAULT)) return; peer = info->peer; 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 (peer) != 1) || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); if (p->family == AF_INET) { struct zapi_ipv4 api; api.vrf_id = VRF_DEFAULT; api.flags = flags; api.type = ZEBRA_ROUTE_BGP; api.message = 0; api.safi = safi; api.nexthop_num = 0; api.ifindex_num = 0; SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; 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, ZEBRA)) { char buf[2][INET_ADDRSTRLEN]; zlog_debug("Zebra send: IPv4 route delete %s/%d metric %u tag %d", 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; api.vrf_id = VRF_DEFAULT; api.flags = flags; api.type = ZEBRA_ROUTE_BGP; api.message = 0; api.safi = safi; api.nexthop_num = 0; api.ifindex_num = 0; SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; 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, ZEBRA)) { char buf[2][INET6_ADDRSTRLEN]; zlog_debug("Zebra send: IPv6 route delete %s/%d metric %u tag %d", 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, &api); } }
/* Send ECMP routes to zebra. */ static void ripng_zebra_ipv6_send (struct route_node *rp, u_char cmd) { static struct in6_addr **nexthops = NULL; static unsigned int *ifindexes = NULL; static unsigned int nexthops_len = 0; struct list *list = (struct list *)rp->info; struct zapi_ipv6 api; struct listnode *listnode = NULL; struct ripng_info *rinfo = NULL; int count = 0; if (vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_RIPNG], VRF_DEFAULT)) { api.vrf_id = VRF_DEFAULT; api.type = ZEBRA_ROUTE_RIPNG; api.flags = 0; api.message = 0; api.safi = SAFI_UNICAST; if (nexthops_len < listcount (list)) { nexthops_len = listcount (list); nexthops = XREALLOC (MTYPE_TMP, nexthops, nexthops_len * sizeof (struct in6_addr *)); ifindexes = XREALLOC (MTYPE_TMP, ifindexes, nexthops_len * sizeof (unsigned int)); } SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) { nexthops[count] = &rinfo->nexthop; ifindexes[count] = rinfo->ifindex; count++; if (cmd == ZEBRA_IPV6_ROUTE_ADD) SET_FLAG (rinfo->flags, RIPNG_RTF_FIB); else UNSET_FLAG (rinfo->flags, RIPNG_RTF_FIB); } api.nexthop = nexthops; api.nexthop_num = count; api.ifindex = ifindexes; api.ifindex_num = count; rinfo = listgetdata (listhead (list)); SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = rinfo->metric; zapi_ipv6_route (cmd, zclient, (struct prefix_ipv6 *)&rp->p, &api); if (IS_RIPNG_DEBUG_ZEBRA) { if (ripng->ecmp) zlog_debug ("%s: %s/%d nexthops %d", (cmd == ZEBRA_IPV6_ROUTE_ADD) ? \ "Install into zebra" : "Delete from zebra", inet6_ntoa (rp->p.u.prefix6), rp->p.prefixlen, count); else zlog_debug ("%s: %s/%d", (cmd == ZEBRA_IPV6_ROUTE_ADD) ? \ "Install into zebra" : "Delete from zebra", inet6_ntoa (rp->p.u.prefix6), rp->p.prefixlen); } }