--- embedaddon/quagga/bgpd/bgp_zebra.c 2013/07/21 23:54:38 1.1.1.3 +++ embedaddon/quagga/bgpd/bgp_zebra.c 2016/11/02 10:09:10 1.1.1.4 @@ -29,6 +29,7 @@ Boston, MA 02111-1307, USA. */ #include "zclient.h" #include "routemap.h" #include "thread.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_route.h" @@ -38,7 +39,7 @@ Boston, MA 02111-1307, USA. */ #include "bgpd/bgp_fsm.h" #include "bgpd/bgp_debug.h" #include "bgpd/bgp_mpath.h" - + /* All information about zebra. */ struct zclient *zclient = NULL; struct in_addr router_id_zebra; @@ -48,7 +49,8 @@ struct stream *bgp_nexthop_buf = NULL; /* Router-id update message from zebra. */ static int -bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length) +bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length, + vrf_id_t vrf_id) { struct prefix router_id; struct listnode *node, *nnode; @@ -76,11 +78,12 @@ bgp_router_id_update (int command, struct zclient *zcl /* Inteface addition message from zebra. */ static int -bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length) +bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length, + vrf_id_t vrf_id) { struct interface *ifp; - ifp = zebra_interface_add_read (zclient->ibuf); + ifp = zebra_interface_add_read (zclient->ibuf, vrf_id); if (BGP_DEBUG(zebra, ZEBRA) && ifp) zlog_debug("Zebra rcvd: interface add %s", ifp->name); @@ -90,13 +93,13 @@ bgp_interface_add (int command, struct zclient *zclien static int bgp_interface_delete (int command, struct zclient *zclient, - zebra_size_t length) + zebra_size_t length, vrf_id_t vrf_id) { struct stream *s; struct interface *ifp; s = zclient->ibuf; - ifp = zebra_interface_state_read (s); + ifp = zebra_interface_state_read (s, vrf_id); ifp->ifindex = IFINDEX_INTERNAL; if (BGP_DEBUG(zebra, ZEBRA)) @@ -106,7 +109,8 @@ bgp_interface_delete (int command, struct zclient *zcl } static int -bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length) +bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length, + vrf_id_t vrf_id) { struct stream *s; struct interface *ifp; @@ -114,7 +118,7 @@ bgp_interface_up (int command, struct zclient *zclient struct listnode *node, *nnode; s = zclient->ibuf; - ifp = zebra_interface_state_read (s); + ifp = zebra_interface_state_read (s, vrf_id); if (! ifp) return 0; @@ -129,7 +133,8 @@ bgp_interface_up (int command, struct zclient *zclient } static int -bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length) +bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length, + vrf_id_t vrf_id) { struct stream *s; struct interface *ifp; @@ -137,7 +142,7 @@ bgp_interface_down (int command, struct zclient *zclie struct listnode *node, *nnode; s = zclient->ibuf; - ifp = zebra_interface_state_read (s); + ifp = zebra_interface_state_read (s, vrf_id); if (! ifp) return 0; @@ -147,12 +152,11 @@ bgp_interface_down (int command, struct zclient *zclie for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c)) bgp_connected_delete (c); - /* Fast external-failover (Currently IPv4 only) */ + /* Fast external-failover */ { struct listnode *mnode; struct bgp *bgp; struct peer *peer; - struct interface *peer_if; for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp)) { @@ -161,15 +165,10 @@ bgp_interface_down (int command, struct zclient *zclie for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) { - if (peer->ttl != 1) + if ((peer->ttl != 1) && (peer->gtsm_hops != 1)) continue; - if (peer->su.sa.sa_family == AF_INET) - peer_if = if_lookup_by_ipv4 (&peer->su.sin.sin_addr); - else - continue; - - if (ifp == peer_if) + if (ifp == peer->nexthop.ifp) BGP_EVENT_ADD (peer, BGP_Stop); } } @@ -180,11 +179,11 @@ bgp_interface_down (int command, struct zclient *zclie static int bgp_interface_address_add (int command, struct zclient *zclient, - zebra_size_t length) + zebra_size_t length, vrf_id_t vrf_id) { struct connected *ifc; - ifc = zebra_interface_address_read (command, zclient->ibuf); + ifc = zebra_interface_address_read (command, zclient->ibuf, vrf_id); if (ifc == NULL) return 0; @@ -205,11 +204,11 @@ bgp_interface_address_add (int command, struct zclient static int bgp_interface_address_delete (int command, struct zclient *zclient, - zebra_size_t length) + zebra_size_t length, vrf_id_t vrf_id) { struct connected *ifc; - ifc = zebra_interface_address_read (command, zclient->ibuf); + ifc = zebra_interface_address_read (command, zclient->ibuf, vrf_id); if (ifc == NULL) return 0; @@ -232,12 +231,14 @@ bgp_interface_address_delete (int command, struct zcli /* Zebra route add and delete treatment. */ static int -zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) +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 char plength = 0; s = zclient->ibuf; nexthop.s_addr = 0; @@ -250,7 +251,8 @@ zebra_read_ipv4 (int command, struct zclient *zclient, /* IPv4 prefix. */ memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; - p.prefixlen = stream_getc (s); + plength = stream_getc (s); + p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, plength); stream_get (&p.prefix, s, PSIZE (p.prefixlen)); /* Nexthop, ifindex, distance, metric. */ @@ -305,15 +307,16 @@ zebra_read_ipv4 (int command, struct zclient *zclient, return 0; } -#ifdef HAVE_IPV6 /* Zebra route add and delete treatment. */ static int -zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length) +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; + unsigned char plength = 0; s = zclient->ibuf; memset (&nexthop, 0, sizeof (struct in6_addr)); @@ -326,7 +329,8 @@ zebra_read_ipv6 (int command, struct zclient *zclient, /* IPv6 prefix. */ memset (&p, 0, sizeof (struct prefix_ipv6)); p.family = AF_INET6; - p.prefixlen = stream_getc (s); + plength = stream_getc (s); + p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, plength); stream_get (&p.prefix, s, PSIZE (p.prefixlen)); /* Nexthop, ifindex, distance, metric. */ @@ -386,8 +390,7 @@ zebra_read_ipv6 (int command, struct zclient *zclient, return 0; } -#endif /* HAVE_IPV6 */ - + struct interface * if_lookup_by_ipv4 (struct in_addr *addr) { @@ -439,7 +442,6 @@ if_lookup_by_ipv4_exact (struct in_addr *addr) return NULL; } -#ifdef HAVE_IPV6 struct interface * if_lookup_by_ipv6 (struct in6_addr *addr) { @@ -532,8 +534,26 @@ if_get_ipv6_local (struct interface *ifp, struct in6_a } return 0; } -#endif /* HAVE_IPV6 */ +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; +} + int bgp_nexthop_set (union sockunion *local, union sockunion *remote, struct bgp_nexthop *nexthop, struct peer *peer) @@ -553,18 +573,16 @@ bgp_nexthop_set (union sockunion *local, union sockuni nexthop->v4 = local->sin.sin_addr; ifp = if_lookup_by_ipv4 (&local->sin.sin_addr); } -#ifdef HAVE_IPV6 if (local->sa.sa_family == AF_INET6) { if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr)) { if (peer->ifname) - ifp = if_lookup_by_index (if_nametoindex (peer->ifname)); + ifp = if_lookup_by_name (peer->ifname); } else ifp = if_lookup_by_ipv6 (&local->sin6.sin6_addr); } -#endif /* HAVE_IPV6 */ if (!ifp) return -1; @@ -574,7 +592,6 @@ bgp_nexthop_set (union sockunion *local, union sockuni /* IPv4 connection. */ if (local->sa.sa_family == AF_INET) { -#ifdef HAVE_IPV6 /* IPv6 nexthop*/ ret = if_get_ipv6_global (ifp, &nexthop->v6_global); @@ -583,17 +600,16 @@ bgp_nexthop_set (union sockunion *local, union sockuni if_get_ipv6_local (ifp, &nexthop->v6_global); else if_get_ipv6_local (ifp, &nexthop->v6_local); -#endif /* HAVE_IPV6 */ } -#ifdef HAVE_IPV6 /* IPv6 connection. */ if (local->sa.sa_family == AF_INET6) { struct interface *direct = NULL; - /* IPv4 nexthop. I don't care about it. */ - if (peer->local_id.s_addr) + /* IPv4 nexthop. */ + ret = if_get_ipv4_address(ifp, &nexthop->v4); + if (!ret && peer->local_id.s_addr) nexthop->v4 = peer->local_id; /* Global address*/ @@ -642,7 +658,6 @@ bgp_nexthop_set (union sockunion *local, union sockuni SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_local, 0); } #endif /* KAME */ -#endif /* HAVE_IPV6 */ return ret; } @@ -658,7 +673,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info if (zclient->sock < 0) return; - if (! zclient->redist[ZEBRA_ROUTE_BGP]) + if (! vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_BGP], VRF_DEFAULT)) return; flags = 0; @@ -694,6 +709,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info struct zapi_ipv4 api; struct in_addr *nexthop; + api.vrf_id = VRF_DEFAULT; api.flags = flags; nexthop = &info->attr->nexthop; stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *)); @@ -741,11 +757,11 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info 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; + ifindex_t ifindex; struct in6_addr *nexthop; struct zapi_ipv6 api; @@ -778,12 +794,13 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex) { if (info->peer->ifname) - ifindex = if_nametoindex (info->peer->ifname); + ifindex = ifname2ifindex (info->peer->ifname); else if (info->peer->nexthop.ifp) ifindex = info->peer->nexthop.ifp->ifindex; } /* Make Zebra API structure. */ + api.vrf_id = VRF_DEFAULT; api.flags = flags; api.type = ZEBRA_ROUTE_BGP; api.message = 0; @@ -810,7 +827,6 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, (struct prefix_ipv6 *) p, &api); } -#endif /* HAVE_IPV6 */ } void @@ -822,7 +838,7 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info if (zclient->sock < 0) return; - if (! zclient->redist[ZEBRA_ROUTE_BGP]) + if (! vrf_bitmap_check (zclient->redist[ZEBRA_ROUTE_BGP], VRF_DEFAULT)) return; peer = info->peer; @@ -841,17 +857,14 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info if (p->family == AF_INET) { struct zapi_ipv4 api; - struct in_addr *nexthop; + api.vrf_id = VRF_DEFAULT; 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.nexthop_num = 0; api.ifindex_num = 0; SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; @@ -859,77 +872,45 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info if (BGP_DEBUG(zebra, ZEBRA)) { char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra send: IPv4 route delete %s/%d nexthop %s metric %u", + zlog_debug("Zebra send: IPv4 route delete %s/%d 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.vrf_id = VRF_DEFAULT; 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; + api.nexthop_num = 0; + api.ifindex_num = 0; 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", + zlog_debug("Zebra send: IPv6 route delete %s/%d 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 */ } - + /* Other routes redistribution into BGP. */ int bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type) @@ -938,10 +919,10 @@ bgp_redistribute_set (struct bgp *bgp, afi_t afi, int bgp->redist[afi][type] = 1; /* Return if already redistribute flag is set. */ - if (zclient->redist[type]) + if (vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT)) return CMD_WARNING; - zclient->redist[type] = 1; + vrf_bitmap_set (zclient->redist[type], VRF_DEFAULT); /* Return if zebra connection is not established. */ if (zclient->sock < 0) @@ -951,7 +932,7 @@ bgp_redistribute_set (struct bgp *bgp, afi_t afi, int zlog_debug("Zebra send: redistribute add %s", zebra_route_string(type)); /* Send distribute add message to zebra. */ - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type); + zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, type, VRF_DEFAULT); return CMD_SUCCESS; } @@ -1006,9 +987,9 @@ bgp_redistribute_unset (struct bgp *bgp, afi_t afi, in bgp->redist_metric[afi][type] = 0; /* Return if zebra connection is disabled. */ - if (! zclient->redist[type]) + if (! vrf_bitmap_check (zclient->redist[type], VRF_DEFAULT)) return CMD_WARNING; - zclient->redist[type] = 0; + vrf_bitmap_unset (zclient->redist[type], VRF_DEFAULT); if (bgp->redist[AFI_IP][type] == 0 && bgp->redist[AFI_IP6][type] == 0 @@ -1018,7 +999,8 @@ bgp_redistribute_unset (struct bgp *bgp, afi_t afi, in if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("Zebra send: redistribute delete %s", zebra_route_string(type)); - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type); + zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, type, + VRF_DEFAULT); } /* Withdraw redistributed routes from current BGP's routing table. */ @@ -1055,19 +1037,26 @@ bgp_redistribute_metric_unset (struct bgp *bgp, afi_t return 1; } - + void bgp_zclient_reset (void) { zclient_reset (zclient); } +static void +bgp_zebra_connected (struct zclient *zclient) +{ + zclient_send_requests (zclient, VRF_DEFAULT); +} + void -bgp_zebra_init (void) +bgp_zebra_init (struct thread_master *master) { /* Set default values. */ - zclient = zclient_new (); + zclient = zclient_new (master); zclient_init (zclient, ZEBRA_ROUTE_BGP); + 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; @@ -1077,13 +1066,18 @@ bgp_zebra_init (void) zclient->ipv4_route_delete = zebra_read_ipv4; zclient->interface_up = bgp_interface_up; zclient->interface_down = bgp_interface_down; -#ifdef HAVE_IPV6 zclient->ipv6_route_add = zebra_read_ipv6; zclient->ipv6_route_delete = zebra_read_ipv6; -#endif /* HAVE_IPV6 */ - /* Interface related init. */ - if_init (); - bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE); +} + +void +bgp_zebra_destroy(void) +{ + if (zclient == NULL) + return; + zclient_stop(zclient); + zclient_free(zclient); + zclient = NULL; }