--- embedaddon/quagga/bgpd/bgp_nexthop.c 2013/07/21 23:54:37 1.1.1.3 +++ embedaddon/quagga/bgpd/bgp_nexthop.c 2016/11/02 10:09:10 1.1.1.4 @@ -30,6 +30,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330 #include "memory.h" #include "hash.h" #include "jhash.h" +#include "filter.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" @@ -42,10 +43,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330 #include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */ struct bgp_nexthop_cache *zlookup_query (struct in_addr); -#ifdef HAVE_IPV6 struct bgp_nexthop_cache *zlookup_query_ipv6 (struct in6_addr *); -#endif /* HAVE_IPV6 */ - + /* Only one BGP scan thread are activated at the same time. */ static struct thread *bgp_scan_thread = NULL; @@ -68,7 +67,7 @@ static struct bgp_table *bgp_connected_table[AFI_MAX]; /* BGP nexthop lookup query client. */ struct zclient *zlookup = NULL; - + /* Add nexthop to the end of the list. */ static void bnc_nexthop_add (struct bgp_nexthop_cache *bnc, struct nexthop *nexthop) @@ -109,7 +108,7 @@ bnc_free (struct bgp_nexthop_cache *bnc) bnc_nexthop_free (bnc); XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc); } - + static int bgp_nexthop_same (struct nexthop *next1, struct nexthop *next2) { @@ -122,12 +121,16 @@ bgp_nexthop_same (struct nexthop *next1, struct nextho if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4)) return 0; break; + case ZEBRA_NEXTHOP_IPV4_IFINDEX: + if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4) + || next1->ifindex != next2->ifindex) + return 0; + break; case ZEBRA_NEXTHOP_IFINDEX: case ZEBRA_NEXTHOP_IFNAME: if (next1->ifindex != next2->ifindex) return 0; break; -#ifdef HAVE_IPV6 case ZEBRA_NEXTHOP_IPV6: if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6)) return 0; @@ -139,7 +142,6 @@ bgp_nexthop_same (struct nexthop *next1, struct nextho if (next1->ifindex != next2->ifindex) return 0; break; -#endif /* HAVE_IPV6 */ default: /* do nothing */ break; @@ -191,7 +193,6 @@ bgp_nexthop_onlink (afi_t afi, struct attr *attr) return 1; } } -#ifdef HAVE_IPV6 else if (afi == AFI_IP6) { if (attr->extra->mp_nexthop_len == 32) @@ -210,11 +211,9 @@ bgp_nexthop_onlink (afi_t afi, struct attr *attr) } } } -#endif /* HAVE_IPV6 */ return 0; } -#ifdef HAVE_IPV6 /* Check specified next-hop is reachable or not. */ static int bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed, @@ -299,7 +298,6 @@ bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp return bnc->valid; } -#endif /* HAVE_IPV6 */ /* Check specified next-hop is reachable or not. */ int @@ -319,10 +317,8 @@ bgp_nexthop_lookup (afi_t afi, struct peer *peer, stru return 1; } -#ifdef HAVE_IPV6 if (afi == AFI_IP6) return bgp_nexthop_lookup_ipv6 (peer, ri, changed, metricchanged); -#endif /* HAVE_IPV6 */ addr = ri->attr->nexthop; @@ -453,7 +449,8 @@ bgp_scan (afi_t afi, safi_t safi) changed = 0; metricchanged = 0; - if (bi->peer->sort == BGP_PEER_EBGP && bi->peer->ttl == 1) + if (bi->peer->sort == BGP_PEER_EBGP && bi->peer->ttl == 1 + && !CHECK_FLAG(bi->peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) valid = bgp_nexthop_onlink (afi, bi->attr); else valid = bgp_nexthop_lookup (afi, bi->peer, bi, @@ -490,7 +487,8 @@ bgp_scan (afi_t afi, safi_t safi) afi, SAFI_UNICAST); } } - bgp_process (bgp, rn, afi, SAFI_UNICAST); + if (rn->info) + bgp_process (bgp, rn, afi, SAFI_UNICAST); } /* Flash old cache. */ @@ -523,16 +521,14 @@ static int bgp_scan_timer (struct thread *t) { bgp_scan_thread = - thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval); + thread_add_timer (bm->master, bgp_scan_timer, NULL, bgp_scan_interval); if (BGP_DEBUG (events, EVENTS)) zlog_debug ("Performing BGP general scanning"); bgp_scan (AFI_IP, SAFI_UNICAST); -#ifdef HAVE_IPV6 bgp_scan (AFI_IP6, SAFI_UNICAST); -#endif /* HAVE_IPV6 */ return 0; } @@ -583,6 +579,17 @@ bgp_address_init (void) bgp_address_hash_cmp); } +void +bgp_address_destroy (void) +{ + if (bgp_address_hash == NULL) + return; + + hash_clean(bgp_address_hash, NULL); + hash_free(bgp_address_hash); + bgp_address_hash = NULL; +} + static void bgp_address_add (struct prefix *p) { @@ -604,6 +611,10 @@ bgp_address_del (struct prefix *p) tmp.addr = p->u.prefix4; addr = hash_lookup (bgp_address_hash, &tmp); + /* may have been deleted earlier by bgp_interface_down() */ + if (addr == NULL) + return; + addr->refcnt--; if (addr->refcnt == 0) @@ -613,7 +624,7 @@ bgp_address_del (struct prefix *p) } } - + struct bgp_connected_ref { unsigned int refcnt; @@ -638,9 +649,9 @@ bgp_connected_add (struct connected *ifc) addr = ifc->address; + p = *(CONNECTED_PREFIX(ifc)); if (addr->family == AF_INET) { - PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); apply_mask_ipv4 ((struct prefix_ipv4 *) &p); if (prefix_ipv4_any ((struct prefix_ipv4 *) &p)) @@ -661,10 +672,8 @@ bgp_connected_add (struct connected *ifc) rn->info = bc; } } -#ifdef HAVE_IPV6 else if (addr->family == AF_INET6) { - PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); apply_mask_ipv6 ((struct prefix_ipv6 *) &p); if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) @@ -686,7 +695,6 @@ bgp_connected_add (struct connected *ifc) rn->info = bc; } } -#endif /* HAVE_IPV6 */ } void @@ -705,9 +713,9 @@ bgp_connected_delete (struct connected *ifc) addr = ifc->address; + p = *(CONNECTED_PREFIX(ifc)); if (addr->family == AF_INET) { - PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); apply_mask_ipv4 ((struct prefix_ipv4 *) &p); if (prefix_ipv4_any ((struct prefix_ipv4 *) &p)) @@ -729,10 +737,8 @@ bgp_connected_delete (struct connected *ifc) bgp_unlock_node (rn); bgp_unlock_node (rn); } -#ifdef HAVE_IPV6 else if (addr->family == AF_INET6) { - PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); apply_mask_ipv6 ((struct prefix_ipv6 *) &p); if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) @@ -755,7 +761,6 @@ bgp_connected_delete (struct connected *ifc) bgp_unlock_node (rn); bgp_unlock_node (rn); } -#endif /* HAVE_IPV6 */ } int @@ -771,7 +776,7 @@ bgp_nexthop_self (struct attr *attr) return 0; } - + static struct bgp_nexthop_cache * zlookup_read (void) { @@ -779,9 +784,10 @@ zlookup_read (void) uint16_t length; u_char marker; u_char version; + uint16_t vrf_id; uint16_t command; - int nbytes; - struct in_addr raddr; + int err; + struct in_addr raddr __attribute__((unused)); uint32_t metric; int i; u_char nexthop_num; @@ -791,22 +797,15 @@ zlookup_read (void) s = zlookup->ibuf; stream_reset (s); - nbytes = stream_read (s, zlookup->sock, 2); - length = stream_getw (s); - - nbytes = stream_read (s, zlookup->sock, length - 2); - marker = stream_getc (s); - version = stream_getc (s); - - if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER) + err = zclient_read_header (s, zlookup->sock, &length, &marker, &version, + &vrf_id, &command); + if (err < 0) { - zlog_err("%s: socket %d version mismatch, marker %d, version %d", - __func__, zlookup->sock, marker, version); + zlog_err("%s: zserv_read_header() failed", __func__); return NULL; } - - command = stream_getw (s); - + + /* XXX: not doing anything with raddr */ raddr.s_addr = stream_get_ipv4 (s); metric = stream_getl (s); nexthop_num = stream_getc (s); @@ -827,6 +826,10 @@ zlookup_read (void) case ZEBRA_NEXTHOP_IPV4: nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); break; + case ZEBRA_NEXTHOP_IPV4_IFINDEX: + nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); + nexthop->ifindex = stream_getl (s); + break; case ZEBRA_NEXTHOP_IFINDEX: case ZEBRA_NEXTHOP_IFNAME: nexthop->ifindex = stream_getl (s); @@ -856,7 +859,7 @@ zlookup_query (struct in_addr addr) s = zlookup->obuf; stream_reset (s); - zclient_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP); + zclient_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP, VRF_DEFAULT); stream_put_in_addr (s, &addr); stream_putw_at (s, 0, stream_get_endp (s)); @@ -880,18 +883,15 @@ zlookup_query (struct in_addr addr) return zlookup_read (); } -#ifdef HAVE_IPV6 static struct bgp_nexthop_cache * zlookup_read_ipv6 (void) { struct stream *s; - uint16_t length; + uint16_t length, vrf_id, cmd; u_char version, marker; - uint16_t command; - int nbytes; struct in6_addr raddr; uint32_t metric; - int i; + int i, err; u_char nexthop_num; struct nexthop *nexthop; struct bgp_nexthop_cache *bnc; @@ -899,22 +899,15 @@ zlookup_read_ipv6 (void) s = zlookup->ibuf; stream_reset (s); - nbytes = stream_read (s, zlookup->sock, 2); - length = stream_getw (s); - - nbytes = stream_read (s, zlookup->sock, length - 2); - marker = stream_getc (s); - version = stream_getc (s); - - if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER) + err = zclient_read_header (s, zlookup->sock, &length, &marker, &version, + &vrf_id, &cmd); + if (err < 0) { - zlog_err("%s: socket %d version mismatch, marker %d, version %d", - __func__, zlookup->sock, marker, version); + zlog_err("%s: zserv_read_header() failed", __func__); return NULL; } - - command = stream_getw (s); - + + /* XXX: not actually doing anything with raddr */ stream_get (&raddr, s, 16); metric = stream_getl (s); @@ -970,7 +963,7 @@ zlookup_query_ipv6 (struct in6_addr *addr) s = zlookup->obuf; stream_reset (s); - zclient_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP); + zclient_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP, VRF_DEFAULT); stream_put (s, addr, 16); stream_putw_at (s, 0, stream_get_endp (s)); @@ -992,7 +985,6 @@ zlookup_query_ipv6 (struct in6_addr *addr) return zlookup_read_ipv6 (); } -#endif /* HAVE_IPV6 */ static int bgp_import_check (struct prefix *p, u_int32_t *igpmetric, @@ -1000,10 +992,9 @@ bgp_import_check (struct prefix *p, u_int32_t *igpmetr { struct stream *s; int ret; - u_int16_t length, command; + u_int16_t length, vrf_id, command; u_char version, marker; - int nbytes; - struct in_addr addr; + struct in_addr addr __attribute__((unused)); struct in_addr nexthop; u_int32_t metric = 0; u_char nexthop_num; @@ -1020,7 +1011,7 @@ bgp_import_check (struct prefix *p, u_int32_t *igpmetr /* Send query to the lookup connection */ s = zlookup->obuf; stream_reset (s); - zclient_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP); + zclient_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP, VRF_DEFAULT); stream_putc (s, p->prefixlen); stream_put_in_addr (s, &p->u.prefix4); @@ -1048,24 +1039,15 @@ bgp_import_check (struct prefix *p, u_int32_t *igpmetr /* Get result. */ stream_reset (s); - /* Fetch length. */ - nbytes = stream_read (s, zlookup->sock, 2); - length = stream_getw (s); - - /* Fetch whole data. */ - nbytes = stream_read (s, zlookup->sock, length - 2); - marker = stream_getc (s); - version = stream_getc (s); - - if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER) + ret = zclient_read_header (s, zlookup->sock, &length, &marker, &version, + &vrf_id, &command); + if (ret < 0) { - zlog_err("%s: socket %d version mismatch, marker %d, version %d", - __func__, zlookup->sock, marker, version); + zlog_err("%s: zserv_read_header() failed", __func__); return 0; } - - command = stream_getw (s); - + + /* XXX: not using addr */ addr.s_addr = stream_get_ipv4 (s); metric = stream_getl (s); nexthop_num = stream_getc (s); @@ -1079,14 +1061,20 @@ bgp_import_check (struct prefix *p, u_int32_t *igpmetr { nexthop.s_addr = 0; nexthop_type = stream_getc (s); - if (nexthop_type == ZEBRA_NEXTHOP_IPV4) + switch (nexthop_type) { + case ZEBRA_NEXTHOP_IPV4: nexthop.s_addr = stream_get_ipv4 (s); - if (igpnexthop) - *igpnexthop = nexthop; + break; + case ZEBRA_NEXTHOP_IPV4_IFINDEX: + nexthop.s_addr = stream_get_ipv4 (s); + /* ifindex */ (void)stream_getl (s); + break; + default: + /* do nothing */ + break; } - else - *igpnexthop = nexthop; + *igpnexthop = nexthop; return 1; } @@ -1110,7 +1098,7 @@ bgp_import (struct thread *t) safi_t safi; bgp_import_thread = - thread_add_timer (master, bgp_import, NULL, bgp_import_interval); + thread_add_timer (bm->master, bgp_import, NULL, bgp_import_interval); if (BGP_DEBUG (events, EVENTS)) zlog_debug ("Import timer expired."); @@ -1223,7 +1211,7 @@ bgp_multiaccess_check_v4 (struct in_addr nexthop, char return 0; } - + DEFUN (bgp_scan_time, bgp_scan_time_cmd, "bgp scan-time <5-60>", @@ -1237,7 +1225,7 @@ DEFUN (bgp_scan_time, { thread_cancel (bgp_scan_thread); bgp_scan_thread = - thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval); + thread_add_timer (bm->master, bgp_scan_timer, NULL, bgp_scan_interval); } return CMD_SUCCESS; @@ -1256,7 +1244,7 @@ DEFUN (no_bgp_scan_time, { thread_cancel (bgp_scan_thread); bgp_scan_thread = - thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval); + thread_add_timer (bm->master, bgp_scan_timer, NULL, bgp_scan_interval); } return CMD_SUCCESS; @@ -1299,6 +1287,10 @@ show_ip_bgp_scan_tables (struct vty *vty, const char d case NEXTHOP_TYPE_IPV4: vty_out (vty, " gate %s%s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE); break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out (vty, " gate %s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN)); + vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE); + break; case NEXTHOP_TYPE_IFINDEX: vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE); break; @@ -1311,7 +1303,6 @@ show_ip_bgp_scan_tables (struct vty *vty, const char d inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE); } -#ifdef HAVE_IPV6 { for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]); rn; @@ -1343,7 +1334,6 @@ show_ip_bgp_scan_tables (struct vty *vty, const char d VTY_NEWLINE); } } -#endif /* HAVE_IPV6 */ vty_out (vty, "BGP connected route:%s", VTY_NEWLINE); for (rn = bgp_table_top (bgp_connected_table[AFI_IP]); @@ -1353,7 +1343,6 @@ show_ip_bgp_scan_tables (struct vty *vty, const char d vty_out (vty, " %s/%d%s", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen, VTY_NEWLINE); -#ifdef HAVE_IPV6 { for (rn = bgp_table_top (bgp_connected_table[AFI_IP6]); rn; @@ -1364,7 +1353,6 @@ show_ip_bgp_scan_tables (struct vty *vty, const char d rn->p.prefixlen, VTY_NEWLINE); } -#endif /* HAVE_IPV6 */ return CMD_SUCCESS; } @@ -1403,9 +1391,9 @@ bgp_config_write_scan_time (struct vty *vty) void bgp_scan_init (void) { - zlookup = zclient_new (); + zlookup = zclient_new (bm->master); zlookup->sock = -1; - zlookup->t_connect = thread_add_event (master, zlookup_connect, zlookup, 0); + zlookup->t_connect = thread_add_event (bm->master, zlookup_connect, zlookup, 0); bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT; bgp_import_interval = BGP_IMPORT_INTERVAL_DEFAULT; @@ -1416,18 +1404,16 @@ bgp_scan_init (void) bgp_connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST); -#ifdef HAVE_IPV6 cache1_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); cache2_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); bgp_nexthop_cache_table[AFI_IP6] = cache1_table[AFI_IP6]; bgp_connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); -#endif /* HAVE_IPV6 */ /* Make BGP scan thread. */ - bgp_scan_thread = thread_add_timer (master, bgp_scan_timer, + bgp_scan_thread = thread_add_timer (bm->master, bgp_scan_timer, NULL, bgp_scan_interval); /* Make BGP import there. */ - bgp_import_thread = thread_add_timer (master, bgp_import, NULL, 0); + bgp_import_thread = thread_add_timer (bm->master, bgp_import, NULL, 0); install_element (BGP_NODE, &bgp_scan_time_cmd); install_element (BGP_NODE, &no_bgp_scan_time_cmd); @@ -1442,29 +1428,40 @@ bgp_scan_init (void) void bgp_scan_finish (void) { - /* Only the current one needs to be reset. */ - bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP]); - - bgp_table_unlock (cache1_table[AFI_IP]); + if (cache1_table[AFI_IP]) + bgp_table_unlock (cache1_table[AFI_IP]); cache1_table[AFI_IP] = NULL; - bgp_table_unlock (cache2_table[AFI_IP]); + if (cache2_table[AFI_IP]) + bgp_table_unlock (cache2_table[AFI_IP]); cache2_table[AFI_IP] = NULL; - - bgp_table_unlock (bgp_connected_table[AFI_IP]); + + if (bgp_connected_table[AFI_IP]) + bgp_table_unlock (bgp_connected_table[AFI_IP]); bgp_connected_table[AFI_IP] = NULL; -#ifdef HAVE_IPV6 - /* Only the current one needs to be reset. */ - bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP6]); - - bgp_table_unlock (cache1_table[AFI_IP6]); + if (cache1_table[AFI_IP6]) + bgp_table_unlock (cache1_table[AFI_IP6]); cache1_table[AFI_IP6] = NULL; - bgp_table_unlock (cache2_table[AFI_IP6]); + if (cache2_table[AFI_IP6]) + bgp_table_unlock (cache2_table[AFI_IP6]); cache2_table[AFI_IP6] = NULL; - bgp_table_unlock (bgp_connected_table[AFI_IP6]); + if (bgp_connected_table[AFI_IP6]) + bgp_table_unlock (bgp_connected_table[AFI_IP6]); bgp_connected_table[AFI_IP6] = NULL; -#endif /* HAVE_IPV6 */ +} + +void +bgp_scan_destroy (void) +{ + if (zlookup == NULL) + return; + THREAD_OFF(bgp_import_thread); + THREAD_OFF(bgp_scan_thread); + THREAD_OFF(zlookup->t_connect); + bgp_scan_finish(); + zclient_free (zlookup); + zlookup = NULL; }