Commits

Jorge Boncompte [DTI2] authored and David Lamparter committed 10f9bf3f202
bgpd: optimize bgp_nexthop_self()

This function scores 2nd, profiling a full internet table load. It's called for every prefix received. Instead of looping in the interface lists comparing addresses use a hash to mantain them. * bgpd.c: Init the own address hash. * bgp_nexthop.c: Introduce methods to maintain an own address hash. (bgp_connected_add) add addresses to the hash. (bgp_connected_delete) delete addresses from the hash. (bgp_nexthop_self) lookup addresses in the hash. Removed the unused afi_t parameter. * bgp_route.c: (bgp_update_main) Micro-optimization, rearranged condition to not lookup the hash for bogus nexthops (0.0.0.0 or a class D/E address) Signed-off-by: Jorge Boncompte [DTI2] <jorge@dti2.net> Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
No tags

bgpd/bgp_nexthop.c

Modified
21 21 #include <zebra.h>
22 22
23 23 #include "command.h"
24 24 #include "thread.h"
25 25 #include "prefix.h"
26 26 #include "zclient.h"
27 27 #include "stream.h"
28 28 #include "network.h"
29 29 #include "log.h"
30 30 #include "memory.h"
31 +#include "hash.h"
32 +#include "jhash.h"
31 33
32 34 #include "bgpd/bgpd.h"
33 35 #include "bgpd/bgp_table.h"
34 36 #include "bgpd/bgp_route.h"
35 37 #include "bgpd/bgp_attr.h"
36 38 #include "bgpd/bgp_nexthop.h"
37 39 #include "bgpd/bgp_debug.h"
38 40 #include "bgpd/bgp_damp.h"
39 41 #include "zebra/rib.h"
40 42 #include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
517 519 zlog_debug ("Performing BGP general scanning");
518 520
519 521 bgp_scan (AFI_IP, SAFI_UNICAST);
520 522
521 523 #ifdef HAVE_IPV6
522 524 bgp_scan (AFI_IP6, SAFI_UNICAST);
523 525 #endif /* HAVE_IPV6 */
524 526
525 527 return 0;
526 528 }
529 +
530 +/* BGP own address structure */
531 +struct bgp_addr
532 +{
533 + struct in_addr addr;
534 + int refcnt;
535 +};
536 +
537 +static struct hash *bgp_address_hash;
538 +
539 +static void *
540 +bgp_address_hash_alloc (void *p)
541 +{
542 + struct in_addr *val = p;
543 + struct bgp_addr *addr;
544 +
545 + addr = XMALLOC (MTYPE_BGP_ADDR, sizeof (struct bgp_addr));
546 + addr->refcnt = 0;
547 + addr->addr.s_addr = val->s_addr;
548 +
549 + return addr;
550 +}
551 +
552 +static unsigned int
553 +bgp_address_hash_key_make (void *p)
554 +{
555 + const struct bgp_addr *addr = p;
556 +
557 + return jhash_1word(addr->addr.s_addr, 0);
558 +}
559 +
560 +static int
561 +bgp_address_hash_cmp (const void *p1, const void *p2)
562 +{
563 + const struct bgp_addr *addr1 = p1;
564 + const struct bgp_addr *addr2 = p2;
565 +
566 + return addr1->addr.s_addr == addr2->addr.s_addr;
567 +}
568 +
569 +void
570 +bgp_address_init (void)
571 +{
572 + bgp_address_hash = hash_create (bgp_address_hash_key_make,
573 + bgp_address_hash_cmp);
574 +}
575 +
576 +static void
577 +bgp_address_add (struct prefix *p)
578 +{
579 + struct bgp_addr tmp;
580 + struct bgp_addr *addr;
581 +
582 + tmp.addr = p->u.prefix4;
583 +
584 + addr = hash_get (bgp_address_hash, &tmp, bgp_address_hash_alloc);
585 + addr->refcnt++;
586 +}
587 +
588 +static void
589 +bgp_address_del (struct prefix *p)
590 +{
591 + struct bgp_addr tmp;
592 + struct bgp_addr *addr;
593 +
594 + tmp.addr = p->u.prefix4;
595 +
596 + addr = hash_lookup (bgp_address_hash, &tmp);
597 + addr->refcnt--;
598 +
599 + if (addr->refcnt == 0)
600 + {
601 + hash_release (bgp_address_hash, addr);
602 + XFREE (MTYPE_BGP_ADDR, addr);
603 + }
604 +}
605 +
527 606
528 607 struct bgp_connected_ref
529 608 {
530 609 unsigned int refcnt;
531 610 };
532 611
533 612 void
534 613 bgp_connected_add (struct connected *ifc)
535 614 {
536 615 struct prefix p;
550 629 addr = ifc->address;
551 630
552 631 if (addr->family == AF_INET)
553 632 {
554 633 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
555 634 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
556 635
557 636 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
558 637 return;
559 638
639 + bgp_address_add (addr);
640 +
560 641 rn = bgp_node_get (bgp_connected_table[AFI_IP], (struct prefix *) &p);
561 642 if (rn->info)
562 643 {
563 644 bc = rn->info;
564 645 bc->refcnt++;
565 646 }
566 647 else
567 648 {
568 649 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
569 650 bc->refcnt = 1;
615 696 addr = ifc->address;
616 697
617 698 if (addr->family == AF_INET)
618 699 {
619 700 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
620 701 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
621 702
622 703 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
623 704 return;
624 705
706 + bgp_address_del (addr);
707 +
625 708 rn = bgp_node_lookup (bgp_connected_table[AFI_IP], &p);
626 709 if (! rn)
627 710 return;
628 711
629 712 bc = rn->info;
630 713 bc->refcnt--;
631 714 if (bc->refcnt == 0)
632 715 {
633 716 XFREE (MTYPE_BGP_CONN, bc);
634 717 rn->info = NULL;
659 742 XFREE (MTYPE_BGP_CONN, bc);
660 743 rn->info = NULL;
661 744 }
662 745 bgp_unlock_node (rn);
663 746 bgp_unlock_node (rn);
664 747 }
665 748 #endif /* HAVE_IPV6 */
666 749 }
667 750
668 751 int
669 -bgp_nexthop_self (afi_t afi, struct attr *attr)
752 +bgp_nexthop_self (struct attr *attr)
670 753 {
671 - struct listnode *node;
672 - struct listnode *node2;
673 - struct interface *ifp;
674 - struct connected *ifc;
675 - struct prefix *p;
754 + struct bgp_addr tmp, *addr;
676 755
677 - for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
678 - {
679 - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
680 - {
681 - p = ifc->address;
756 + tmp.addr = attr->nexthop;
757 +
758 + addr = hash_lookup (bgp_address_hash, &tmp);
759 + if (addr)
760 + return 1;
682 761
683 - if (p && p->family == AF_INET
684 - && IPV4_ADDR_SAME (&p->u.prefix4, &attr->nexthop))
685 - return 1;
686 - }
687 - }
688 762 return 0;
689 763 }
690 764
691 765 static struct bgp_nexthop_cache *
692 766 zlookup_read (void)
693 767 {
694 768 struct stream *s;
695 769 uint16_t length;
696 770 u_char marker;
697 771 u_char version;

Everything looks good. We'll let you know here if there's anything you should know about.

Add shortcut