]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge remote-tracking branch 'origin/stable/3.0'
authorDonald Sharp <sharpd@cumulusnetworks.com>
Mon, 8 May 2017 20:51:21 +0000 (16:51 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Mon, 8 May 2017 20:51:21 +0000 (16:51 -0400)
12 files changed:
1  2 
bgpd/bgp_vty.c
configure.ac
doc/Building_FRR_on_Ubuntu1604.md
lib/thread.c
lib/thread.h
ospfd/ospf_vty.c
pimd/pim_cmd.c
pimd/pim_iface.c
pimd/pim_rp.c
pimd/pim_vty.c
pimd/pim_zebra.c
zebra/interface.c

diff --combined bgpd/bgp_vty.c
index 31f7872de222c91ad0f516cee09d22e9f8317209,9d954e5007ef8c84a3cf0ed620dea9c135463d8d..b41ffa6e5296dcd8493566d5aac84855d91b70eb
@@@ -60,73 -60,6 +60,73 @@@ Software Foundation, Inc., 59 Temple Pl
  
  static struct peer_group *
  listen_range_exists (struct bgp *bgp, struct prefix *range, int exact);
 +#if 0
 +#define INSTALL_CMD_ON_AF_NODES(cmd) \
 +  install_element(BGP_IPV4_NODE, cmd); \
 +  install_element(BGP_IPV4M_NODE, cmd); \
 +  install_element(BGP_IPV4L_NODE, cmd); \
 +  install_element(BGP_IPV6_NODE, cmd); \
 +  install_element(BGP_IPV6M_NODE, cmd); \
 +  install_element(BGP_IPV6L_NODE, cmd); \
 +  install_element(BGP_VPNV4_NODE, cmd);
 +#endif
 +static enum node_type
 +bgp_node_type (afi_t afi, safi_t safi)
 +{
 +  switch (afi)
 +    {
 +    case AFI_IP:
 +      switch (safi)
 +        {
 +        case SAFI_UNICAST:
 +          return BGP_IPV4_NODE;
 +          break;
 +        case SAFI_MULTICAST:
 +          return BGP_IPV4M_NODE;
 +          break;
 +        case SAFI_LABELED_UNICAST:
 +          return BGP_IPV4L_NODE;
 +          break;
 +        case SAFI_MPLS_VPN:
 +          return BGP_VPNV4_NODE;
 +          break;
 +        case SAFI_ENCAP:
 +          return BGP_ENCAP_NODE;
 +          break;
 +       }
 +      break;
 +    case AFI_IP6:
 +      switch (safi)
 +        {
 +        case SAFI_UNICAST:
 +          return BGP_IPV6_NODE;
 +          break;
 +        case SAFI_MULTICAST:
 +          return BGP_IPV6M_NODE;
 +          break;
 +        case SAFI_LABELED_UNICAST:
 +          return BGP_IPV6L_NODE;
 +          break;
 +        case SAFI_MPLS_VPN:
 +          return BGP_VPNV6_NODE;
 +          break;
 +        case SAFI_ENCAP:
 +          return BGP_ENCAP_NODE;
 +          break;
 +        }
 +      break;
 +    case AFI_L2VPN:
 +      return BGP_EVPN_NODE;
 +      break;
 +    case AFI_MAX:
 +      // We should never be here but to clarify the switch statement..
 +      return BGP_IPV4_NODE;
 +      break;
 +    }
 +
 +  // Impossible to happen
 +  return BGP_IPV4_NODE;
 +}
  
  /* Utility function to get address family from current node.  */
  afi_t
@@@ -137,7 -70,6 +137,7 @@@ bgp_node_afi (struct vty *vty
      {
      case BGP_IPV6_NODE:
      case BGP_IPV6M_NODE:
 +    case BGP_IPV6L_NODE:
      case BGP_VPNV6_NODE:
      case BGP_ENCAPV6_NODE:
        afi = AFI_IP6;
@@@ -175,10 -107,6 +175,10 @@@ bgp_node_safi (struct vty *vty
      case BGP_EVPN_NODE:
        safi = SAFI_EVPN;
        break;
 +    case BGP_IPV4L_NODE:
 +    case BGP_IPV6L_NODE:
 +      safi = SAFI_LABELED_UNICAST;
 +      break;
      default:
        safi = SAFI_UNICAST;
        break;
@@@ -232,7 -160,7 +232,7 @@@ argv_find_and_parse_afi(struct cmd_toke
    return ret;
  }
  
 -/* supports <unicast|multicast|vpn|encap> */
 +/* supports <unicast|multicast|vpn|encap|labeled-unicast> */
  safi_t
  bgp_vty_safi_from_arg(const char *safi_str)
  {
      safi = SAFI_ENCAP;
    else if (strncmp (safi_str, "v", 1) == 0)
      safi = SAFI_MPLS_VPN;
 +  else if (strncmp (safi_str, "l", 1) == 0)
 +    safi = SAFI_LABELED_UNICAST;
    return safi;
  }
  
@@@ -266,12 -192,6 +266,12 @@@ argv_find_and_parse_safi (struct cmd_to
        if (safi)
          *safi = SAFI_MULTICAST;
      }
 +   else if (argv_find (argv, argc, "labeled-unicast", index))
 +    {
 +      ret = 1;
 +      if (safi)
 +        *safi = SAFI_LABELED_UNICAST;
 +    }
    else if (argv_find (argv, argc, "vpn", index))
      {
        ret = 1;
   * that is being parsed.
   *
   * The show commands are generally of the form:
 - * "show [ip] bgp [<view|vrf> WORD] [<ipv4|ipv6> [<unicast|multicast|vpn|encap>]] ..."
 + * "show [ip] bgp [<view|vrf> WORD] [<ipv4|ipv6> [<unicast|multicast|vpn|encap|labeled-unicast>]] ..."
   *
   * Since we use argv_find if the show command in particular doesn't have:
   * [ip]
   * [<view|vrf> WORD]
 - * [<ipv4|ipv6> [<unicast|multicast|vpn|encap>]]
 + * [<ipv4|ipv6> [<unicast|multicast|vpn|encap|labeled-unicast>]]
   * The command parsing should still be ok.
   *
   * vty  -> The vty for the command so we can output some useful data in
@@@ -342,7 -262,6 +342,6 @@@ bgp_vty_find_and_parse_afi_safi_bgp (st
    if (argv_find (argv, argc, "view", idx) || argv_find (argv, argc, "vrf", idx))
      {
        vrf_name = argv[*idx + 1]->arg;
-       *idx += 2;
  
        if (strmatch (vrf_name, "all"))
          *bgp = NULL;
@@@ -5731,16 -5650,30 +5730,16 @@@ DEFUN (no_neighbor_addpath_tx_bestpath_
  
  DEFUN_NOSH (address_family_ipv4_safi,
         address_family_ipv4_safi_cmd,
 -       "address-family ipv4 [<unicast|multicast|vpn|encap>]",
 +       "address-family ipv4 [<unicast|multicast|vpn|encap|labeled-unicast>]",
         "Enter Address Family command mode\n"
         "Address Family\n"
         BGP_SAFI_HELP_STR)
  {
 -  int idx_safi = 2;
 -  if (argc == (idx_safi + 1))
 +
 +  if (argc == 3)
      {
 -      switch (bgp_vty_safi_from_arg(argv[idx_safi]->arg))
 -        {
 -        case SAFI_MULTICAST:
 -          vty->node = BGP_IPV4M_NODE;
 -          break;
 -        case SAFI_ENCAP:
 -          vty->node = BGP_ENCAP_NODE;
 -          break;
 -        case SAFI_MPLS_VPN:
 -          vty->node = BGP_VPNV4_NODE;
 -          break;
 -        case SAFI_UNICAST:
 -        default:
 -          vty->node = BGP_IPV4_NODE;
 -          break;
 -        }
 +      safi_t safi = bgp_vty_safi_from_arg(argv[2]->arg);
 +      vty->node = bgp_node_type(AFI_IP, safi);
      }
    else
      vty->node = BGP_IPV4_NODE;
  
  DEFUN_NOSH (address_family_ipv6_safi,
         address_family_ipv6_safi_cmd,
 -       "address-family ipv6 [<unicast|multicast|vpn|encap>]",
 +       "address-family ipv6 [<unicast|multicast|vpn|encap|labeled-unicast>]",
         "Enter Address Family command mode\n"
         "Address Family\n"
         BGP_SAFI_HELP_STR)
  {
 -  int idx_safi = 2;
 -  if (argc == (idx_safi + 1))
 +  if (argc == 3)
      {
 -      switch (bgp_vty_safi_from_arg(argv[idx_safi]->arg))
 -        {
 -        case SAFI_MULTICAST:
 -          vty->node = BGP_IPV6M_NODE;
 -          break;
 -        case SAFI_ENCAP:
 -          vty->node = BGP_ENCAPV6_NODE;
 -          break;
 -        case SAFI_MPLS_VPN:
 -          vty->node = BGP_VPNV6_NODE;
 -          break;
 -        case SAFI_UNICAST:
 -        default:
 -          vty->node = BGP_IPV6_NODE;
 -          break;
 -        }
 +      safi_t safi = bgp_vty_safi_from_arg(argv[2]->arg);
 +      vty->node = bgp_node_type(AFI_IP6, safi);
      }
    else
      vty->node = BGP_IPV6_NODE;
@@@ -5831,11 -5779,9 +5830,11 @@@ DEFUN_NOSH (exit_address_family
  {
    if (vty->node == BGP_IPV4_NODE
        || vty->node == BGP_IPV4M_NODE
 +      || vty->node == BGP_IPV4L_NODE
        || vty->node == BGP_VPNV4_NODE
        || vty->node == BGP_IPV6_NODE
        || vty->node == BGP_IPV6M_NODE
 +      || vty->node == BGP_IPV6L_NODE
        || vty->node == BGP_VPNV6_NODE
        || vty->node == BGP_ENCAP_NODE
        || vty->node == BGP_ENCAPV6_NODE
@@@ -6761,7 -6707,6 +6760,7 @@@ bgp_show_summary_afi_safi (struct vty *
    int afi_wildcard  = (afi == AFI_MAX);
    int safi_wildcard = (safi == SAFI_MAX);
    int is_wildcard   = (afi_wildcard || safi_wildcard);
 +  bool json_output = false;
  
    if (use_json && is_wildcard)
      vty_out (vty, "{%s", VTY_NEWLINE);
          {
            if (bgp_show_summary_afi_safi_peer_exists (bgp, afi, safi))
              {
 +              json_output = true;
                if (is_wildcard)
                  {
                    /*
  
    if (use_json && is_wildcard)
      vty_out (vty, "}%s", VTY_NEWLINE);
 -
 +  else if (use_json && !json_output)
 +    vty_out (vty, "{}%s", VTY_NEWLINE);
  }
  
  static void
@@@ -6943,8 -6886,6 +6942,8 @@@ afi_safi_print (afi_t afi, safi_t safi
      return "IPv4 Unicast";
    else if (afi == AFI_IP && safi == SAFI_MULTICAST)
      return "IPv4 Multicast";
 +  else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST)
 +    return "IPv4 labeled-unicast";
    else if (afi == AFI_IP && safi == SAFI_MPLS_VPN)
      return "IPv4 VPN";
    else if (afi == AFI_IP && safi == SAFI_ENCAP)
      return "IPv6 Unicast";
    else if (afi == AFI_IP6 && safi == SAFI_MULTICAST)
      return "IPv6 Multicast";
 +  else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST)
 +    return "IPv6 labeled-unicast";
    else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN)
      return "IPv6 VPN";
    else if (afi == AFI_IP6 && safi == SAFI_ENCAP)
@@@ -6978,8 -6917,6 +6977,8 @@@ afi_safi_json (afi_t afi, safi_t safi
      return "ipv4Unicast";
    else if (afi == AFI_IP && safi == SAFI_MULTICAST)
      return "ipv4Multicast";
 +  else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST)
 +    return "ipv4LabeledUnicast";
    else if (afi == AFI_IP && safi == SAFI_MPLS_VPN)
      return "ipv4Vpn";
    else if (afi == AFI_IP && safi == SAFI_ENCAP)
      return "ipv6Unicast";
    else if (afi == AFI_IP6 && safi == SAFI_MULTICAST)
      return "ipv6Multicast";
 +  else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST)
 +    return "ipv6LabeledUnicast";
    else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN)
      return "ipv6Vpn";
    else if (afi == AFI_IP6 && safi == SAFI_ENCAP)
@@@ -10121,13 -10056,6 +10120,13 @@@ static struct cmd_node bgp_ipv4_multica
    1,
  };
  
 +static struct cmd_node bgp_ipv4_labeled_unicast_node =
 +{
 +  BGP_IPV4L_NODE,
 +  "%s(config-router-af)# ",
 +  1,
 +};
 +
  static struct cmd_node bgp_ipv6_unicast_node =
  {
    BGP_IPV6_NODE,
@@@ -10142,13 -10070,6 +10141,13 @@@ static struct cmd_node bgp_ipv6_multica
    1,
  };
  
 +static struct cmd_node bgp_ipv6_labeled_unicast_node =
 +{
 +  BGP_IPV6L_NODE,
 +  "%s(config-router-af)# ",
 +  1,
 +};
 +
  static struct cmd_node bgp_vpnv4_node =
  {
    BGP_VPNV4_NODE,
@@@ -10193,10 -10114,8 +10192,10 @@@ bgp_vty_init (void
    install_node (&bgp_node, bgp_config_write);
    install_node (&bgp_ipv4_unicast_node, NULL);
    install_node (&bgp_ipv4_multicast_node, NULL);
 +  install_node (&bgp_ipv4_labeled_unicast_node, NULL);
    install_node (&bgp_ipv6_unicast_node, NULL);
    install_node (&bgp_ipv6_multicast_node, NULL);
 +  install_node (&bgp_ipv6_labeled_unicast_node, NULL);
    install_node (&bgp_vpnv4_node, NULL);
    install_node (&bgp_vpnv6_node, NULL);
    install_node (&bgp_encap_node, NULL);
    install_default (BGP_NODE);
    install_default (BGP_IPV4_NODE);
    install_default (BGP_IPV4M_NODE);
 +  install_default (BGP_IPV4L_NODE);
    install_default (BGP_IPV6_NODE);
    install_default (BGP_IPV6M_NODE);
 +  install_default (BGP_IPV6L_NODE);
    install_default (BGP_VPNV4_NODE);
    install_default (BGP_VPNV6_NODE);
    install_default (BGP_ENCAP_NODE);
    install_element (BGP_IPV6_NODE, &bgp_maxpaths_cmd);
    install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_cmd);
    install_element (BGP_NODE, &bgp_maxpaths_ibgp_cmd);
 -  install_element(BGP_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
 +  install_element (BGP_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
    install_element (BGP_NODE, &no_bgp_maxpaths_ibgp_cmd);
    install_element (BGP_IPV4_NODE, &bgp_maxpaths_ibgp_cmd);
 -  install_element(BGP_IPV4_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
 +  install_element (BGP_IPV4_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
    install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_ibgp_cmd);
    install_element (BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cmd);
 -  install_element(BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
 +  install_element (BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
    install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_ibgp_cmd);
  
 +  install_element (BGP_IPV4L_NODE, &bgp_maxpaths_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_bgp_maxpaths_cmd);
 +  install_element (BGP_IPV6L_NODE, &bgp_maxpaths_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_bgp_maxpaths_cmd);
 +
 +  install_element (BGP_IPV4L_NODE, &bgp_maxpaths_ibgp_cmd);
 +  install_element (BGP_IPV4L_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_bgp_maxpaths_ibgp_cmd);
 +  install_element (BGP_IPV6L_NODE, &bgp_maxpaths_ibgp_cmd);
 +  install_element (BGP_IPV6L_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_bgp_maxpaths_ibgp_cmd);
 +
    /* "timers bgp" commands. */
    install_element (BGP_NODE, &bgp_timers_cmd);
    install_element (BGP_NODE, &no_bgp_timers_cmd);
    install_element (BGP_NODE, &neighbor_activate_cmd);
    install_element (BGP_IPV4_NODE, &neighbor_activate_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_activate_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_activate_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_activate_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_activate_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_activate_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_activate_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_activate_cmd);
    install_element (BGP_ENCAP_NODE, &neighbor_activate_cmd);
    install_element (BGP_NODE, &no_neighbor_activate_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_activate_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_activate_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_activate_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_activate_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_activate_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_activate_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_activate_cmd);
    install_element (BGP_VPNV6_NODE, &no_neighbor_activate_cmd);
    install_element (BGP_ENCAP_NODE, &no_neighbor_activate_cmd);
    install_element (BGP_NODE, &neighbor_set_peer_group_cmd);
    install_element (BGP_IPV4_NODE, &neighbor_set_peer_group_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_set_peer_group_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_set_peer_group_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_set_peer_group_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_set_peer_group_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_set_peer_group_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_set_peer_group_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_set_peer_group_cmd);
    install_element (BGP_ENCAP_NODE, &neighbor_set_peer_group_cmd);
    install_element (BGP_NODE, &no_neighbor_set_peer_group_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_set_peer_group_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_set_peer_group_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_set_peer_group_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_set_peer_group_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_set_peer_group_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_set_peer_group_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_set_peer_group_cmd);
    install_element (BGP_VPNV6_NODE, &no_neighbor_set_peer_group_cmd);
    install_element (BGP_ENCAP_NODE, &no_neighbor_set_peer_group_cmd);
    install_element (BGP_NODE, &no_neighbor_soft_reconfiguration_cmd);
    install_element (BGP_IPV4_NODE, &neighbor_soft_reconfiguration_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_soft_reconfiguration_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_soft_reconfiguration_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_soft_reconfiguration_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_soft_reconfiguration_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_soft_reconfiguration_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_soft_reconfiguration_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_soft_reconfiguration_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_soft_reconfiguration_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_soft_reconfiguration_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_soft_reconfiguration_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_soft_reconfiguration_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_soft_reconfiguration_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_soft_reconfiguration_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_soft_reconfiguration_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_attr_unchanged_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_attr_unchanged_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_attr_unchanged_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_attr_unchanged_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_attr_unchanged_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_attr_unchanged_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_attr_unchanged_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_attr_unchanged_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_attr_unchanged_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_attr_unchanged_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_attr_unchanged_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_attr_unchanged_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_attr_unchanged_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_nexthop_self_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_nexthop_self_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_nexthop_self_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_nexthop_self_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_nexthop_self_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_nexthop_self_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_nexthop_self_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_nexthop_self_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_nexthop_self_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_nexthop_self_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_nexthop_self_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_nexthop_self_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_nexthop_self_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_nexthop_self_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_nexthop_self_force_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_nexthop_self_force_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_nexthop_self_force_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_nexthop_self_force_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_nexthop_self_force_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_nexthop_self_force_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_nexthop_self_force_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_nexthop_self_force_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_nexthop_self_force_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_nexthop_self_force_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_nexthop_self_force_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_nexthop_self_force_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_nexthop_self_force_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_nexthop_self_force_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_as_override_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_as_override_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_as_override_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_as_override_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_as_override_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_as_override_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_as_override_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_as_override_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_as_override_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_as_override_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_as_override_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_as_override_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_as_override_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_as_override_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_replace_as_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_all_replace_as_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_remove_private_as_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_remove_private_as_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_remove_private_as_all_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_remove_private_as_all_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_remove_private_as_replace_as_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_remove_private_as_replace_as_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_remove_private_as_all_replace_as_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_all_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_replace_as_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_all_replace_as_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_remove_private_as_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_remove_private_as_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_remove_private_as_all_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_remove_private_as_all_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_remove_private_as_replace_as_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_remove_private_as_replace_as_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_remove_private_as_all_replace_as_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_all_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_send_community_type_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_send_community_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_send_community_type_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_send_community_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_send_community_type_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_send_community_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_send_community_type_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_send_community_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_send_community_type_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_send_community_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_send_community_type_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_send_community_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_send_community_type_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_send_community_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_send_community_type_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_send_community_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_send_community_type_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_send_community_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_send_community_type_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_send_community_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_route_reflector_client_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_route_reflector_client_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_route_reflector_client_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_route_reflector_client_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_route_reflector_client_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_route_reflector_client_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_route_reflector_client_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_route_reflector_client_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_route_reflector_client_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_route_reflector_client_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_route_reflector_client_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_route_reflector_client_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_route_reflector_client_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_route_reflector_client_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_route_server_client_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_route_server_client_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_route_server_client_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_route_server_client_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_route_server_client_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_route_server_client_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_route_server_client_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_route_server_client_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_route_server_client_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_route_server_client_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_route_server_client_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_route_server_client_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_route_server_client_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_route_server_client_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_addpath_tx_all_paths_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_addpath_tx_all_paths_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_addpath_tx_all_paths_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_addpath_tx_all_paths_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_addpath_tx_all_paths_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_addpath_tx_all_paths_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_addpath_tx_all_paths_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_addpath_tx_all_paths_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_addpath_tx_all_paths_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_addpath_tx_all_paths_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_addpath_tx_all_paths_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_addpath_tx_all_paths_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_addpath_tx_all_paths_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_addpath_tx_all_paths_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_capability_orf_prefix_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_capability_orf_prefix_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_capability_orf_prefix_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_capability_orf_prefix_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_capability_orf_prefix_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_capability_orf_prefix_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_capability_orf_prefix_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_capability_orf_prefix_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_capability_orf_prefix_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_capability_orf_prefix_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_capability_orf_prefix_cmd);
  
    /* "neighbor capability dynamic" commands.*/
    install_element (BGP_NODE, &neighbor_capability_dynamic_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_default_originate_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_default_originate_rmap_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_default_originate_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_default_originate_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_default_originate_rmap_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_default_originate_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_default_originate_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_default_originate_rmap_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_default_originate_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_default_originate_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_default_originate_rmap_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_default_originate_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_default_originate_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_default_originate_rmap_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_default_originate_cmd);
  
    /* "neighbor port" commands. */
    install_element (BGP_NODE, &neighbor_port_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_weight_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_weight_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_weight_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_weight_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_weight_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_weight_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_weight_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_weight_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_weight_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_weight_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_weight_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_weight_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_weight_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_weight_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_distribute_list_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_distribute_list_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_distribute_list_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_distribute_list_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_distribute_list_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_distribute_list_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_distribute_list_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_distribute_list_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_distribute_list_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_distribute_list_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_distribute_list_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_distribute_list_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_distribute_list_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_distribute_list_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_prefix_list_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_prefix_list_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_prefix_list_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_prefix_list_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_prefix_list_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_prefix_list_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_prefix_list_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_prefix_list_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_prefix_list_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_prefix_list_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_prefix_list_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_prefix_list_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_prefix_list_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_prefix_list_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_filter_list_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_filter_list_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_filter_list_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_filter_list_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_filter_list_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_filter_list_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_filter_list_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_filter_list_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_filter_list_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_filter_list_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_filter_list_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_filter_list_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_filter_list_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_filter_list_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_route_map_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_route_map_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_route_map_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_route_map_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_route_map_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_route_map_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_route_map_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_route_map_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_route_map_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_route_map_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_route_map_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_route_map_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_route_map_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_route_map_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_unsuppress_map_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_unsuppress_map_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_unsuppress_map_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_unsuppress_map_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_unsuppress_map_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_unsuppress_map_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_unsuppress_map_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_unsuppress_map_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_unsuppress_map_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_unsuppress_map_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_unsuppress_map_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_unsuppress_map_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_unsuppress_map_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_unsuppress_map_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_maximum_prefix_restart_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_maximum_prefix_threshold_restart_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_maximum_prefix_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_maximum_prefix_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_maximum_prefix_threshold_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_maximum_prefix_warning_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_maximum_prefix_threshold_warning_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_maximum_prefix_restart_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_maximum_prefix_threshold_restart_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_maximum_prefix_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_maximum_prefix_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_maximum_prefix_threshold_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_maximum_prefix_warning_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_maximum_prefix_restart_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_maximum_prefix_threshold_restart_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_maximum_prefix_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_maximum_prefix_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_maximum_prefix_threshold_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_maximum_prefix_warning_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_maximum_prefix_threshold_warning_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_maximum_prefix_restart_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_maximum_prefix_threshold_restart_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_maximum_prefix_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_maximum_prefix_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_maximum_prefix_threshold_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_maximum_prefix_warning_cmd);
    install_element (BGP_IPV4_NODE, &no_neighbor_allowas_in_cmd);
    install_element (BGP_IPV4M_NODE, &neighbor_allowas_in_cmd);
    install_element (BGP_IPV4M_NODE, &no_neighbor_allowas_in_cmd);
 +  install_element (BGP_IPV4L_NODE, &neighbor_allowas_in_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_neighbor_allowas_in_cmd);
    install_element (BGP_IPV6_NODE, &neighbor_allowas_in_cmd);
    install_element (BGP_IPV6_NODE, &no_neighbor_allowas_in_cmd);
    install_element (BGP_IPV6M_NODE, &neighbor_allowas_in_cmd);
    install_element (BGP_IPV6M_NODE, &no_neighbor_allowas_in_cmd);
 +  install_element (BGP_IPV6L_NODE, &neighbor_allowas_in_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_neighbor_allowas_in_cmd);
    install_element (BGP_VPNV4_NODE, &neighbor_allowas_in_cmd);
    install_element (BGP_VPNV4_NODE, &no_neighbor_allowas_in_cmd);
    install_element (BGP_VPNV6_NODE, &neighbor_allowas_in_cmd);
    /* "exit-address-family" command. */
    install_element (BGP_IPV4_NODE, &exit_address_family_cmd);
    install_element (BGP_IPV4M_NODE, &exit_address_family_cmd);
 +  install_element (BGP_IPV4L_NODE, &exit_address_family_cmd);
    install_element (BGP_IPV6_NODE, &exit_address_family_cmd);
    install_element (BGP_IPV6M_NODE, &exit_address_family_cmd);
 +  install_element (BGP_IPV6L_NODE, &exit_address_family_cmd);
    install_element (BGP_VPNV4_NODE, &exit_address_family_cmd);
    install_element (BGP_VPNV6_NODE, &exit_address_family_cmd);
    install_element (BGP_ENCAP_NODE, &exit_address_family_cmd);
diff --combined configure.ac
index 9bdcfd1e65a8d6e3aab9f3b1ab6b1966c75ceed3,d9bed28c95468b6a51a394b1b19413fbc798bad9..919902d938738241196cbfea30c64b75e08d38d6
@@@ -7,7 -7,7 +7,7 @@@
  ##
  AC_PREREQ(2.60)
  
 -AC_INIT(frr, 3.0, [https://github.com/frrouting/frr/issues])
 +AC_INIT(frr, 3.1-dev, [https://github.com/frrouting/frr/issues])
  PACKAGE_URL="https://frrouting.org/"
  PACKAGE_FULLNAME="FRRouting"
  AC_SUBST(PACKAGE_FULLNAME)
@@@ -73,10 -73,6 +73,10 @@@ LIBS="$LIBS -ltcmalloc_minimal
  esac],[tcmalloc_enabled=false])
  
  
 +dnl Thanks autoconf, but we don't want a default -g -O2.  We have our own
 +dnl flag determination logic.
 +CFLAGS="${CFLAGS:-}"
 +
  dnl --------------------
  dnl Check CC and friends
  dnl --------------------
@@@ -89,7 -85,6 +89,7 @@@ AM_PROG_CC_C_
  dnl remove autoconf default "-g -O2"
  CFLAGS="$orig_cflags"
  AC_PROG_CC_C99
 +dnl NB: see C11 below
  
  AC_PROG_EGREP
  PKG_PROG_PKG_CONFIG
@@@ -101,7 -96,7 +101,7 @@@ AC_CHECK_PROG([SED],[sed],[sed],[/bin/f
  dnl try and enable CFLAGS that are useful for Quagga
  dnl - specifically, options to control warnings
  
 -AC_USE_SYSTEM_EXTENSIONS()
 +AC_USE_SYSTEM_EXTENSIONS
  AC_DEFUN([AC_C_FLAG], [{
        AC_LANG_PUSH(C)
        ac_c_flag_save="$CFLAGS"
@@@ -127,13 -122,6 +127,13 @@@ dnl ICC won't bail on unknown options w
  dnl need to do this first so we get useful results for the other options
  AC_C_FLAG([-diag-error 10006])
  
 +dnl AC_PROG_CC_C99 may change CC to include -std=gnu99 or something
 +ac_cc="$CC"
 +CC="${CC% -std=gnu99}"
 +CC="${CC% -std=c99}"
 +
 +AC_C_FLAG([-std=gnu11], [CC="$ac_cc"], [CC="$CC -std=gnu11"])
 +
  dnl if the user specified any CFLAGS, we don't add "-g -Os/-O2" here
  if test "z$orig_cflags" = "z"; then
    AC_C_FLAG([-g])
@@@ -189,18 -177,6 +189,18 @@@ AC_LINK_IFELSE
        ])
  AC_LANG_POP(C)
  
 +dnl ----------
 +dnl Essentials
 +dnl ----------
 +
 +AX_PTHREAD([
 +  CC="$PTHREAD_CC"
 +  CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
 +  LIBS="$PTHREAD_LIBS $LIBS"
 +], [
 +  AC_MSG_FAILURE([This Quagga version needs pthreads])
 +])
 +
  dnl --------------
  dnl Check programs
  dnl --------------
@@@ -248,8 -224,6 +248,8 @@@ AC_ARG_ENABLE(ldpd
    AS_HELP_STRING([--enable-ldpd], [build ldpd]))
  AC_ARG_ENABLE(nhrpd,
    AS_HELP_STRING([--disable-nhrpd], [do not build nhrpd]))
 +AC_ARG_ENABLE(eigrpd,
 +  AS_HELP_STRING([--disable-eigrpd], [do not build eigrpd]))
  AC_ARG_ENABLE(watchfrr,
    AS_HELP_STRING([--disable-watchfrr], [do not build watchfrr]))
  AC_ARG_ENABLE(isisd,
@@@ -315,8 -289,6 +315,8 @@@ AC_ARG_ENABLE(werror
    AS_HELP_STRING([--enable-werror], [enable -Werror (recommended for developers only)]))
  AC_ARG_ENABLE(cumulus,
    AS_HELP_STRING([--enable-cumulus], [enable Cumulus Switch Special Extensions]))
 +AC_ARG_ENABLE(datacenter,
 +  AS_HELP_STRING([--enable-datacenter], [enable Compilation for Data Center Extensions]))
  AC_ARG_ENABLE(rr-semantics,
    AS_HELP_STRING([--disable-rr-semantics], [disable the v6 Route Replace semantics]))
  AC_ARG_ENABLE([protobuf],
@@@ -362,7 -334,7 +362,7 @@@ if test "${enable_rr_semantics}" != "no
  fi
  
  if test "${enable_poll}" = "yes" ; then
-   AC_DEFINE(HAVE_POLL,,Compile systemd support in)
+   AC_DEFINE(HAVE_POLL_CALL,,Compile systemd support in)
  fi
  
  dnl ----------
@@@ -371,11 -343,11 +371,11 @@@ dnl ---------
  AC_MSG_CHECKING(whether this OS has MPLS stack)
  case "$host" in
    *-linux*)
 -      MPLS_METHOD="zebra_mpls_netlink.o"
 +      MPLS_METHOD="zebra_mpls_netlink.o zebra_mpls.o"
        AC_MSG_RESULT(Linux MPLS)
    ;;
    *-openbsd*)
 -      MPLS_METHOD="zebra_mpls_openbsd.o"
 +      MPLS_METHOD="zebra_mpls_openbsd.o zebra_mpls.o"
        AC_MSG_RESULT(OpenBSD MPLS)
    ;;
    *)
  esac
  AC_SUBST(MPLS_METHOD)
  
 -if test "${enable_cumulus}" = "yes" ; then
 -  AC_DEFINE(HAVE_CUMULUS,,Compile Special Cumulus Code in)
 +if test "${enable_datacenter}" = "yes" ; then
 +  AC_DEFINE(HAVE_DATACENTER,,Compile extensions for a DataCenter)
    DFLT_NAME="datacenter"
  else
    DFLT_NAME="traditional"
  fi
 +
 +if test "${enable_cumulus}" = "yes" ; then
 +  AC_DEFINE(HAVE_CUMULUS,,Compile Special Cumulus Code in)
 +fi
 +
  AC_SUBST(DFLT_NAME)
  AC_DEFINE_UNQUOTED(DFLT_NAME,["$DFLT_NAME"], Name of the configuration default set)
  
@@@ -572,72 -539,6 +572,72 @@@ AC_CHECK_HEADERS([stropts.h sys/ksym.h 
        linux/version.h asm/types.h \
        sys/cdefs.h])
  
 +ac_stdatomic_ok=false
 +AC_DEFINE(FRR_AUTOCONF_ATOMIC, 1, [did autoconf checks for atomic funcs])
 +AC_CHECK_HEADER([stdatomic.h],[
 +
 +  AC_MSG_CHECKING([whether _Atomic qualifier works])
 +  AC_LINK_IFELSE([AC_LANG_SOURCE([[
 +#include <stdatomic.h>
 +int main(int argc, char **argv) {
 +  _Atomic int i = 0;
 +  return i;
 +}
 +]])], [
 +    AC_DEFINE(HAVE_STDATOMIC_H, 1, [found stdatomic.h])
 +    AC_MSG_RESULT([yes])
 +    ac_stdatomic_ok=true
 +  ], [
 +    AC_MSG_RESULT([no])
 +  ])
 +])
 +
 +AS_IF([$ac_stdatomic_ok], [true], [
 +  AC_MSG_CHECKING([for __atomic_* builtins])
 +  AC_LINK_IFELSE([AC_LANG_SOURCE([[
 +int main(int argc, char **argv) {
 +  volatile int i = 1;
 +  __atomic_store_n (&i, 0, __ATOMIC_RELEASE);
 +  return __atomic_load_n (&i, __ATOMIC_ACQUIRE);
 +}
 +]])], [
 +    AC_DEFINE(HAVE___ATOMIC, 1, [found __atomic builtins])
 +    AC_MSG_RESULT([yes])
 +  ], [
 +    AC_MSG_RESULT([no])
 +
 +    dnl FreeBSD 9 has a broken stdatomic.h where _Atomic doesn't work
 +    AC_MSG_CHECKING([for __sync_* builtins])
 +    AC_LINK_IFELSE([AC_LANG_SOURCE([[
 +int main(int argc, char **argv) {
 +  volatile int i = 1;
 +  __sync_fetch_and_sub (&i, 1);
 +  return __sync_val_compare_and_swap (&i, 0, 1);
 +}
 +]])], [
 +      AC_DEFINE(HAVE___SYNC, 1, [found __sync builtins])
 +      AC_MSG_RESULT([yes])
 +
 +      AC_MSG_CHECKING([for __sync_swap builtin])
 +      AC_LINK_IFELSE([AC_LANG_SOURCE([[
 +int main(int argc, char **argv) {
 +  volatile int i = 1;
 +  return __sync_swap (&i, 2);
 +}
 +]])], [
 +        AC_DEFINE(HAVE___SYNC_SWAP, 1, [found __sync_swap builtin])
 +        AC_MSG_RESULT([yes])
 +      ], [
 +        AC_MSG_RESULT([no])
 +      ])
 +
 +    ], [
 +      AC_MSG_RESULT([no])
 +      AC_MSG_FAILURE([stdatomic.h unavailable and $CC has neither __atomic nor __sync builtins])
 +    ])
 +  ])
 +])
 +
  dnl Utility macro to avoid retyping includes all the time
  m4_define([FRR_INCLUDES],
  [#ifdef SUNOS_5
  fi
  AM_CONDITIONAL(NHRPD, test "x$NHRPD" = "xnhrpd")
  
 +if test "${enable_eigrpd}" = "no";then
 +  EIGRPD=""
 +else
 +  EIGRPD="eigrpd"
 +fi
 +AM_CONDITIONAL(EIGRPD, test "x$EIGRPD" = "xeigrpd")
 +
  if test "${enable_watchfrr}" = "no";then
    WATCHFRR=""
  else
@@@ -1397,7 -1291,6 +1397,7 @@@ AC_SUBST(OSPFD
  AC_SUBST(OSPF6D)
  AC_SUBST(LDPD)
  AC_SUBST(NHRPD)
 +AC_SUBST(EIGRPD)
  AC_SUBST(WATCHFRR)
  AC_SUBST(ISISD)
  AC_SUBST(PIMD)
@@@ -1609,12 -1502,6 +1609,12 @@@ AC_TRY_COMPILE([#include <netinet/in.h>
    AC_MSG_RESULT(no)
  ])
  
 +dnl --------------------------------------
 +dnl checking for be32dec existence or not
 +dnl --------------------------------------
 +AC_CHECK_DECLS([be32enc, be32dec], [], [],
 +             [#include <sys/endian.h>])
 +
  dnl --------------------------------------
  dnl checking for clock_time monotonic struct and call
  dnl --------------------------------------
@@@ -1844,10 -1731,10 +1844,10 @@@ AC_CONFIG_FILES([Makefile lib/Makefile 
          ospf6d/Makefile ldpd/Makefile isisd/Makefile vtysh/Makefile
          doc/Makefile ospfclient/Makefile tests/Makefile m4/Makefile
          pimd/Makefile
 +        eigrpd/Makefile
          nhrpd/Makefile
          redhat/Makefile
          tools/Makefile
 -        cumulus/Makefile
          pkgsrc/Makefile
          fpm/Makefile
          redhat/frr.spec 
          doc/ospfd.8
          doc/ldpd.8
          doc/ripd.8
 +        doc/eigrpd.8
          doc/ripngd.8
          doc/pimd.8
          doc/nhrpd.8
          doc/zebra.8
          doc/frr.1
          pkgsrc/bgpd.sh pkgsrc/ospf6d.sh pkgsrc/ospfd.sh
 -        pkgsrc/ripd.sh pkgsrc/ripngd.sh pkgsrc/zebra.sh])
 +        pkgsrc/ripd.sh pkgsrc/ripngd.sh pkgsrc/zebra.sh
 +        pkgsrc/eigrpd.sh])
  
  if test "${enable_bgp_vnc}" != "no"; then
     if test "${with_rfp_path}" = "bgpd/rfp-example" ; then 
index 8b8bbf4bb2e2bb860230eeb16e3e0aa5df2dc26b,5715b701587bbaf0c8ff8c75d7e78fed983e32bd..09b5aa8b72cbf9bec8417accf46e296446f3a8c5
@@@ -14,7 -14,7 +14,7 @@@ Add packages
  
      apt-get install git autoconf automake libtool make gawk libreadline-dev \
         texinfo dejagnu pkg-config libpam0g-dev libjson-c-dev bison flex \
-        python-pytest libc-ares-dev python3-dev
+        python-pytest libc-ares-dev python3-dev libsystemd-dev
  
  Get FRR, compile it and install it (from Git)
  ---------------------------------------------
@@@ -56,6 -56,7 +56,7 @@@ an example.
          --enable-rtadv \
          --enable-tcp-zebra \
          --enable-fpm \
+       --enable-systemd=yes \
          --with-pkg-git-version \
          --with-pkg-extra-version=-MyOwnFRRVersion   
      make
@@@ -118,7 -119,7 +119,7 @@@ Add the following lines to `/etc/module
      sudo install -m 644 tools/frr.service /etc/systemd/system/frr.service  
      sudo install -m 644 cumulus/etc/default/frr /etc/default/frr  
      sudo install -m 644 cumulus/etc/frr/daemons /etc/frr/daemons  
 -    sudo install -m 644 cumulus/etc/frr/debian.conf /etc/frr/debian.conf  
 +    sudo install -m 644 cumulus/etc/frr/daemons.conf /etc/frr/daemons.conf  
      sudo install -m 644 cumulus/etc/frr/Frr.conf /etc/frr/Frr.conf  
      sudo install -m 644 -o frr -g frr cumulus/etc/frr/vtysh.conf /etc/frr/vtysh.conf   
  
@@@ -136,13 -137,8 +137,8 @@@ For example
      isisd=yes
  
  ### Enable the systemd serivce
- Edit `/etc/systemd/system/frr.service` and remove the line **OnFailure=heartbeat-failed@%n.service**  
- For example.
+  - systemctl enable frr
  
-     [Unit]  
-     Description=Cumulus Linux FRR  
-     After=syslog.target networking.service  
-  Â  Â 
  ### Start the systemd service
  - systemctl start frr
  - use `systemctl status frr` to check its status.
diff --combined lib/thread.c
index 74d498baf8e89d3c973d59e59711e8ac11922bd0,34802fcedd2477c11b7e47c2505ede8b3e675d72..3fb28bce26f0e0961a530f3025619d6c77eeed46
@@@ -41,7 -41,7 +41,7 @@@ DEFINE_MTYPE_STATIC(LIB, THREAD_STATS
  #include <mach/mach_time.h>
  #endif
  
 -/* Relative time, since startup */
 +static pthread_mutex_t cpu_record_mtx = PTHREAD_MUTEX_INITIALIZER;
  static struct hash *cpu_record = NULL;
  
  static unsigned long
@@@ -137,14 -137,9 +137,14 @@@ cpu_record_print(struct vty *vty, threa
    vty_out(vty, "Active   Runtime(ms)   Invoked Avg uSec Max uSecs");
    vty_out(vty, " Avg uSec Max uSecs");
    vty_out(vty, "  Type  Thread%s", VTY_NEWLINE);
 -  hash_iterate(cpu_record,
 -             (void(*)(struct hash_backet*,void*))cpu_record_hash_print,
 -             args);
 +
 +  pthread_mutex_lock (&cpu_record_mtx);
 +  {
 +    hash_iterate(cpu_record,
 +                 (void(*)(struct hash_backet*,void*))cpu_record_hash_print,
 +                 args);
 +  }
 +  pthread_mutex_unlock (&cpu_record_mtx);
  
    if (tmp.total_calls > 0)
      vty_out_cpu_thread_history(vty, &tmp);
@@@ -221,25 -216,16 +221,25 @@@ cpu_record_hash_clear (struct hash_back
    if ( !(a->types & *filter) )
         return;
    
 -  hash_release (cpu_record, bucket->data);
 +  pthread_mutex_lock (&cpu_record_mtx);
 +  {
 +    hash_release (cpu_record, bucket->data);
 +  }
 +  pthread_mutex_unlock (&cpu_record_mtx);
  }
  
  static void
  cpu_record_clear (thread_type filter)
  {
    thread_type *tmp = &filter;
 -  hash_iterate (cpu_record,
 -              (void (*) (struct hash_backet*,void*)) cpu_record_hash_clear,
 -              tmp);
 +
 +  pthread_mutex_lock (&cpu_record_mtx);
 +  {
 +    hash_iterate (cpu_record,
 +                  (void (*) (struct hash_backet*,void*)) cpu_record_hash_clear,
 +                  tmp);
 +  }
 +  pthread_mutex_unlock (&cpu_record_mtx);
  }
  
  DEFUN (clear_thread_cpu,
@@@ -340,20 -326,16 +340,20 @@@ thread_master_create (void
  
    getrlimit(RLIMIT_NOFILE, &limit);
  
 -  if (cpu_record == NULL) 
 -    cpu_record 
 -      = hash_create ((unsigned int (*) (void *))cpu_record_hash_key,
 -                   (int (*) (const void *, const void *))cpu_record_hash_cmp);
 +  pthread_mutex_lock (&cpu_record_mtx);
 +  {
 +    if (cpu_record == NULL)
 +      cpu_record = hash_create ((unsigned int (*) (void *))cpu_record_hash_key,
 +                                (int (*) (const void *, const void *))
 +                                cpu_record_hash_cmp);
 +  }
 +  pthread_mutex_unlock (&cpu_record_mtx);
  
    rv = XCALLOC (MTYPE_THREAD_MASTER, sizeof (struct thread_master));
    if (rv == NULL)
 -    {
 -      return NULL;
 -    }
 +    return NULL;
 +
 +  pthread_mutex_init (&rv->mtx, NULL);
  
    rv->fd_limit = (int)limit.rlim_cur;
    rv->read = XCALLOC (MTYPE_THREAD, sizeof (struct thread *) * rv->fd_limit);
    rv->background = pqueue_create();
    rv->timer->cmp = rv->background->cmp = thread_timer_cmp;
    rv->timer->update = rv->background->update = thread_timer_update;
 +  rv->spin = true;
 +  rv->handle_signals = true;
  
- #if defined(HAVE_POLL)
+ #if defined(HAVE_POLL_CALL)
    rv->handler.pfdsize = rv->fd_limit;
    rv->handler.pfdcount = 0;
    rv->handler.pfds = XCALLOC (MTYPE_THREAD_MASTER,
@@@ -518,16 -498,11 +518,16 @@@ thread_queue_free (struct thread_maste
  void
  thread_master_free_unused (struct thread_master *m)
  {
 -  struct thread *t;
 -  while ((t = thread_trim_head(&m->unuse)) != NULL)
 -    {
 -      XFREE(MTYPE_THREAD, t);
 -    }
 +  pthread_mutex_lock (&m->mtx);
 +  {
 +    struct thread *t;
 +    while ((t = thread_trim_head(&m->unuse)) != NULL)
 +      {
 +        pthread_mutex_destroy (&t->mtx);
 +        XFREE(MTYPE_THREAD, t);
 +      }
 +  }
 +  pthread_mutex_unlock (&m->mtx);
  }
  
  /* Stop thread scheduler. */
@@@ -541,37 -516,25 +541,37 @@@ thread_master_free (struct thread_maste
    thread_list_free (m, &m->ready);
    thread_list_free (m, &m->unuse);
    thread_queue_free (m, m->background);
 +  pthread_mutex_destroy (&m->mtx);
  
- #if defined(HAVE_POLL)
+ #if defined(HAVE_POLL_CALL)
    XFREE (MTYPE_THREAD_MASTER, m->handler.pfds);
  #endif
    XFREE (MTYPE_THREAD_MASTER, m);
  
 -  if (cpu_record)
 -    {
 -      hash_clean (cpu_record, cpu_record_hash_free);
 -      hash_free (cpu_record);
 -      cpu_record = NULL;
 -    }
 +  pthread_mutex_lock (&cpu_record_mtx);
 +  {
 +    if (cpu_record)
 +      {
 +        hash_clean (cpu_record, cpu_record_hash_free);
 +        hash_free (cpu_record);
 +        cpu_record = NULL;
 +      }
 +  }
 +  pthread_mutex_unlock (&cpu_record_mtx);
  }
  
  /* Return remain time in second. */
  unsigned long
  thread_timer_remain_second (struct thread *thread)
  {
 -  int64_t remain = monotime_until(&thread->u.sands, NULL) / 1000000LL;
 +  int64_t remain;
 +
 +  pthread_mutex_lock (&thread->mtx);
 +  {
 +    remain = monotime_until(&thread->u.sands, NULL) / 1000000LL;
 +  }
 +  pthread_mutex_unlock (&thread->mtx);
 +
    return remain < 0 ? 0 : remain;
  }
  
@@@ -582,11 -545,7 +582,11 @@@ struct timeva
  thread_timer_remain(struct thread *thread)
  {
    struct timeval remain;
 -  monotime_until(&thread->u.sands, &remain);
 +  pthread_mutex_lock (&thread->mtx);
 +  {
 +    monotime_until(&thread->u.sands, &remain);
 +  }
 +  pthread_mutex_unlock (&thread->mtx);
    return remain;
  }
  
@@@ -601,11 -560,8 +601,11 @@@ thread_get (struct thread_master *m, u_
    if (! thread)
      {
        thread = XCALLOC (MTYPE_THREAD, sizeof (struct thread));
 +      /* mutex only needs to be initialized at struct creation. */
 +      pthread_mutex_init (&thread->mtx, NULL);
        m->alloc++;
      }
 +
    thread->type = type;
    thread->add_type = type;
    thread->master = m;
      {
        tmp.func = func;
        tmp.funcname = funcname;
 -      thread->hist = hash_get (cpu_record, &tmp,
 -                             (void * (*) (void *))cpu_record_hash_alloc);
 +      pthread_mutex_lock (&cpu_record_mtx);
 +      {
 +        thread->hist = hash_get (cpu_record, &tmp,
 +                                 (void * (*) (void *))cpu_record_hash_alloc);
 +      }
 +      pthread_mutex_unlock (&cpu_record_mtx);
      }
    thread->hist->total_active++;
    thread->func = func;
    return thread;
  }
  
- #if defined (HAVE_POLL)
+ #if defined (HAVE_POLL_CALL)
  
  #define fd_copy_fd_set(X) (X)
  
@@@ -698,45 -650,15 +698,45 @@@ static in
  fd_select (struct thread_master *m, int size, thread_fd_set *read, thread_fd_set *write, thread_fd_set *except, struct timeval *timer_wait)
  {
    int num;
- #if defined(HAVE_POLL)
 +
 +  /* If timer_wait is null here, that means either select() or poll() should
 +   * block indefinitely, unless the thread_master has overriden it. select()
 +   * and poll() differ in the timeout values they interpret as an indefinite
 +   * block; select() requires a null pointer, while poll takes a millisecond
 +   * value of -1.
 +   *
 +   * The thread_master owner has the option of overriding the default behavior
 +   * by setting ->selectpoll_timeout. If the value is positive, it specifies
 +   * the maximum number of milliseconds to wait. If the timeout is -1, it
 +   * specifies that we should never wait and always return immediately even if
 +   * no event is detected. If the value is zero, the behavior is default.
 +   */
 +
 -  /* recalc timeout for poll. Attention NULL pointer is no timeout with
 -  select, where with poll no timeount is -1 */
+ #if defined(HAVE_POLL_CALL)
    int timeout = -1;
 -  if (timer_wait != NULL)
 +
 +  if (timer_wait != NULL && m->selectpoll_timeout == 0) // use the default value
      timeout = (timer_wait->tv_sec*1000) + (timer_wait->tv_usec/1000);
 +  else if (m->selectpoll_timeout > 0) // use the user's timeout
 +    timeout = m->selectpoll_timeout;
 +  else if (m->selectpoll_timeout < 0) // effect a poll (return immediately)
 +    timeout = 0;
  
    num = poll (m->handler.pfds, m->handler.pfdcount + m->handler.pfdcountsnmp, timeout);
  #else
 +  struct timeval timeout;
 +  if (m->selectpoll_timeout > 0) // use the user's timeout
 +  {
 +    timeout.tv_sec = m->selectpoll_timeout / 1000;
 +    timeout.tv_usec = (m->selectpoll_timeout % 1000) * 1000;
 +    timer_wait = &timeout;
 +  }
 +  else if (m->selectpoll_timeout < 0) // effect a poll (return immediately)
 +  {
 +    timeout.tv_sec = 0;
 +    timeout.tv_usec = 0;
 +    timer_wait = &timeout;
 +  }
    num = select (size, read, write, except, timer_wait);
  #endif
  
  static int
  fd_is_set (struct thread *thread, thread_fd_set *fdset, int pos)
  {
- #if defined(HAVE_POLL)
+ #if defined(HAVE_POLL_CALL)
    return 1;
  #else
    return FD_ISSET (THREAD_FD (thread), fdset);
  static int
  fd_clear_read_write (struct thread *thread)
  {
- #if !defined(HAVE_POLL)
+ #if !defined(HAVE_POLL_CALL)
    thread_fd_set *fdset = NULL;
    int fd = THREAD_FD (thread);
  
@@@ -781,49 -703,36 +781,49 @@@ funcname_thread_add_read_write (int dir
  {
    struct thread *thread = NULL;
  
 -#if !defined(HAVE_POLL_CALL)
 -  thread_fd_set *fdset = NULL;
 -  if (dir == THREAD_READ)
 -    fdset = &m->handler.readfd;
 -  else
 -    fdset = &m->handler.writefd;
 -#endif
 -
 +  pthread_mutex_lock (&m->mtx);
 +  {
- #if defined (HAVE_POLL)
+ #if defined (HAVE_POLL_CALL)
 -  thread = generic_thread_add(m, func, arg, fd, dir, debugargpass);
 -
 -  if (thread == NULL)
 -    return NULL;
 +    thread = generic_thread_add(m, func, arg, fd, dir, debugargpass);
  #else
 -  if (FD_ISSET (fd, fdset))
 -    {
 -      zlog_warn ("There is already %s fd [%d]",
 -                 (dir == THREAD_READ) ? "read" : "write", fd);
 -      return NULL;
 -    }
 +    if (fd >= FD_SETSIZE)
 +      {
 +        zlog_err ("File descriptor %d is >= FD_SETSIZE (%d). Please recompile"
 +                  "with --enable-poll=yes", fd, FD_SETSIZE);
 +        assert (fd < FD_SETSIZE && !"fd >= FD_SETSIZE");
 +      }
 +    thread_fd_set *fdset = NULL;
 +    if (dir == THREAD_READ)
 +      fdset = &m->handler.readfd;
 +    else
 +      fdset = &m->handler.writefd;
  
 -  FD_SET (fd, fdset);
 -  thread = thread_get (m, dir, func, arg, debugargpass);
 +    if (FD_ISSET (fd, fdset))
 +      {
 +        zlog_warn ("There is already %s fd [%d]",
 +                   (dir == THREAD_READ) ? "read" : "write", fd);
 +      }
 +    else
 +      {
 +        FD_SET (fd, fdset);
 +        thread = thread_get (m, dir, func, arg, debugargpass);
 +      }
  #endif
  
 -  thread->u.fd = fd;
 -  if (dir == THREAD_READ)
 -    thread_add_fd (m->read, thread);
 -  else
 -    thread_add_fd (m->write, thread);
 +    if (thread)
 +      {
 +        pthread_mutex_lock (&thread->mtx);
 +        {
 +          thread->u.fd = fd;
 +          if (dir == THREAD_READ)
 +            thread_add_fd (m->read, thread);
 +          else
 +            thread_add_fd (m->write, thread);
 +        }
 +        pthread_mutex_unlock (&thread->mtx);
 +      }
 +  }
 +  pthread_mutex_unlock (&m->mtx);
  
    return thread;
  }
@@@ -844,21 -753,13 +844,21 @@@ funcname_thread_add_timer_timeval (stru
    assert (type == THREAD_TIMER || type == THREAD_BACKGROUND);
    assert (time_relative);
    
 -  queue = ((type == THREAD_TIMER) ? m->timer : m->background);
 -  thread = thread_get (m, type, func, arg, debugargpass);
 +  pthread_mutex_lock (&m->mtx);
 +  {
 +    queue = ((type == THREAD_TIMER) ? m->timer : m->background);
 +    thread = thread_get (m, type, func, arg, debugargpass);
  
 -  monotime(&thread->u.sands);
 -  timeradd(&thread->u.sands, time_relative, &thread->u.sands);
 +    pthread_mutex_lock (&thread->mtx);
 +    {
 +      monotime(&thread->u.sands);
 +      timeradd(&thread->u.sands, time_relative, &thread->u.sands);
 +      pqueue_enqueue(thread, queue);
 +    }
 +    pthread_mutex_unlock (&thread->mtx);
 +  }
 +  pthread_mutex_unlock (&m->mtx);
  
 -  pqueue_enqueue(thread, queue);
    return thread;
  }
  
@@@ -946,17 -847,9 +946,17 @@@ funcname_thread_add_event (struct threa
  
    assert (m != NULL);
  
 -  thread = thread_get (m, THREAD_EVENT, func, arg, debugargpass);
 -  thread->u.val = val;
 -  thread_list_add (&m->event, thread);
 +  pthread_mutex_lock (&m->mtx);
 +  {
 +    thread = thread_get (m, THREAD_EVENT, func, arg, debugargpass);
 +    pthread_mutex_lock (&thread->mtx);
 +    {
 +      thread->u.val = val;
 +      thread_list_add (&m->event, thread);
 +    }
 +    pthread_mutex_unlock (&thread->mtx);
 +  }
 +  pthread_mutex_unlock (&m->mtx);
  
    return thread;
  }
  static void
  thread_cancel_read_or_write (struct thread *thread, short int state)
  {
- #if defined(HAVE_POLL)
+ #if defined(HAVE_POLL_CALL)
    nfds_t i;
  
    for (i=0;i<thread->master->handler.pfdcount;++i)
    fd_clear_read_write (thread);
  }
  
 -/* Cancel thread from scheduler. */
 +/**
 + * Cancel thread from scheduler.
 + *
 + * This function is *NOT* MT-safe. DO NOT call it from any other pthread except
 + * the one which owns thread->master.
 + */
  void
  thread_cancel (struct thread *thread)
  {
    struct thread_list *list = NULL;
    struct pqueue *queue = NULL;
    struct thread **thread_array = NULL;
 -  
 +
 +  pthread_mutex_lock (&thread->master->mtx);
 +  pthread_mutex_lock (&thread->mtx);
 +
    switch (thread->type)
      {
      case THREAD_READ:
- #if defined (HAVE_POLL)
+ #if defined (HAVE_POLL_CALL)
        thread_cancel_read_or_write (thread, POLLIN | POLLHUP);
  #else
        thread_cancel_read_or_write (thread, 0);
        thread_array = thread->master->read;
        break;
      case THREAD_WRITE:
- #if defined (HAVE_POLL)
+ #if defined (HAVE_POLL_CALL)
        thread_cancel_read_or_write (thread, POLLOUT | POLLHUP);
  #else
        thread_cancel_read_or_write (thread, 0);
        queue = thread->master->background;
        break;
      default:
 -      return;
 +      goto done;
        break;
      }
  
    if (queue)
      {
        assert(thread->index >= 0);
 -      assert(thread == queue->array[thread->index]);
 -      pqueue_remove_at(thread->index, queue);
 +      pqueue_remove (thread, queue);
      }
    else if (list)
      {
      }
  
    thread_add_unuse (thread->master, thread);
 +
 +done:
 +  pthread_mutex_unlock (&thread->mtx);
 +  pthread_mutex_unlock (&thread->master->mtx);
  }
  
  /* Delete all events which has argument value arg. */
@@@ -1069,48 -951,39 +1069,48 @@@ thread_cancel_event (struct thread_mast
  {
    unsigned int ret = 0;
    struct thread *thread;
 +  struct thread *t;
  
 -  thread = m->event.head;
 -  while (thread)
 -    {
 -      struct thread *t;
 -
 -      t = thread;
 -      thread = t->next;
 -
 -      if (t->arg == arg)
 +  pthread_mutex_lock (&m->mtx);
 +  {
 +    thread = m->event.head;
 +    while (thread)
 +      {
 +        t = thread;
 +        pthread_mutex_lock (&t->mtx);
          {
 -          ret++;
 -          thread_list_delete (&m->event, t);
 -          thread_add_unuse (m, t);
 +          thread = t->next;
 +
 +          if (t->arg == arg)
 +            {
 +              ret++;
 +              thread_list_delete (&m->event, t);
 +              thread_add_unuse (m, t);
 +            }
          }
 -    }
 -
 -  /* thread can be on the ready list too */
 -  thread = m->ready.head;
 -  while (thread)
 -    {
 -      struct thread *t;
 -
 -      t = thread;
 -      thread = t->next;
 +        pthread_mutex_unlock (&t->mtx);
 +      }
  
 -      if (t->arg == arg)
 +    /* thread can be on the ready list too */
 +    thread = m->ready.head;
 +    while (thread)
 +      {
 +        t = thread;
 +        pthread_mutex_lock (&t->mtx);
          {
 -          ret++;
 -          thread_list_delete (&m->ready, t);
 -          thread_add_unuse (m, t);
 +          thread = t->next;
 +
 +          if (t->arg == arg)
 +            {
 +              ret++;
 +              thread_list_delete (&m->ready, t);
 +              thread_add_unuse (m, t);
 +            }
          }
 -    }
 +        pthread_mutex_unlock (&t->mtx);
 +      }
 +  }
 +  pthread_mutex_unlock (&m->mtx);
    return ret;
  }
  
@@@ -1154,7 -1027,7 +1154,7 @@@ thread_process_fds_helper (struct threa
        thread_delete_fd (thread_array, thread);
        thread_list_add (&m->ready, thread);
        thread->type = THREAD_READY;
- #if defined(HAVE_POLL)
+ #if defined(HAVE_POLL_CALL)
        thread->master->handler.pfds[pos].events &= ~(state);
  #endif
        return 1;
    return 0;
  }
  
- #if defined(HAVE_POLL)
+ #if defined(HAVE_POLL_CALL)
  
  /* check poll events */
  static void
@@@ -1203,7 -1076,7 +1203,7 @@@ check_pollfds(struct thread_master *m, 
  static void
  thread_process_fds (struct thread_master *m, thread_fd_set *rset, thread_fd_set *wset, int num)
  {
- #if defined (HAVE_POLL)
+ #if defined (HAVE_POLL_CALL)
    check_pollfds (m, rset, num);
  #else
    int ready = 0, index;
@@@ -1270,24 -1143,18 +1270,24 @@@ thread_fetch (struct thread_master *m, 
    struct timeval *timer_wait = &timer_val;
    struct timeval *timer_wait_bg;
  
 -  while (1)
 +  do
      {
        int num = 0;
  
        /* Signals pre-empt everything */
 -      quagga_sigevent_process ();
 +      if (m->handle_signals)
 +        quagga_sigevent_process ();
         
 +      pthread_mutex_lock (&m->mtx);
        /* Drain the ready queue of already scheduled jobs, before scheduling
         * more.
         */
        if ((thread = thread_trim_head (&m->ready)) != NULL)
 -        return thread_run (m, thread, fetch);
 +        {
 +          fetch = thread_run (m, thread, fetch);
 +          pthread_mutex_unlock (&m->mtx);
 +          return fetch;
 +        }
        
        /* To be fair to all kinds of threads, and avoid starvation, we
         * need to be careful to consider all thread types for scheduling
        thread_process (&m->event);
        
        /* Structure copy.  */
- #if !defined(HAVE_POLL)
+ #if !defined(HAVE_POLL_CALL)
        readfd = fd_copy_fd_set(m->handler.readfd);
        writefd = fd_copy_fd_set(m->handler.writefd);
        exceptfd = fd_copy_fd_set(m->handler.exceptfd);
        if (num < 0)
          {
            if (errno == EINTR)
 -            continue; /* signal received - process it */
 +            {
 +              pthread_mutex_unlock (&m->mtx);
 +              continue; /* signal received - process it */
 +            }
            zlog_warn ("select() error: %s", safe_strerror (errno));
 +          pthread_mutex_unlock (&m->mtx);
            return NULL;
          }
  
         list at this time.  If this is code is uncommented, then background
         timer threads will not run unless there is nothing else to do. */
        if ((thread = thread_trim_head (&m->ready)) != NULL)
 -        return thread_run (m, thread, fetch);
 +        {
 +          fetch = thread_run (m, thread, fetch);
 +          pthread_mutex_unlock (&m->mtx);
 +          return fetch;
 +        }
  #endif
  
        /* Background timer/events, lowest priority */
        thread_timer_process (m->background, &now);
        
        if ((thread = thread_trim_head (&m->ready)) != NULL)
 -        return thread_run (m, thread, fetch);
 -    }
 +        {
 +          fetch = thread_run (m, thread, fetch);
 +          pthread_mutex_unlock (&m->mtx);
 +          return fetch;
 +        }
 +
 +      pthread_mutex_unlock (&m->mtx);
 +
 +    } while (m->spin);
 +
 +  return NULL;
  }
  
  unsigned long
@@@ -1398,23 -1248,13 +1398,23 @@@ thread_consumed_time (RUSAGE_T *now, RU
  int
  thread_should_yield (struct thread *thread)
  {
 -  return monotime_since(&thread->real, NULL) > (int64_t)thread->yield;
 +  int result;
 +  pthread_mutex_lock (&thread->mtx);
 +  {
 +    result = monotime_since(&thread->real, NULL) > (int64_t)thread->yield;
 +  }
 +  pthread_mutex_unlock (&thread->mtx);
 +  return result;
  }
  
  void
  thread_set_yield_time (struct thread *thread, unsigned long yield_time)
  {
 -  thread->yield = yield_time;
 +  pthread_mutex_lock (&thread->mtx);
 +  {
 +    thread->yield = yield_time;
 +  }
 +  pthread_mutex_unlock (&thread->mtx);
  }
  
  void
@@@ -1484,7 -1324,6 +1484,7 @@@ funcname_thread_execute (struct thread_
  
    memset (&dummy, 0, sizeof (struct thread));
  
 +  pthread_mutex_init (&dummy.mtx, NULL);
    dummy.type = THREAD_EVENT;
    dummy.add_type = THREAD_EXECUTE;
    dummy.master = NULL;
  
    tmp.func = dummy.func = func;
    tmp.funcname = dummy.funcname = funcname;
 -  dummy.hist = hash_get (cpu_record, &tmp,
 -                       (void * (*) (void *))cpu_record_hash_alloc);
 +  pthread_mutex_lock (&cpu_record_mtx);
 +  {
 +    dummy.hist = hash_get (cpu_record, &tmp,
 +                           (void * (*) (void *))cpu_record_hash_alloc);
 +  }
 +  pthread_mutex_unlock (&cpu_record_mtx);
  
    dummy.schedfrom = schedfrom;
    dummy.schedfrom_line = fromln;
diff --combined lib/thread.h
index 18fd340ba5d18c41897633b6a2cb6b87fb7095cf,6cb7896e7d1c89f7b59410b16d0c609705e3043f..6fb6ad7c9d9eae0e7df3b390f6f410c80cc3f423
@@@ -24,7 -24,6 +24,7 @@@
  
  #include <zebra.h>
  #include "monotime.h"
 +#include <pthread.h>
  
  struct rusage_t
  {
@@@ -51,7 -50,7 +51,7 @@@ struct pqueue
   */
  typedef fd_set thread_fd_set;
  
- #if defined(HAVE_POLL)
+ #if defined(HAVE_POLL_CALL)
  #include <poll.h>
  struct fd_handler
  {
@@@ -85,10 -84,6 +85,10 @@@ struct thread_maste
    int fd_limit;
    struct fd_handler handler;
    unsigned long alloc;
 +  long selectpoll_timeout;
 +  bool spin;
 +  bool handle_signals;
 +  pthread_mutex_t mtx;
  };
  
  typedef unsigned char thread_type;
@@@ -115,7 -110,6 +115,7 @@@ struct threa
    const char *funcname;
    const char *schedfrom;
    int schedfrom_line;
 +  pthread_mutex_t mtx;
  };
  
  struct cpu_thread_history 
diff --combined ospfd/ospf_vty.c
index 9e577105ca58690e3897c153dcaa23b79cc6284c,f5880ca9e35f6b51a23244c50003b4b163eb7e11..4a7dbb9541908b042ea927ce4666d40d100c6260
@@@ -1539,7 -1539,7 +1539,7 @@@ ospf_area_nssa_cmd_handler (struct vty 
        return CMD_WARNING;
      }
  
-   if (argc > 1)
+   if (argc > 3)
      {
        if (strncmp (argv[3]->text, "translate-c", 11) == 0)
          ospf_area_nssa_translator_role_set (ospf, area_id,
@@@ -6333,7 -6333,7 +6333,7 @@@ DEFUN (no_ip_ospf_dead_interval
  {
    VTY_DECLVAR_CONTEXT(interface, ifp);
    int idx_ipv4 = argc - 1;
 -  struct in_addr addr;
 +  struct in_addr addr = { .s_addr = 0L};
    int ret;
    struct ospf_if_params *params;
    struct ospf_interface *oi;
@@@ -6465,7 -6465,6 +6465,7 @@@ DEFUN (no_ip_ospf_hello_interval
    int idx = 0;
    struct in_addr addr;
    struct ospf_if_params *params;
 +
    params = IF_DEF_PARAMS (ifp);
  
    if (argv_find (argv, argc, "A.B.C.D", &idx))
diff --combined pimd/pim_cmd.c
index ee3538a05477a8234a43f8242734dd3a31854b9c,1224bc5fc80223b9da14d172784a79d6de848915..e476a32fb03e5912756c6dc53489783e2e43e928
@@@ -820,7 -820,6 +820,7 @@@ static void pim_show_interfaces_single(
      mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd);
  
      if (uj) {
 +      char pbuf[PREFIX2STR_BUFFER];
        json_row = json_object_new_object();
        json_object_pim_ifp_add(json_row, ifp);
  
  
          sec_list = json_object_new_array();
          for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) {
 -          json_object_array_add(sec_list, json_object_new_string(inet_ntoa(sec_addr->addr)));
 +          json_object_array_add(sec_list,
 +                                json_object_new_string(prefix2str(&sec_addr->addr,
 +                                                                pbuf,
 +                                                                sizeof(pbuf))));
          }
          json_object_object_add(json_row, "secondaryAddressList", sec_list);
        }
          vty_out(vty, "Use Source : %s%s", inet_ntoa(pim_ifp->update_source), VTY_NEWLINE);
        }
        if (pim_ifp->sec_addr_list) {
 +        char pbuf[PREFIX2STR_BUFFER];
          vty_out(vty, "Address    : %s (primary)%s",
 -                                    inet_ntoa(ifaddr), VTY_NEWLINE);
 +                inet_ntoa(ifaddr), VTY_NEWLINE);
          for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) {
            vty_out(vty, "             %s%s",
 -                                    inet_ntoa(sec_addr->addr), VTY_NEWLINE);
 +                  prefix2str(&sec_addr->addr,
 +                           pbuf,
 +                           sizeof(pbuf)), VTY_NEWLINE);
          }
        } else {
          vty_out(vty, "Address    : %s%s", inet_ntoa(ifaddr), VTY_NEWLINE);
@@@ -1624,9 -1617,13 +1624,9 @@@ static void pim_show_neighbors_secondar
                     neigh_src_str, sizeof(neigh_src_str));
  
        for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, prefix_node, p)) {
 -      char neigh_sec_str[INET_ADDRSTRLEN];
 +      char neigh_sec_str[PREFIX2STR_BUFFER];
  
 -      if (p->family != AF_INET)
 -        continue;
 -
 -      pim_inet4_dump("<src?>", p->u.prefix4,
 -                     neigh_sec_str, sizeof(neigh_sec_str));
 +      prefix2str(p, neigh_sec_str, sizeof(neigh_sec_str));
  
        vty_out(vty, "%-9s %-15s %-15s %-15s%s",
                ifp->name,
@@@ -3738,31 -3735,6 +3738,31 @@@ DEFUN (no_ip_pim_packets
    return CMD_SUCCESS;
  }
  
 +DEFUN (ip_pim_v6_secondary,
 +       ip_pim_v6_secondary_cmd,
 +       "ip pim send-v6-secondary",
 +       IP_STR
 +       "pim multicast routing\n"
 +       "Send v6 secondary addresses\n")
 +{
 +  pimg->send_v6_secondary = 1;
 +
 +  return CMD_SUCCESS;
 +}
 +
 +DEFUN (no_ip_pim_v6_secondary,
 +       no_ip_pim_v6_secondary_cmd,
 +       "no ip pim send-v6-secondary",
 +       NO_STR
 +       IP_STR
 +       "pim multicast routing\n"
 +       "Send v6 secondary addresses\n")
 +{
 +  pimg->send_v6_secondary = 0;
 +
 +  return CMD_SUCCESS;
 +}
 +
  DEFUN (ip_pim_rp,
         ip_pim_rp_cmd,
         "ip pim rp A.B.C.D [A.B.C.D/M]",
@@@ -3831,12 -3803,12 +3831,12 @@@ DEFUN (no_ip_pim_rp
         "ip address of RP\n"
         "Group Address range to cover\n")
  {
 -  int idx_ipv4 = 4;
 +  int idx_ipv4 = 4, idx_group = 0;
  
 -  if (argc == (idx_ipv4 + 1))
 -    return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, NULL, NULL);
 +  if (argv_find (argv, argc, "A.B.C.D/M", &idx_group))
 +    return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_group]->arg, NULL);
    else
 -    return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL);
 +    return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, NULL, NULL);
  }
  
  DEFUN (no_ip_pim_rp_prefix_list,
@@@ -4031,7 -4003,7 +4031,7 @@@ DEFUN (ip_ssmpingd
    int idx_ipv4 = 2;
    int result;
    struct in_addr source_addr;
-   const char *source_str = (argc == idx_ipv4) ? argv[idx_ipv4]->arg : "0.0.0.0";
+   const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0";
  
    result = inet_pton(AF_INET, source_str, &source_addr);
    if (result <= 0) {
@@@ -4061,7 -4033,7 +4061,7 @@@ DEFUN (no_ip_ssmpingd
    int idx_ipv4 = 3;
    int result;
    struct in_addr source_addr;
-   const char *source_str = (argc == idx_ipv4) ? argv[idx_ipv4]->arg : "0.0.0.0";
+   const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0";
  
    result = inet_pton(AF_INET, source_str, &source_addr);
    if (result <= 0) {
@@@ -4113,6 -4085,7 +4113,7 @@@ DEFUN (ip_pim_ecmp_rebalance
         "Enable PIM ECMP \n"
         "Enable PIM ECMP Rebalance\n")
  {
+   qpim_ecmp_enable = 1;
    qpim_ecmp_rebalance_enable = 1;
  
    return CMD_SUCCESS;
@@@ -5984,7 -5957,7 +5985,7 @@@ DEFUN (no_ip_msdp_mesh_group_source
         "mesh group source\n"
         "mesh group local address\n")
  {
-   if (argc == 6)
+   if (argc == 7)
      return ip_no_msdp_mesh_group_cmd_worker(vty, argv[6]->arg);
    else
      return ip_no_msdp_mesh_group_source_cmd_worker(vty, argv[4]->arg);
@@@ -6484,16 -6457,13 +6485,16 @@@ DEFUN (show_ip_msdp_sa_sg
         "JavaScript Object Notation\n")
  {
    u_char uj = use_json(argc, argv);
 -  if (uj)
 -    argc--;
  
 -  if (argc == 6)
 -    ip_msdp_show_sa_sg(vty, argv[4]->arg, argv[5]->arg, uj);
 -  else if (argc == 5)
 -    ip_msdp_show_sa_addr(vty, argv[4]->arg, uj);
 +  int idx = 0;
 +  char *src_ip = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg : NULL;
 +  char *grp_ip = idx < argc && argv_find (argv, argc, "A.B.C.D", &idx) ?
 +                 argv[idx]->arg : NULL;
 +
 +  if (src_ip && grp_ip)
 +    ip_msdp_show_sa_sg(vty, src_ip, grp_ip, uj);
 +  else if (src_ip)
 +    ip_msdp_show_sa_addr(vty, src_ip, uj);
    else
      ip_msdp_show_sa(vty, uj);
  
@@@ -6529,8 -6499,6 +6530,8 @@@ void pim_cmd_init(
    install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd);
    install_element (CONFIG_NODE, &ip_pim_packets_cmd);
    install_element (CONFIG_NODE, &no_ip_pim_packets_cmd);
 +  install_element (CONFIG_NODE, &ip_pim_v6_secondary_cmd);
 +  install_element (CONFIG_NODE, &no_ip_pim_v6_secondary_cmd);
    install_element (CONFIG_NODE, &ip_ssmpingd_cmd);
    install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd); 
    install_element (CONFIG_NODE, &ip_msdp_peer_cmd);
diff --combined pimd/pim_iface.c
index 524f2ee0b356c1a61c9fc3f39201438a794b09ae,cce87ae5fd49b467e2653812e22bd36ad0f7bbb2..48a59344eb6f679d40c0800947d81972ad760973
@@@ -50,6 -50,8 +50,8 @@@ struct list *pim_ifchannel_list = NULL
  static int pim_iface_vif_index[MAXVIFS];
  
  static void pim_if_igmp_join_del_all(struct interface *ifp);
+ static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
+                         struct in_addr group_addr, struct in_addr source_addr);
  
  void
  pim_if_init (void)
@@@ -326,29 -328,12 +328,29 @@@ static int pim_sec_addr_comp(const voi
    const struct pim_secondary_addr *sec1 = p1;
    const struct pim_secondary_addr *sec2 = p2;
  
 -  if (ntohl(sec1->addr.s_addr) < ntohl(sec2->addr.s_addr))
 +  if (sec1->addr.family == AF_INET &&
 +      sec2->addr.family == AF_INET6)
      return -1;
  
 -  if (ntohl(sec1->addr.s_addr) > ntohl(sec2->addr.s_addr))
 +  if (sec1->addr.family == AF_INET6 &&
 +      sec2->addr.family == AF_INET)
      return 1;
  
 +  if (sec1->addr.family == AF_INET)
 +    {
 +      if (ntohl(sec1->addr.u.prefix4.s_addr) < ntohl(sec2->addr.u.prefix4.s_addr))
 +        return -1;
 +
 +      if (ntohl(sec1->addr.u.prefix4.s_addr) > ntohl(sec2->addr.u.prefix4.s_addr))
 +        return 1;
 +    }
 +  else
 +    {
 +      return memcmp (&sec1->addr.u.prefix6,
 +                     &sec2->addr.u.prefix6,
 +                     sizeof (struct in6_addr));
 +    }
 +
    return 0;
  }
  
@@@ -358,7 -343,7 +360,7 @@@ static void pim_sec_addr_free(struct pi
  }
  
  static struct pim_secondary_addr *
 -pim_sec_addr_find(struct pim_interface *pim_ifp, struct in_addr addr)
 +pim_sec_addr_find(struct pim_interface *pim_ifp, struct prefix *addr)
  {
    struct pim_secondary_addr *sec_addr;
    struct listnode *node;
    }
  
    for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
 -    if (sec_addr->addr.s_addr == addr.s_addr) {
 +    if (prefix_cmp(&sec_addr->addr, addr)) {
        return sec_addr;
      }
    }
@@@ -383,7 -368,7 +385,7 @@@ static void pim_sec_addr_del(struct pim
    pim_sec_addr_free(sec_addr);
  }
  
 -static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct in_addr addr)
 +static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct prefix *addr)
  {
    int changed = 0;
    struct pim_secondary_addr *sec_addr;
    }
  
    changed = 1;
 -  sec_addr->addr = addr;
 +  sec_addr->addr = *addr;
    listnode_add_sort(pim_ifp->sec_addr_list, sec_addr);
  
    return changed;
@@@ -452,6 -437,10 +454,6 @@@ static int pim_sec_addr_update(struct i
    for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
      struct prefix *p = ifc->address;
  
 -    if (p->family != AF_INET) {
 -      continue;
 -    }
 -
      if (PIM_INADDR_IS_ANY(p->u.prefix4)) {
        continue;
      }
        continue;
      }
  
 -    if (pim_sec_addr_add(pim_ifp, p->u.prefix4)) {
 +    if (pim_sec_addr_add(pim_ifp, p)) {
        changed = 1;
      }
    }
@@@ -586,19 -575,45 +588,48 @@@ void pim_if_addr_add(struct connected *
  
    detect_address_change(ifp, 0, __PRETTY_FUNCTION__);
  
 +  if (ifc->address->family != AF_INET)
 +    return;
 +
    if (PIM_IF_TEST_IGMP(pim_ifp->options)) {
      struct igmp_sock *igmp;
  
      /* lookup IGMP socket */
      igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
 -                                     ifaddr);
 +                                       ifaddr);
      if (!igmp) {
        /* if addr new, add IGMP socket */
        pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, ifp);
      }
+     /* Replay Static IGMP groups */
+     if (pim_ifp->igmp_join_list)
+       {
+         struct listnode *node;
+         struct listnode *nextnode;
+         struct igmp_join *ij;
+         int join_fd;
+         for (ALL_LIST_ELEMENTS (pim_ifp->igmp_join_list, node, nextnode, ij))
+           {
+             /* Close socket and reopen with Source and Group */
+             close(ij->sock_fd);
+             join_fd = igmp_join_sock(ifp->name, ifp->ifindex, ij->group_addr, ij->source_addr);
+             if (join_fd < 0)
+               {
+                 char group_str[INET_ADDRSTRLEN];
+                 char source_str[INET_ADDRSTRLEN];
+                 pim_inet4_dump("<grp?>", ij->group_addr, group_str, sizeof(group_str));
+                 pim_inet4_dump("<src?>", ij->source_addr, source_str, sizeof(source_str));
+                 zlog_warn("%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
+                     __PRETTY_FUNCTION__,
+                     group_str, source_str, ifp->name);
+                 /* warning only */
+               }
+             else
+               ij->sock_fd = join_fd;
+           }
+       }
    } /* igmp */
  
    if (PIM_IF_TEST_PIM(pim_ifp->options))
@@@ -712,17 -727,14 +743,17 @@@ void pim_if_addr_del(struct connected *
    ifp = ifc->ifp;
    zassert(ifp);
  
 +  if (ifc->address->family != AF_INET)
 +    return;
 +
    if (PIM_DEBUG_ZEBRA) {
      char buf[BUFSIZ];
      prefix2str(ifc->address, buf, BUFSIZ);
      zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s",
 -             __PRETTY_FUNCTION__,
 -             ifp->name, ifp->ifindex, buf,
 -             CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ?
 -             "secondary" : "primary");
 +               __PRETTY_FUNCTION__,
 +               ifp->name, ifp->ifindex, buf,
 +               CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ?
 +               "secondary" : "primary");
    }
  
    detect_address_change(ifp, force_prim_as_any, __PRETTY_FUNCTION__);
@@@ -749,9 -761,12 +780,9 @@@ void pim_if_addr_add_all(struct interfa
      struct prefix *p = ifc->address;
      
      if (p->family != AF_INET)
 -      {
 -        v6_addrs++;
 -        continue;
 -      }
 -
 -    v4_addrs++;
 +      v6_addrs++;
 +    else
 +      v4_addrs++;
      pim_if_addr_add(ifc);
    }
  
@@@ -1142,7 -1157,6 +1173,7 @@@ struct pim_neighbor *pim_if_find_neighb
    struct listnode *neighnode;
    struct pim_neighbor *neigh;
    struct pim_interface *pim_ifp;
 +  struct prefix p;
  
    zassert(ifp);
  
      return 0;
    }
  
 +  p.family = AF_INET;
 +  p.u.prefix4 = addr;
 +  p.prefixlen = IPV4_MAX_PREFIXLEN;
 +
    for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) {
  
      /* primary address ? */
        return neigh;
  
      /* secondary address ? */
 -    if (pim_neighbor_find_secondary(neigh, addr))
 +    if (pim_neighbor_find_secondary(neigh, &p))
        return neigh;
    }
  
@@@ -1527,6 -1537,9 +1558,9 @@@ pim_if_connected_to_source (struct inte
    struct connected *c;
    struct prefix p;
  
+   if (!ifp)
+     return 0;
    p.family = AF_INET;
    p.u.prefix4 = src;
    p.prefixlen = IPV4_MAX_BITLEN;
diff --combined pimd/pim_rp.c
index feddb8d8d54f9424cb2a521f6f2fb905d7afb577,6c4504d9b0be236b2a3ed2cbbf0da8eb4e6e35a0..cdc760e92df31dc7ab5174d8e27377308b9075fe
@@@ -250,7 -250,7 +250,7 @@@ pim_rp_check_interface_addrs(struct rp_
    }
  
    for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
 -    if (sec_addr->addr.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) {
 +    if (prefix_same(&sec_addr->addr, &rp_info->rp.rpf_addr)) {
        return 1;
      }
    }
@@@ -281,7 -281,7 +281,7 @@@ pim_rp_check_interfaces (struct rp_inf
  int
  pim_rp_new (const char *rp, const char *group_range, const char *plist)
  {
-   int result;
+   int result = 0;
    struct rp_info *rp_info;
    struct rp_info *rp_all;
    struct prefix group_all;
@@@ -741,7 -741,7 +741,7 @@@ pim_rp_g (struct in_addr group
            char buf1[PREFIX2STR_BUFFER];
            prefix2str (&nht_p, buf, sizeof (buf));
            prefix2str (&rp_info->group, buf1, sizeof (buf1));
-           zlog_debug ("%s: NHT Register RP addr %s grp %s with Zebra ",
+           zlog_debug ("%s: NHT Register RP addr %s grp %s with Zebra",
                        __PRETTY_FUNCTION__, buf, buf1);
          }
        memset (&pnc, 0, sizeof (struct pim_nexthop_cache));
                char buf1[PREFIX2STR_BUFFER];
                prefix2str (&nht_p, buf, sizeof (buf));
                prefix2str (&g, buf1, sizeof (buf1));
-               zlog_debug ("%s: NHT nexthop cache not found for RP %s grp %s",
+               zlog_debug ("%s: Nexthop cache not found for RP %s grp %s register with Zebra",
                            __PRETTY_FUNCTION__, buf, buf1);
              }
            pim_rpf_set_refresh_time ();
@@@ -972,8 -972,7 +972,7 @@@ pim_resolve_rp_nh (void
              {
                if (nh_node->gate.ipv4.s_addr == 0)
                  {
-                   nbr =
-                     pim_neighbor_find_if (if_lookup_by_index
+                   nbr = pim_neighbor_find_if (if_lookup_by_index
                                            (nh_node->ifindex, VRF_DEFAULT));
                    if (nbr)
                      {
                          {
                            char str[PREFIX_STRLEN];
                            char str1[INET_ADDRSTRLEN];
+                           struct interface *ifp1 = if_lookup_by_index(nh_node->ifindex,
+                                                                               VRF_DEFAULT);
                            pim_inet4_dump ("<nht_nbr?>", nbr->source_addr,
                                            str1, sizeof (str1));
                            pim_addr_dump ("<nht_addr?>", &nht_p, str,
                                           sizeof (str));
-                           zlog_debug
-                             ("%s: addr %s new nexthop addr %s ifindex %d ",
+                           zlog_debug ("%s: addr %s new nexthop addr %s interface %s",
                               __PRETTY_FUNCTION__, str, str1,
-                              nh_node->ifindex);
+                              ifp1->name);
                          }
                      }
                  }
diff --combined pimd/pim_vty.c
index 62d1f936ecf5aeaeaa4a1c8da0ed59edfa574fde,754cf8468b415569b7cd079fd0a02ff147a4c343..2d502d9aa901b8c9317e856a8fb0316008897e2d
@@@ -150,12 -150,6 +150,12 @@@ int pim_global_config_write(struct vty 
  
    writes += pim_msdp_config_write (vty);
  
 +  if (!pimg->send_v6_secondary)
 +    {
 +      vty_out (vty, "no ip pim send-v6-secondary%s", VTY_NEWLINE);
 +      ++writes;
 +    }
 +
    writes += pim_rp_config_write (vty);
  
    if (qpim_register_suppress_time != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT)
                   VTY_NEWLINE);
        ++writes;
      }
+   if (qpim_ecmp_rebalance_enable)
+     {
+       vty_out (vty, "ip pim ecmp rebalance%s", VTY_NEWLINE);
+       ++writes;
+     }
+   else if (qpim_ecmp_enable)
+     {
+       vty_out (vty, "ip pim ecmp%s", VTY_NEWLINE);
+       ++writes;
+     }
    if (qpim_ssmpingd_list) {
      struct listnode *node;
      struct ssmpingd_sock *ss;
diff --combined pimd/pim_zebra.c
index 253ab7ab4429069f8b6e02f9ee59b25fff1f77d4,baf296623fd92cf24adde2cba2881f8729c67124..b2a7319bf1740bc856ecd99d307f7d7be3db2965
@@@ -53,7 -53,6 +53,6 @@@
  
  static struct zclient *zclient = NULL;
  
- static int fib_lookup_if_vif_index(struct in_addr addr);
  
  /* Router-id update message from zebra. */
  static int pim_router_id_update_zebra(int command, struct zclient *zclient,
@@@ -258,11 -257,31 +257,11 @@@ static int pim_zebra_if_address_add(in
  #endif
    }
  
 -  if (p->family != AF_INET)
 -    {
 -      struct listnode *cnode;
 -      struct connected *conn;
 -      int v4addrs = 0;
 -
 -      for (ALL_LIST_ELEMENTS_RO (c->ifp->connected, cnode, conn))
 -        {
 -          if (conn->address->family == AF_INET)
 -          v4addrs++;
 -        }
 -      if (!v4addrs && pim_ifp) 
 -      {
 -        pim_ifp->primary_address = pim_find_primary_addr (c->ifp);
 -        pim_if_addr_add_all (c->ifp);
 -          pim_if_add_vif (c->ifp);
 -      }
 -      return 0;
 -    }
 -
    if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
      /* trying to add primary address */
  
      struct in_addr primary_addr = pim_find_primary_addr(c->ifp);
 -    if (primary_addr.s_addr != p->u.prefix4.s_addr) {
 +    if (p->family != AF_INET || primary_addr.s_addr != p->u.prefix4.s_addr) {
        if (PIM_DEBUG_ZEBRA) {
        /* but we had a primary address already */
  
@@@ -449,7 -468,28 +448,28 @@@ pim_scan_individual_oil (struct channel
    if (in_vif_index)
      input_iface_vif_index = in_vif_index;
    else
-     input_iface_vif_index = fib_lookup_if_vif_index (vif_source);
+     {
+       struct prefix src, grp;
+       src.family = AF_INET;
+       src.prefixlen = IPV4_MAX_BITLEN;
+       src.u.prefix4 = vif_source;
+       grp.family = AF_INET;
+       grp.prefixlen = IPV4_MAX_BITLEN;
+       grp.u.prefix4 = c_oil->oil.mfcc_mcastgrp;
+       if (PIM_DEBUG_ZEBRA)
+         {
+           char source_str[INET_ADDRSTRLEN];
+           char group_str[INET_ADDRSTRLEN];
+           pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
+           pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
+           zlog_debug ("%s: channel_oil (%s, %s) upstream info is not present.",
+                       __PRETTY_FUNCTION__, source_str, group_str);
+         }
+       input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(vif_source, &src, &grp);
+     }
    if (input_iface_vif_index < 1)
      {
        if (PIM_DEBUG_ZEBRA)
@@@ -537,12 -577,25 +557,25 @@@ void pim_scan_oil(
    struct listnode    *node;
    struct listnode    *nextnode;
    struct channel_oil *c_oil;
+   ifindex_t          ifindex;
+   int                vif_index = 0;
  
    qpim_scan_oil_last = pim_time_monotonic_sec();
    ++qpim_scan_oil_events;
  
    for (ALL_LIST_ELEMENTS(pim_channel_oil_list, node, nextnode, c_oil))
-     pim_scan_individual_oil (c_oil, 0);
+     {
+       if (c_oil->up && c_oil->up->rpf.source_nexthop.interface)
+         {
+           ifindex = c_oil->up->rpf.source_nexthop.interface->ifindex;
+           vif_index = pim_if_find_vifindex_by_ifindex (ifindex);
+           /* Pass Current selected NH vif index to mroute download */
+           if (vif_index)
+             pim_scan_individual_oil (c_oil, vif_index);
+         }
+       else
+         pim_scan_individual_oil (c_oil, 0);
+     }
  }
  
  static int on_rpf_cache_refresh(struct thread *t)
@@@ -679,67 -732,6 +712,6 @@@ void igmp_anysource_forward_stop(struc
      igmp_source_forward_stop (source);
  }
  
- static int fib_lookup_if_vif_index(struct in_addr addr)
- {
-   struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM];
-   int num_ifindex;
-   int vif_index;
-   ifindex_t first_ifindex;
-   num_ifindex = zclient_lookup_nexthop(nexthop_tab,
-                                      MULTIPATH_NUM, addr,
-                                      PIM_NEXTHOP_LOOKUP_MAX);
-   if (num_ifindex < 1) {
-     if (PIM_DEBUG_ZEBRA)
-       {
-       char addr_str[INET_ADDRSTRLEN];
-       pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
-       zlog_debug("%s %s: could not find nexthop ifindex for address %s",
-                  __FILE__, __PRETTY_FUNCTION__,
-                  addr_str);
-       }
-     return -1;
-   }
-   
-   first_ifindex = nexthop_tab[0].ifindex;
-   
-   if (num_ifindex > 1) {
-     if (PIM_DEBUG_ZEBRA)
-       {
-       char addr_str[INET_ADDRSTRLEN];
-       pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
-       zlog_debug("%s %s: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)",
-                  __FILE__, __PRETTY_FUNCTION__,
-                  num_ifindex, addr_str, first_ifindex);
-       }
-     /* debug warning only, do not return */
-   }
-   
-   if (PIM_DEBUG_ZEBRA) {
-     char addr_str[INET_ADDRSTRLEN];
-     pim_inet4_dump("<ifaddr?>", addr, addr_str, sizeof(addr_str));
-     zlog_debug("%s %s: found nexthop ifindex=%d (interface %s) for address %s",
-              __FILE__, __PRETTY_FUNCTION__,
-              first_ifindex, ifindex2ifname(first_ifindex, VRF_DEFAULT), addr_str);
-   }
-   vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex);
-   if (vif_index < 0) {
-     if (PIM_DEBUG_ZEBRA)
-       {
-       char addr_str[INET_ADDRSTRLEN];
-       pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
-       zlog_debug("%s %s: low vif_index=%d < 1 nexthop for address %s",
-                  __FILE__, __PRETTY_FUNCTION__,
-                  vif_index, addr_str);
-       }
-     return -2;
-   }
-   return vif_index;
- }
  static void
  igmp_source_forward_reevaluate_one(struct igmp_source *source)
  {
@@@ -853,6 -845,7 +825,7 @@@ void igmp_source_forward_start(struct i
      int ret = 0;
      struct pim_nexthop_cache out_pnc;
      struct pim_nexthop nexthop;
+     struct pim_upstream *up = NULL;
  
      if (!pim_rp_set_upstream_addr (&vif_source, source->source_addr, sg.grp))
        return;
      nht_p.u.prefix4 = vif_source;
      memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache));
  
+     src.family = AF_INET;
+     src.prefixlen = IPV4_MAX_BITLEN;
+     src.u.prefix4 = vif_source;   //RP or Src address
+     grp.family = AF_INET;
+     grp.prefixlen = IPV4_MAX_BITLEN;
+     grp.u.prefix4 = sg.grp;
      if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1)
        {
          if (out_pnc.nexthop_num)
            {
-             src.family = AF_INET;
-             src.prefixlen = IPV4_MAX_BITLEN;
-             src.u.prefix4 = vif_source;   //RP or Src address
-             grp.family = AF_INET;
-             grp.prefixlen = IPV4_MAX_BITLEN;
-             grp.u.prefix4 = sg.grp;
-             memset (&nexthop, 0, sizeof (nexthop));
+             up = pim_upstream_find (&sg);
+             memset (&nexthop, 0, sizeof (struct pim_nexthop));
+             if (up)
+               memcpy (&nexthop, &up->rpf.source_nexthop, sizeof (struct pim_nexthop));
              //Compute PIM RPF using Cached nexthop
-             pim_ecmp_nexthop_search (&out_pnc, &nexthop,
-                                   &src, &grp, 0);
+             pim_ecmp_nexthop_search (&out_pnc, &nexthop, &src, &grp, 0);
              if (nexthop.interface)
                input_iface_vif_index = pim_if_find_vifindex_by_ifindex (nexthop.interface->ifindex);
            }
            }
        }
      else
-       input_iface_vif_index = fib_lookup_if_vif_index(vif_source);
+       input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(vif_source, &src, &grp);
  
      if (PIM_DEBUG_ZEBRA)
        {
@@@ -1075,7 -1071,6 +1051,6 @@@ void pim_forward_start(struct pim_ifcha
        struct prefix nht_p, src, grp;
        int ret = 0;
        struct pim_nexthop_cache out_pnc;
-       struct pim_nexthop nexthop;
  
        /* Register addr with Zebra NHT */
        nht_p.family = AF_INET;
        grp.u.prefix4 = up->sg.grp;
        memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache));
  
-       if ((ret =
-                   pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1)
+       if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1)
          {
            if (out_pnc.nexthop_num)
              {
                grp.family = AF_INET;
                grp.prefixlen = IPV4_MAX_BITLEN;
                grp.u.prefix4 = up->sg.grp;
-               memset (&nexthop, 0, sizeof (nexthop));
                //Compute PIM RPF using Cached nexthop
-               pim_ecmp_nexthop_search (&out_pnc, &nexthop, &src, &grp, 0);
-               input_iface_vif_index =
-                   pim_if_find_vifindex_by_ifindex (nexthop.interface->ifindex);
+               if (pim_ecmp_nexthop_search (&out_pnc, &up->rpf.source_nexthop, &src, &grp, 0) == 0)
+                 input_iface_vif_index = pim_if_find_vifindex_by_ifindex (up->rpf.source_nexthop.interface->ifindex);
+               else
+                 {
+                   if (PIM_DEBUG_TRACE)
+                     zlog_debug ("%s: Nexthop selection failed for %s ", __PRETTY_FUNCTION__, up->sg_str);
+                 }
              }
            else
              {
              }
          }
        else
-           input_iface_vif_index = fib_lookup_if_vif_index (up->upstream_addr);
+         input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(up->upstream_addr, &src, &grp);
  
        if (input_iface_vif_index < 1)
          {
          }
        if (PIM_DEBUG_TRACE)
          {
-           zlog_debug ("%s: NHT entry %s update channel_oil vif_index %d ",
-                       __PRETTY_FUNCTION__, up->sg_str, input_iface_vif_index);
+           struct interface *in_intf = pim_if_find_by_vif_index (input_iface_vif_index);
+           zlog_debug ("%s: Update channel_oil IIF %s VIFI %d entry %s ",
+                       __PRETTY_FUNCTION__, in_intf ? in_intf->name : "NIL",
+                       input_iface_vif_index, up->sg_str);
          }
        up->channel_oil = pim_channel_oil_add (&up->sg, input_iface_vif_index);
        if (!up->channel_oil)
diff --combined zebra/interface.c
index c3d303736204c1539415d335d8ef9b158f022190,78ac0258caf7ac4f2b46edf86aaba3f6de2bf259..42e7c7bb1871bbf4bb8d706fbb65b11def946751
@@@ -709,7 -709,6 +709,7 @@@ if_delete_update (struct interface *ifp
       for setting ifindex to IFINDEX_INTERNAL after processing the
       interface deletion message. */
    ifp->ifindex = IFINDEX_INTERNAL;
 +  ifp->node = NULL;
  }
  
  /* VRF change for an interface */
@@@ -1707,6 -1706,8 +1707,8 @@@ link_param_cmd_set_float (struct interf
  static void
  link_param_cmd_unset (struct interface *ifp, uint32_t type)
  {
+   if (ifp->link_params == NULL)
+     return;
  
    /* Unset field */
    UNSET_PARAM(ifp->link_params, type);