s32 bgp_fec_announce_6pe(struct zclient *zc, struct prefix *p, struct bgp_info *info, struct bgp *bgp) { u32 flags = 0; struct stream * s = zc->obuf ; struct peer * peer = info->peer ; u32 gateway ,label ; struct rtm_fec_info_key key; struct in6_addr *nexthop = NULL; if( !info || !info->attr || !info->attr->extra ) return -1 ; if (info->attr->extra->mp_nexthop_len == 16) { nexthop = &info->attr->extra->mp_nexthop_global; } /* If both global and link-local address present. */ else 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(NULL == nexthop || !IN6_IS_ADDR_V4MAPPED(nexthop)) { return -1; } memcpy (&gateway , ((s8 *)nexthop) + 12, 4); label = decode_label ( bgp_info_extra_get(info)->tag) ; SET_FLAG(flags, ZAPI_FEC_GATEWAY); stream_reset(s); zclient_create_header(s,ZEBRA_MPLS_FEC6_INFO_ADD); stream_put_prefix(s,p); stream_putl(s, flags); stream_putl(s, ZEBRA_FEC_TYPE_6PE); if( peer ) stream_putl(s,peer->nexthop.v4.s_addr); else stream_putl(s,0); // lsr_id = 0 stream_putl(s,label); stream_putl(s,gateway); stream_putw_at (s, 0, stream_get_endp (s)); key.peer_addr = gateway; return rtm_fec_send(ZEBRA_MPLS_FEC6_INFO_ADD, zc, p, s, &key) ; }
s32 bgp_fec_announce_6vpe(bgp_litevrf_config_t *litevrf, struct prefix *p, struct bgp_info *info) { u32 flags = 0; struct stream * s = zclient->obuf ; struct peer * peer = info->peer ; u32 gateway ,label ; struct rtm_fec_info_key key; struct in6_addr *nexthop = NULL; if( !info || !info->attr || !info->attr->extra ) return -1 ; nexthop = &info->attr->extra->mp_nexthop_global; if(NULL == nexthop || !IN6_IS_ADDR_V4MAPPED(nexthop)) { return -1; } memcpy (&gateway , ((s8 *)nexthop) + 12, 4); label = decode_label ( bgp_info_extra_get(info)->tag) ; SET_FLAG(flags, ZAPI_FEC_GATEWAY|ZAPI_FEC_LITEVRF); stream_reset(s); zclient_create_header(s,ZEBRA_MPLS_FEC6_INFO_ADD); stream_put_prefix(s,p); stream_putl(s, flags); stream_putl(s,litevrf->id); stream_putl(s, ZEBRA_FEC_TYPE_6VPE); if( peer ) stream_putl(s,peer->nexthop.v4.s_addr); else stream_putl(s,0); // lsr_id = 0 stream_putl(s,label); stream_putl(s,gateway); stream_putw_at (s, 0, stream_get_endp (s)); key.peer_addr = gateway; return rtm_fec_send(ZEBRA_MPLS_FEC6_INFO_ADD, zclient, p, s, &key) ; }
static int send_client (struct rnh *rnh, struct zserv *client, vrf_id_t vrf_id) { struct stream *s; struct rib *rib; unsigned long nump; u_char num; struct nexthop *nexthop; struct route_node *rn; rn = rnh->node; rib = rnh->state; /* Get output stream. */ s = client->obuf; stream_reset (s); zserv_create_header (s, ZEBRA_NEXTHOP_UPDATE, vrf_id); stream_putw(s, rn->p.family); stream_put_prefix (s, &rn->p); if (rib) { stream_putl (s, rib->metric); num = 0; nump = stream_get_endp(s); stream_putc (s, 0); for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) && ! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) { stream_putc (s, nexthop->type); switch (nexthop->type) { case ZEBRA_NEXTHOP_IPV4: stream_put_in_addr (s, &nexthop->gate.ipv4); break; case ZEBRA_NEXTHOP_IFINDEX: case ZEBRA_NEXTHOP_IFNAME: stream_putl (s, nexthop->ifindex); break; case ZEBRA_NEXTHOP_IPV4_IFINDEX: case ZEBRA_NEXTHOP_IPV4_IFNAME: stream_put_in_addr (s, &nexthop->gate.ipv4); stream_putl (s, nexthop->ifindex); break; #ifdef HAVE_IPV6 case ZEBRA_NEXTHOP_IPV6: stream_put (s, &nexthop->gate.ipv6, 16); break; case ZEBRA_NEXTHOP_IPV6_IFINDEX: case ZEBRA_NEXTHOP_IPV6_IFNAME: stream_put (s, &nexthop->gate.ipv6, 16); stream_putl (s, nexthop->ifindex); break; #endif /* HAVE_IPV6 */ default: /* do nothing */ break; } num++; } stream_putc_at (s, nump, num); } else { stream_putl (s, 0); stream_putc (s, 0); } stream_putw_at (s, 0, stream_get_endp (s)); client->nh_last_upd_time = quagga_time(NULL); client->last_write_cmd = ZEBRA_NEXTHOP_UPDATE; return zebra_server_send_message(client); }