]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge remote-tracking branch 'origin/stable/3.0'
authorDonald Sharp <sharpd@cumulusnetworks.com>
Tue, 2 May 2017 19:52:09 +0000 (15:52 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Tue, 2 May 2017 19:52:09 +0000 (15:52 -0400)
41 files changed:
bgpd/bgp_mplsvpn.c
bgpd/bgp_route.c
bgpd/bgp_vty.c
configure.ac
ldpd/interface.c
ldpd/l2vpn.c
ldpd/ldp_zebra.c
ldpd/ldpd.h
nhrpd/nhrp_main.c
ospf6d/ospf6d.c
ospfd/ospf_interface.c
ospfd/ospf_vty.c
pimd/pim_cmd.c
pimd/pim_ifchannel.c
pimd/pim_ifchannel.h
pimd/pim_join.c
pimd/pim_jp_agg.c
pimd/pim_memory.c
pimd/pim_memory.h
pimd/pim_neighbor.c
pimd/pim_nht.c
pimd/pim_register.c
pimd/pim_rp.c
pimd/pim_rpf.c
pimd/pim_upstream.c
pimd/pim_upstream.h
pimd/pim_vty.c
pimd/pimd.c
pimd/pimd.h
snapcraft/Makefile.am
snapcraft/README.snap_build.md
snapcraft/extra_version_info.txt [new file with mode: 0644]
snapcraft/scripts/Makefile
snapcraft/scripts/show_version [new file with mode: 0644]
snapcraft/snapcraft.yaml.in
vtysh/Makefile.am
vtysh/vtysh.c
zebra/if_netlink.c
zebra/interface.c
zebra/interface.h
zebra/zebra_vrf.c

index d29fb26030907ea3d65fdf5fd69f2bb58dedddf8..88cde15e83381d17e109ccae2efa945ada6e076c 100644 (file)
@@ -773,25 +773,6 @@ bgp_show_mpls_vpn (struct vty *vty, afi_t afi, struct prefix_rd *prd,
   return CMD_SUCCESS;
 }
 
-#ifdef KEEP_OLD_VPN_COMMANDS
-DEFUN (show_ip_bgp_vpn_all,
-       show_ip_bgp_vpn_all_cmd,
-       "show [ip] bgp <vpnv4|vpnv6>",
-       SHOW_STR
-       IP_STR
-       BGP_STR
-       BGP_VPNVX_HELP_STR)
-{
-  afi_t afi;
-  int idx = 0;
-
-  if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi))
-    return bgp_show_mpls_vpn (vty, afi, NULL, bgp_show_type_normal, NULL, 0, 0);
-
-  return CMD_SUCCESS;
-}
-#endif
-
 DEFUN (show_bgp_ip_vpn_all_rd,
        show_bgp_ip_vpn_all_rd_cmd,
        "show bgp "BGP_AFI_CMD_STR" vpn all [rd ASN:nn_or_IP-address:nn] [json]",
index 2666644c7e9e852ce9a15fd4fb4ff740e0c15e71..3e51831d18fa4521399289964818b43d29075491 100644 (file)
@@ -9537,8 +9537,17 @@ DEFUN (show_ip_bgp_vpn_all_route_prefix,
       vty_out (vty, "Can't find default instance%s", VTY_NEWLINE);
       return CMD_WARNING;
     }
-  network = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL;
-  network = argv_find (argv, argc, "A.B.C.D/M", &idx) ? argv[idx]->arg : NULL;
+
+  if (argv_find (argv, argc, "A.B.C.D", &idx))
+    network = argv[idx]->arg;
+  else if (argv_find (argv, argc, "A.B.C.D/M", &idx))
+    network = argv[idx]->arg;
+  else
+    {
+      vty_out (vty, "Unable to figure out Network%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
   return bgp_show_route (vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0, BGP_PATH_ALL, use_json(argc, argv));
 }
 #endif /* KEEP_OLD_VPN_COMMANDS */
@@ -9558,8 +9567,16 @@ DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix,
 {
   int idx = 0;
   char *network = NULL;
-  network = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL;
-  network = argv_find (argv, argc, "A.B.C.D/M", &idx) ? argv[idx]->arg : NULL;
+
+  if (argv_find (argv, argc, "A.B.C.D", &idx))
+    network = argv[idx]->arg;
+  else if (argv_find (argv, argc, "A.B.C.D/M", &idx))
+    network = argv[idx]->arg;
+  else
+    {
+      vty_out (vty, "Unable to figure out Network%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
   return bgp_show_route (vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0, BGP_PATH_ALL, use_json(argc, argv));
 }
 
index 44389b99c209898ebca4d66a2168323c8690c788..361ab339624fff15774133c0d6001415b40fa391 100644 (file)
@@ -5948,7 +5948,6 @@ DEFUN (clear_ip_bgp_all,
        "Push out prefix-list ORF and do inbound soft reconfig\n"
        BGP_SOFT_OUT_STR)
 {
-  VTY_DECLVAR_CONTEXT(bgp, bgp);
   char *vrf = NULL;
 
   afi_t afi = AFI_IP6;
@@ -5988,25 +5987,11 @@ DEFUN (clear_ip_bgp_all,
       clr_sort = clear_group;
       idx++;
       clr_arg = argv[idx]->arg;
-
-      if (! peer_group_lookup (bgp, clr_arg))
-        {
-          vty_out (vty, "%% No such peer-group%s", VTY_NEWLINE);
-          return CMD_WARNING;
-        }
     }
   else if (argv_find (argv, argc, "WORD", &idx))
     {
-      if (peer_lookup_by_conf_if (bgp, argv[idx]->arg))
-        {
-          clr_sort = clear_peer;
-          clr_arg = argv[idx]->arg;
-        }
-      else
-        {
-          vty_out (vty, "%% No such neighbor%s", VTY_NEWLINE);
-         return CMD_WARNING;
-        }
+      clr_sort = clear_peer;
+      clr_arg = argv[idx]->arg;
     }
   else if (argv_find (argv, argc, "(1-4294967295)", &idx))
     {
@@ -6745,6 +6730,27 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi,
   return CMD_SUCCESS;
 }
 
+/*
+ * Return if we have a peer configured to use this afi/safi
+ */
+static int
+bgp_show_summary_afi_safi_peer_exists (struct bgp *bgp, int afi, int safi)
+{
+  struct listnode *node;
+  struct peer *peer;
+
+  for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
+    {
+      if (!CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE))
+        continue;
+
+      if (peer->afc[afi][safi])
+        return 1;
+    }
+
+  return 0;
+}
+
 static void
 bgp_show_summary_afi_safi (struct vty *vty, struct bgp *bgp, int afi, int safi,
                   u_char use_json, json_object *json)
@@ -6753,6 +6759,7 @@ bgp_show_summary_afi_safi (struct vty *vty, struct bgp *bgp, int afi, int safi,
   int afi_wildcard  = (afi == AFI_MAX);
   int safi_wildcard = (safi == SAFI_MAX);
   int is_wildcard   = (afi_wildcard || safi_wildcard);
+
   if (use_json && is_wildcard)
     vty_out (vty, "{%s", VTY_NEWLINE);
   if (afi_wildcard)
@@ -6763,26 +6770,33 @@ bgp_show_summary_afi_safi (struct vty *vty, struct bgp *bgp, int afi, int safi,
         safi = 1;                 /* SAFI_UNICAST */
       while (safi < SAFI_MAX)
         {
-          if (is_wildcard)
+          if (bgp_show_summary_afi_safi_peer_exists (bgp, afi, safi))
             {
-              if (use_json)
+              if (is_wildcard)
                 {
-                  json = json_object_new_object();
+                  /*
+                   * So limit output to those afi/safi pairs that
+                   * actualy have something interesting in them
+                   */
+                  if (use_json)
+                    {
+                      json = json_object_new_object();
 
-                  if (! is_first)
-                    vty_out (vty, ",%s", VTY_NEWLINE);
-                  else
-                    is_first = 0;
+                      if (! is_first)
+                        vty_out (vty, ",%s", VTY_NEWLINE);
+                      else
+                        is_first = 0;
 
-                  vty_out(vty, "\"%s\":", afi_safi_json(afi, safi));
-                }
-              else
-                {
-                  vty_out (vty, "%s%s Summary:%s",
-                           VTY_NEWLINE, afi_safi_print(afi, safi), VTY_NEWLINE);
+                      vty_out(vty, "\"%s\":", afi_safi_json(afi, safi));
+                    }
+                  else
+                    {
+                      vty_out (vty, "%s%s Summary:%s",
+                               VTY_NEWLINE, afi_safi_print(afi, safi), VTY_NEWLINE);
+                    }
                 }
+              bgp_show_summary (vty, bgp, afi, safi, use_json, json);
             }
-          bgp_show_summary (vty, bgp, afi, safi, use_json, json);
           safi++;
           if (safi == SAFI_RESERVED_4 || 
               safi == SAFI_RESERVED_5) /* handle special cases to match zebra.h */
@@ -6946,31 +6960,37 @@ afi_safi_print (afi_t afi, safi_t safi)
     return "Unknown";
 }
 
+/*
+ * Please note that we have intentionally camelCased
+ * the return strings here.  So if you want
+ * to use this function, please ensure you
+ * are doing this within json output
+ */
 const char *
 afi_safi_json (afi_t afi, safi_t safi)
 {
   if (afi == AFI_IP && safi == SAFI_UNICAST)
-    return "IPv4Unicast";
+    return "ipv4Unicast";
   else if (afi == AFI_IP && safi == SAFI_MULTICAST)
-    return "IPv4Multicast";
+    return "ipv4Multicast";
   else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST)
-    return "IPv4LabeledUnicast";
+    return "ipv4LabeledUnicast";
   else if (afi == AFI_IP && safi == SAFI_MPLS_VPN)
-    return "IPv4VPN";
+    return "ipv4Vpn";
   else if (afi == AFI_IP && safi == SAFI_ENCAP)
-    return "IPv4Encap";
+    return "ipv4Encap";
   else if (afi == AFI_IP6 && safi == SAFI_UNICAST)
-    return "IPv6Unicast";
+    return "ipv6Unicast";
   else if (afi == AFI_IP6 && safi == SAFI_MULTICAST)
-    return "IPv6Multicast";
+    return "ipv6Multicast";
   else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST)
-    return "IPv6LabeledUnicast";
+    return "ipv6LabeledUnicast";
   else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN)
-    return "IPv6VPN";
+    return "ipv6Vpn";
   else if (afi == AFI_IP6 && safi == SAFI_ENCAP)
-    return "IPv6Encap";
+    return "ipv6Encap";
   else if (afi == AFI_L2VPN && safi == SAFI_EVPN)
-    return "L2VPN EVPN";
+    return "l2VpnEvpn";
   else
     return "Unknown";
 }
@@ -8851,9 +8871,11 @@ DEFUN (show_ip_bgp_neighbors,
 
   int idx = 0;
 
-  if (argv_find (argv, argc, "WORD", &idx))
-    vrf = argv[idx]->arg;
+  if (argv_find (argv, argc, "view", &idx) ||
+      argv_find (argv, argc, "vrf", &idx))
+    vrf = argv[idx+1]->arg;
 
+  idx++;
   if (argv_find (argv, argc, "A.B.C.D", &idx) ||
       argv_find (argv, argc, "X:X::X:X", &idx) ||
       argv_find (argv, argc, "WORD", &idx))
index bef74c72676c5e95f19fc43c9900c63788990e93..c7dc641afee45c4fe5f92ae533b96d2cec033467 100755 (executable)
@@ -318,7 +318,7 @@ AC_ARG_ENABLE(rr-semantics,
 AC_ARG_ENABLE([protobuf],
   AS_HELP_STRING([--enable-protobuf], [Enable experimental protobuf support]))
 AC_ARG_ENABLE([oldvpn_commands],
-  AS_HELP_STRING([--enable-old-vpn-commands], [Keep old vpn commands]))
+  AS_HELP_STRING([--enable-oldvpn-commands], [Keep old vpn commands]))
 
 AC_CHECK_HEADERS(json-c/json.h)
 AC_CHECK_LIB(json-c, json_object_get, LIBS="$LIBS -ljson-c")
@@ -430,7 +430,7 @@ fi
 #
 # Logic for old vpn commans support.
 #
-if test "$enable_old_vpn_commands" = "yes"; then
+if test "$enable_oldvpn_commands" = "yes"; then
    AC_DEFINE(KEEP_OLD_VPN_COMMANDS,, [Define for compiling with old vpn commands])
 fi
 
index 7678152470ecd32d887b34febc499f4bfc126e77..440bb2dca06244828fad0ceb4ff7811999143a8c 100644 (file)
@@ -31,7 +31,7 @@ static struct if_addr *if_addr_new(struct kaddr *);
 static struct if_addr  *if_addr_lookup(struct if_addr_head *, struct kaddr *);
 static int              if_start(struct iface *, int);
 static int              if_reset(struct iface *, int);
-static void             if_update_af(struct iface_af *, int);
+static void             if_update_af(struct iface_af *);
 static int              if_hello_timer(struct thread *);
 static void             if_start_hello_timer(struct iface_af *);
 static void             if_stop_hello_timer(struct iface_af *);
@@ -139,7 +139,7 @@ if_update_info(struct iface *iface, struct kif *kif)
 
        /* get index and flags */
        iface->ifindex = kif->ifindex;
-       iface->flags = kif->flags;
+       iface->operative = kif->operative;
 }
 
 struct iface_af *
@@ -209,7 +209,7 @@ if_addr_add(struct kaddr *ka)
                }
        }
 
-       iface = if_lookup(leconf, ka->ifindex);
+       iface = if_lookup_name(leconf, ka->ifname);
        if (iface) {
                if (ka->af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&ka->addr.v6))
                        iface->linklocal = ka->addr.v6;
@@ -229,7 +229,7 @@ if_addr_del(struct kaddr *ka)
        struct if_addr          *if_addr;
        struct nbr              *nbr;
 
-       iface = if_lookup(leconf, ka->ifindex);
+       iface = if_lookup_name(leconf, ka->ifname);
        if (iface) {
                if (ka->af == AF_INET6 &&
                    IN6_ARE_ADDR_EQUAL(&iface->linklocal, &ka->addr.v6))
@@ -328,7 +328,7 @@ if_reset(struct iface *iface, int af)
 }
 
 static void
-if_update_af(struct iface_af *ia, int link_ok)
+if_update_af(struct iface_af *ia)
 {
        int                      addr_ok = 0, socket_ok, rtr_id_ok;
        struct if_addr          *if_addr;
@@ -366,13 +366,14 @@ if_update_af(struct iface_af *ia, int link_ok)
                rtr_id_ok = 0;
 
        if (ia->state == IF_STA_DOWN) {
-               if (!ia->enabled || !link_ok || !addr_ok || !socket_ok ||
-                   !rtr_id_ok)
+               if (!ia->enabled || !ia->iface->operative || !addr_ok ||
+                   !socket_ok || !rtr_id_ok)
                        return;
 
                if_start(ia->iface, ia->af);
        } else if (ia->state == IF_STA_ACTIVE) {
-               if (ia->enabled && link_ok && addr_ok && socket_ok && rtr_id_ok)
+               if (ia->enabled && ia->iface->operative && addr_ok &&
+                   socket_ok && rtr_id_ok)
                        return;
 
                if_reset(ia->iface, ia->af);
@@ -382,14 +383,10 @@ if_update_af(struct iface_af *ia, int link_ok)
 void
 ldp_if_update(struct iface *iface, int af)
 {
-       int                      link_ok;
-
-       link_ok = (iface->flags & IFF_UP) && (iface->flags & IFF_RUNNING);
-
        if (af == AF_INET || af == AF_UNSPEC)
-               if_update_af(&iface->ipv4, link_ok);
+               if_update_af(&iface->ipv4);
        if (af == AF_INET6 || af == AF_UNSPEC)
-               if_update_af(&iface->ipv6, link_ok);
+               if_update_af(&iface->ipv6);
 }
 
 void
@@ -464,7 +461,6 @@ if_to_ctl(struct iface_af *ia)
        memcpy(ictl.name, ia->iface->name, sizeof(ictl.name));
        ictl.ifindex = ia->iface->ifindex;
        ictl.state = ia->state;
-       ictl.flags = ia->iface->flags;
        ictl.type = ia->iface->type;
        ictl.hello_holdtime = if_get_hello_holdtime(ia);
        ictl.hello_interval = if_get_hello_interval(ia);
index 92d865210a32c5e330c7bc8cb2d90521f3af448e..27948f5a1aa50debfd6659a4396e2d15f666c37c 100644 (file)
@@ -142,7 +142,7 @@ void
 l2vpn_if_update_info(struct l2vpn_if *lif, struct kif *kif)
 {
        lif->ifindex = kif->ifindex;
-       lif->flags = kif->flags;
+       lif->operative = kif->operative;
        memcpy(lif->mac, kif->mac, sizeof(lif->mac));
 }
 
@@ -154,7 +154,7 @@ l2vpn_if_update(struct l2vpn_if *lif)
        struct map       fec;
        struct nbr      *nbr;
 
-       if ((lif->flags & IFF_UP) && (lif->flags & IFF_RUNNING))
+       if (lif->operative)
                return;
 
        RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
index 241603b8e11c7566cf9a79057fb35d03f9386594..3320238a05c6df1add4b166b524ddb9ea462e408 100644 (file)
@@ -64,7 +64,7 @@ ifp2kif(struct interface *ifp, struct kif *kif)
        memset(kif, 0, sizeof(*kif));
        strlcpy(kif->ifname, ifp->name, sizeof(kif->ifname));
        kif->ifindex = ifp->ifindex;
-       kif->flags = ifp->flags;
+       kif->operative = if_is_operative(ifp);
        if (ifp->ll_type == ZEBRA_LLT_ETHER)
                memcpy(kif->mac, ifp->hw_addr, ETHER_ADDR_LEN);
 }
@@ -73,6 +73,7 @@ static void
 ifc2kaddr(struct interface *ifp, struct connected *ifc, struct kaddr *ka)
 {
        memset(ka, 0, sizeof(*ka));
+       strlcpy(ka->ifname, ifp->name, sizeof(ka->ifname));
        ka->ifindex = ifp->ifindex;
        ka->af = ifc->address->family;
        ka->prefixlen = ifc->address->prefixlen;
@@ -232,6 +233,7 @@ ldp_interface_delete(int command, struct zclient *zclient, zebra_size_t length,
     vrf_id_t vrf_id)
 {
        struct interface        *ifp;
+       struct kif               kif;
 
        /* zebra_interface_state_read() updates interface structure in iflist */
        ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
@@ -243,7 +245,10 @@ ldp_interface_delete(int command, struct zclient *zclient, zebra_size_t length,
 
        /* To support pseudo interface do not free interface structure.  */
        /* if_delete(ifp); */
-       ifp->ifindex = IFINDEX_INTERNAL;
+       ifp->ifindex = IFINDEX_DELETED;
+
+       ifp2kif(ifp, &kif);
+       main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif));
 
        return (0);
 }
@@ -257,7 +262,6 @@ ldp_interface_status_change(int command, struct zclient *zclient,
        struct connected        *ifc;
        struct kif               kif;
        struct kaddr             ka;
-       int                      link_new;
 
        /*
         * zebra_interface_state_read() updates interface structure in
@@ -272,8 +276,7 @@ ldp_interface_status_change(int command, struct zclient *zclient,
        ifp2kif(ifp, &kif);
        main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif));
 
-       link_new = (ifp->flags & IFF_UP) && (ifp->flags & IFF_RUNNING);
-       if (link_new) {
+       if (if_is_operative(ifp)) {
                for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
                        ifc2kaddr(ifp, ifc, &ka);
                        main_imsg_compose_ldpe(IMSG_NEWADDR, 0, &ka,
@@ -309,8 +312,8 @@ ldp_interface_address_add(int command, struct zclient *zclient,
        if (bad_addr(ka.af, &ka.addr))
                return (0);
 
-       debug_zebra_in("address add %s/%u", log_addr(ka.af, &ka.addr),
-           ka.prefixlen);
+       debug_zebra_in("address add %s/%u interface %s",
+           log_addr(ka.af, &ka.addr), ka.prefixlen, ifp->name);
 
        /* notify ldpe about new address */
        main_imsg_compose_ldpe(IMSG_NEWADDR, 0, &ka, sizeof(ka));
@@ -338,8 +341,8 @@ ldp_interface_address_delete(int command, struct zclient *zclient,
        if (bad_addr(ka.af, &ka.addr))
                return (0);
 
-       debug_zebra_in("address delete %s/%u", log_addr(ka.af, &ka.addr),
-           ka.prefixlen);
+       debug_zebra_in("address delete %s/%u interface %s",
+           log_addr(ka.af, &ka.addr), ka.prefixlen, ifp->name);
 
        /* notify ldpe about removed address */
        main_imsg_compose_ldpe(IMSG_DELADDR, 0, &ka, sizeof(ka));
index cba1939d98b67e845256380387ecf115435ada82..3acc4fbe2d8b1f97551c4e3daf02657b6658d09a 100644 (file)
@@ -305,7 +305,7 @@ struct iface {
        struct if_addr_head      addr_list;
        struct in6_addr          linklocal;
        enum iface_type          type;
-       uint16_t                 flags;
+       int                      operative;
        struct iface_af          ipv4;
        struct iface_af          ipv6;
        QOBJ_FIELDS
@@ -387,7 +387,7 @@ struct l2vpn_if {
        struct l2vpn            *l2vpn;
        char                     ifname[IF_NAMESIZE];
        unsigned int             ifindex;
-       uint16_t                 flags;
+       int                      operative;
        uint8_t                  mac[ETHER_ADDR_LEN];
        QOBJ_FIELDS
 };
@@ -553,6 +553,7 @@ struct kpw {
 };
 
 struct kaddr {
+       char                     ifname[IF_NAMESIZE];
        unsigned short           ifindex;
        int                      af;
        union ldpd_addr          addr;
@@ -564,6 +565,7 @@ struct kif {
        char                     ifname[IF_NAMESIZE];
        unsigned short           ifindex;
        int                      flags;
+       int                      operative;
        uint8_t                  mac[ETHER_ADDR_LEN];
        int                      mtu;
 };
@@ -581,7 +583,6 @@ struct ctl_iface {
        char                     name[IF_NAMESIZE];
        unsigned int             ifindex;
        int                      state;
-       uint16_t                 flags;
        enum iface_type          type;
        uint16_t                 hello_holdtime;
        uint16_t                 hello_interval;
index 2f6ee1c04fdccaebc4c8da30000c3f8ab4e409e3..a44ce35bb8e91f933b965c204bb32b2a063f74fd 100644 (file)
@@ -44,11 +44,9 @@ static zebra_capabilities_t _caps_p [] = {
 };
 
 static struct zebra_privs_t nhrpd_privs = {
-#ifdef QUAGGA_USER
-       .user = QUAGGA_USER,
-#endif
-#ifdef QUAGGA_GROUP
-       .group = QUAGGA_GROUP,
+#if defined(FRR_USER) && defined(FRR_GROUP)
+       .user = FRR_USER,
+       .group = FRR_GROUP,
 #endif
 #ifdef VTY_GROUP
        .vty_group = VTY_GROUP,
index 036cc6d4c85ca21b6d5843a2b57494f138df24a0..aa219c78071f78944089ecce7867c793a0cfcf41 100644 (file)
@@ -147,19 +147,19 @@ parse_type_spec (int idx_lsa, int argc, struct cmd_token **argv)
 
   if (argc > idx_lsa)
     {
-      if (strmatch (argv[0]->text, "router"))
+      if (strmatch (argv[idx_lsa]->text, "router"))
         type = htons (OSPF6_LSTYPE_ROUTER);
-      else if (strmatch (argv[0]->text, "network"))
+      else if (strmatch (argv[idx_lsa]->text, "network"))
         type = htons (OSPF6_LSTYPE_NETWORK);
-      else if (strmatch (argv[0]->text, "as-external"))
+      else if (strmatch (argv[idx_lsa]->text, "as-external"))
         type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
-      else if (strmatch (argv[0]->text, "intra-prefix"))
+      else if (strmatch (argv[idx_lsa]->text, "intra-prefix"))
         type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
-      else if (strmatch (argv[0]->text, "inter-router"))
+      else if (strmatch (argv[idx_lsa]->text, "inter-router"))
         type = htons (OSPF6_LSTYPE_INTER_ROUTER);
-      else if (strmatch (argv[0]->text, "inter-prefix"))
+      else if (strmatch (argv[idx_lsa]->text, "inter-prefix"))
         type = htons (OSPF6_LSTYPE_INTER_PREFIX);
-      else if (strmatch (argv[0]->text, "link"))
+      else if (strmatch (argv[idx_lsa]->text, "link"))
         type = htons (OSPF6_LSTYPE_LINK);
     }
 
@@ -296,7 +296,7 @@ DEFUN (show_ipv6_ospf6_database_id,
        "Dump LSAs\n"
        "Display LSA's internal information\n")
 {
-  int idx_ipv4 = 4;
+  int idx_ipv4 = 5;
   int idx_level = 6;
   int level;
   struct listnode *i, *j;
@@ -388,7 +388,7 @@ DEFUN (show_ipv6_ospf6_database_router,
 
 DEFUN (show_ipv6_ospf6_database_type_id,
        show_ipv6_ospf6_database_type_id_cmd,
-       "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> [linkstate-id] A.B.C.D [<detail|dump|internal>]",
+       "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> linkstate-id A.B.C.D [<detail|dump|internal>]",
        SHOW_STR
        IPV6_STR
        OSPF6_STR
index b4a282a52a1ed324c2f5b6e96b585d1af9089149..aeb12a59fa2770cc932dbf465ccfe47c6accb6a7 100644 (file)
@@ -333,46 +333,6 @@ ospf_if_free (struct ospf_interface *oi)
   XFREE (MTYPE_OSPF_IF, oi);
 }
 
-
-/*
-*  check if interface with given address is configured and
-*  return it if yes.  special treatment for PtP networks.
-*/
-struct ospf_interface *
-ospf_if_is_configured (struct ospf *ospf, struct in_addr *address)
-{
-  struct listnode *node, *nnode;
-  struct ospf_interface *oi;
-  struct prefix_ipv4 addr;
-
-  addr.family = AF_INET;
-  addr.prefix = *address;
-  addr.prefixlen = IPV4_MAX_PREFIXLEN;
-
-  for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
-    if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
-      {
-        if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED))
-          {
-            if (htonl(oi->ifp->ifindex) == address->s_addr)
-              return oi;
-          }
-        else if (oi->type == OSPF_IFTYPE_POINTOPOINT)
-         {
-           /* special leniency: match if addr is anywhere on peer subnet */
-           if (prefix_match(CONNECTED_PREFIX(oi->connected),
-                            (struct prefix *)&addr))
-             return oi;
-         }
-        else
-         {
-           if (IPV4_ADDR_SAME (address, &oi->address->u.prefix4))
-             return oi;
-         }
-      }
-  return NULL;
-}
-
 int
 ospf_if_is_up (struct ospf_interface *oi)
 {
index 8e6ecb57eb2cf8d65d6616bb5e88f25c8ae1510a..23a0e682c8925f07edbbbf795b6fa62c35ae5dfe 100644 (file)
@@ -7161,7 +7161,7 @@ DEFUN (no_ospf_redistribute_source,
 
 DEFUN (ospf_redistribute_instance_source,
        ospf_redistribute_instance_source_cmd,
-       "redistribute <ospf|table> (1-65535) [<metric (0-16777214)|metric-type (1-2)|route-map WORD>]",
+       "redistribute <ospf|table> (1-65535) {<metric (0-16777214)|metric-type (1-2)|route-map WORD>}",
        REDIST_STR
        "Open Shortest Path First\n"
        "Non-main Kernel Routing Table\n"
@@ -7177,7 +7177,7 @@ DEFUN (ospf_redistribute_instance_source,
   VTY_DECLVAR_CONTEXT(ospf, ospf);
   int idx_ospf_table = 1;
   int idx_number = 2;
-  int idx_redist_param = 3;
+  int idx = 3;
   int source;
   int type = -1;
   int metric = -1;
@@ -7209,19 +7209,21 @@ DEFUN (ospf_redistribute_instance_source,
     }
 
   /* Get metric value. */
-  if (strcmp (argv[idx_redist_param]->arg, "metric") == 0)
-    if (!str2metric (argv[idx_redist_param+1]->arg, &metric))
+  if (argv_find (argv, argc, "metric", &idx))
+    if (!str2metric (argv[idx+1]->arg, &metric))
       return CMD_WARNING;
 
+  idx = 3;
   /* Get metric type. */
-  if (strcmp (argv[idx_redist_param]->arg, "metric-type") == 0)
-    if (!str2metric_type (argv[idx_redist_param+1]->arg, &type))
+  if (argv_find (argv, argc, "metric-type", &idx))
+    if (!str2metric_type (argv[idx+1]->arg, &type))
       return CMD_WARNING;
 
   red = ospf_redist_add(ospf, source, instance);
 
-  if (strcmp (argv[idx_redist_param]->arg, "route-map") == 0)
-    ospf_routemap_set (red, argv[idx_redist_param+1]->arg);
+  idx = 3;
+  if (argv_find (argv, argc, "route-map", &idx))
+    ospf_routemap_set (red, argv[idx+1]->arg);
   else
     ospf_routemap_unset (red);
 
@@ -7230,7 +7232,7 @@ DEFUN (ospf_redistribute_instance_source,
 
 DEFUN (no_ospf_redistribute_instance_source,
        no_ospf_redistribute_instance_source_cmd,
-       "no redistribute <ospf|table> (1-65535) [<metric (0-16777214)|metric-type (1-2)|route-map WORD>]",
+       "no redistribute <ospf|table> (1-65535) {<metric (0-16777214)|metric-type (1-2)|route-map WORD>}",
        NO_STR
        REDIST_STR
        "Open Shortest Path First\n"
index 53a080a3ab308249c360806aeeee59200fc83269..f1a73afa9a81c14abc6edcafddd3ccfffd338e29 100644 (file)
@@ -3561,6 +3561,33 @@ pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, const cha
   return CMD_SUCCESS;
 }
 
+static int
+pim_cmd_spt_switchover (enum pim_spt_switchover spt, const char *plist)
+{
+  pimg->spt.switchover = spt;
+
+  switch (pimg->spt.switchover)
+    {
+    case PIM_SPT_IMMEDIATE:
+      if (pimg->spt.plist)
+        XFREE (MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist);
+
+      pim_upstream_add_lhr_star_pimreg ();
+      break;
+    case PIM_SPT_INFINITY:
+      pim_upstream_remove_lhr_star_pimreg (plist);
+
+      if (pimg->spt.plist)
+        XFREE (MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist);
+
+      if (plist)
+        pimg->spt.plist = XSTRDUP (MTYPE_PIM_SPT_PLIST_NAME, plist);
+      break;
+    }
+
+  return CMD_SUCCESS;
+}
+
 DEFUN (ip_pim_spt_switchover_infinity,
        ip_pim_spt_switchover_infinity_cmd,
        "ip pim spt-switchover infinity-and-beyond",
@@ -3569,10 +3596,20 @@ DEFUN (ip_pim_spt_switchover_infinity,
        "SPT-Switchover\n"
        "Never switch to SPT Tree\n")
 {
-  pimg->spt_switchover = PIM_SPT_INFINITY;
+  return pim_cmd_spt_switchover (PIM_SPT_INFINITY, NULL);
+}
 
-  pim_upstream_remove_lhr_star_pimreg();
-  return CMD_SUCCESS;
+DEFUN (ip_pim_spt_switchover_infinity_plist,
+       ip_pim_spt_switchover_infinity_plist_cmd,
+       "ip pim spt-switchover infinity-and-beyond prefix-list WORD",
+       IP_STR
+       PIM_STR
+       "SPT-Switchover\n"
+       "Never switch to SPT Tree\n"
+       "Prefix-List to control which groups to switch\n"
+       "Prefix-List name\n")
+{
+  return pim_cmd_spt_switchover (PIM_SPT_INFINITY, argv[5]->arg);
 }
 
 DEFUN (no_ip_pim_spt_switchover_infinity,
@@ -3584,15 +3621,26 @@ DEFUN (no_ip_pim_spt_switchover_infinity,
        "SPT_Switchover\n"
        "Never switch to SPT Tree\n")
 {
-  pimg->spt_switchover = PIM_SPT_IMMEDIATE;
+  return pim_cmd_spt_switchover (PIM_SPT_IMMEDIATE, NULL);
+}
 
-  pim_upstream_add_lhr_star_pimreg();
-  return CMD_SUCCESS;
+DEFUN (no_ip_pim_spt_switchover_infinity_plist,
+       no_ip_pim_spt_switchover_infinity_plist_cmd,
+       "no ip pim spt-switchover infinity-and-beyond prefix-list WORD",
+       NO_STR
+       IP_STR
+       PIM_STR
+       "SPT_Switchover\n"
+       "Never switch to SPT Tree\n"
+       "Prefix-List to control which groups to switch\n"
+       "Prefix-List name\n")
+{
+  return pim_cmd_spt_switchover (PIM_SPT_IMMEDIATE, NULL);
 }
 
 DEFUN (ip_pim_joinprune_time,
        ip_pim_joinprune_time_cmd,
-       "ip pim join-prune-interval <60-600>",
+       "ip pim join-prune-interval (60-600)",
        IP_STR
        "pim multicast routing\n"
        "Join Prune Send Interval\n"
@@ -3604,7 +3652,7 @@ DEFUN (ip_pim_joinprune_time,
 
 DEFUN (no_ip_pim_joinprune_time,
        no_ip_pim_joinprune_time_cmd,
-       "no ip pim join-prune-interval <60-600>",
+       "no ip pim join-prune-interval (60-600)",
        NO_STR
        IP_STR
        "pim multicast routing\n"
@@ -3617,19 +3665,19 @@ DEFUN (no_ip_pim_joinprune_time,
 
 DEFUN (ip_pim_register_suppress,
        ip_pim_register_suppress_cmd,
-       "ip pim register-suppress-time <5-60000>",
+       "ip pim register-suppress-time (5-60000)",
        IP_STR
        "pim multicast routing\n"
        "Register Suppress Timer\n"
        "Seconds\n")
 {
-  qpim_keep_alive_time = atoi (argv[3]->arg);
+  qpim_register_suppress_time = atoi (argv[3]->arg);
   return CMD_SUCCESS;
 }
 
 DEFUN (no_ip_pim_register_suppress,
        no_ip_pim_register_suppress_cmd,
-       "no ip pim register-suppress-time <5-60000>",
+       "no ip pim register-suppress-time (5-60000)",
        NO_STR
        IP_STR
        "pim multicast routing\n"
@@ -3642,19 +3690,19 @@ DEFUN (no_ip_pim_register_suppress,
 
 DEFUN (ip_pim_keep_alive,
        ip_pim_keep_alive_cmd,
-       "ip pim keep-alive-timer <31-60000>",
+       "ip pim keep-alive-timer (31-60000)",
        IP_STR
        "pim multicast routing\n"
        "Keep alive Timer\n"
        "Seconds\n")
 {
-  qpim_rp_keep_alive_time = atoi (argv[4]->arg);
+  qpim_keep_alive_time = atoi (argv[3]->arg);
   return CMD_SUCCESS;
 }
 
 DEFUN (no_ip_pim_keep_alive,
        no_ip_pim_keep_alive_cmd,
-       "no ip pim keep-alive-timer <31-60000>",
+       "no ip pim keep-alive-timer (31-60000)",
        NO_STR
        IP_STR
        "pim multicast routing\n"
@@ -3667,7 +3715,7 @@ DEFUN (no_ip_pim_keep_alive,
 
 DEFUN (ip_pim_packets,
        ip_pim_packets_cmd,
-       "ip pim packets <1-100>",
+       "ip pim packets (1-100)",
        IP_STR
        "pim multicast routing\n"
        "packets to process at one time per fd\n"
@@ -3679,7 +3727,7 @@ DEFUN (ip_pim_packets,
 
 DEFUN (no_ip_pim_packets,
        no_ip_pim_packets_cmd,
-       "no ip pim packets <1-100>",
+       "no ip pim packets (1-100)",
        NO_STR
        IP_STR
        "pim multicast routing\n"
@@ -3727,9 +3775,10 @@ DEFUN (ip_pim_rp,
   int idx_ipv4 = 3;
 
   if (argc == (idx_ipv4 + 1))
-    return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL);
-  else
     return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, NULL, NULL);
+  else
+    return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL);
+
 }
 
 DEFUN (ip_pim_rp_prefix_list,
@@ -4087,23 +4136,37 @@ static int
 pim_cmd_igmp_start (struct vty *vty, struct interface *ifp)
 {
   struct pim_interface *pim_ifp;
+  uint8_t need_startup = 0;
 
   pim_ifp = ifp->info;
 
-  if (!pim_ifp) {
-    pim_ifp = pim_if_new(ifp, 1 /* igmp=true */, 0 /* pim=false */);
-    if (!pim_ifp) {
-      vty_out(vty, "Could not enable IGMP on interface %s%s",
+  if (!pim_ifp)
+    {
+      pim_ifp = pim_if_new(ifp, 1 /* igmp=true */, 0 /* pim=false */);
+      if (!pim_ifp)
+        {
+          vty_out(vty, "Could not enable IGMP on interface %s%s",
              ifp->name, VTY_NEWLINE);
-      return CMD_WARNING;
+          return CMD_WARNING;
+        }
+      need_startup = 1;
+    }
+  else
+    {
+      if (!PIM_IF_TEST_IGMP(pim_ifp->options))
+        {
+          PIM_IF_DO_IGMP(pim_ifp->options);
+          need_startup = 1;
+        }
     }
-  }
-  else {
-    PIM_IF_DO_IGMP(pim_ifp->options);
-  }
 
-  pim_if_addr_add_all(ifp);
-  pim_if_membership_refresh(ifp);
+  /* 'ip igmp' executed multiple times, with need_startup
+    avoid multiple if add all and membership refresh */
+  if (need_startup)
+    {
+      pim_if_addr_add_all(ifp);
+      pim_if_membership_refresh(ifp);
+    }
 
   return CMD_SUCCESS;
 }
@@ -4469,22 +4532,37 @@ DEFUN (interface_ip_igmp_version,
        "IGMP version number\n")
 {
   VTY_DECLVAR_CONTEXT(interface,ifp);
-  struct pim_interface *pim_ifp;
-  int igmp_version;
+  struct pim_interface *pim_ifp = NULL;
+  int igmp_version, old_version = 0;
   int ret;
 
   pim_ifp = ifp->info;
 
-  if (!pim_ifp) {
-    ret = pim_cmd_igmp_start(vty, ifp);
-    if (ret != CMD_SUCCESS)
-      return ret;
-    pim_ifp = ifp->info;
-  }
+  if (!pim_ifp)
+    {
+      ret = pim_cmd_igmp_start(vty, ifp);
+      if (ret != CMD_SUCCESS)
+        return ret;
+      pim_ifp = ifp->info;
+    }
 
   igmp_version = atoi(argv[3]->arg);
+  old_version = pim_ifp->igmp_version;
   pim_ifp->igmp_version = igmp_version;
 
+  //Check if IGMP is Enabled otherwise, enable on interface
+  if (!PIM_IF_TEST_IGMP (pim_ifp->options))
+    {
+      PIM_IF_DO_IGMP(pim_ifp->options);
+      pim_if_addr_add_all(ifp);
+      pim_if_membership_refresh(ifp);
+      old_version = igmp_version;   //avoid refreshing membership again.
+    }
+  /* Current and new version is different refresh existing
+     membership. Going from 3 -> 2 or 2 -> 3. */
+  if (old_version != igmp_version)
+    pim_if_membership_refresh(ifp);
+
   return CMD_SUCCESS;
 }
 
@@ -6442,7 +6520,9 @@ void pim_cmd_init()
   install_element (CONFIG_NODE, &ip_pim_register_suppress_cmd);
   install_element (CONFIG_NODE, &no_ip_pim_register_suppress_cmd);
   install_element (CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd);
+  install_element (CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
   install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
+  install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_plist_cmd);
   install_element (CONFIG_NODE, &ip_pim_joinprune_time_cmd);
   install_element (CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
   install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd);
index ebd36f8782509c45fa47abaa3e4ab54156dd9afd..d267ee9fb288d1786426d60361d59146e46ed0bc 100644 (file)
@@ -27,6 +27,7 @@
 #include "vrf.h"
 #include "hash.h"
 #include "jhash.h"
+#include "prefix.h"
 
 #include "pimd.h"
 #include "pim_str.h"
@@ -49,30 +50,25 @@ pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2)
   struct pim_interface *pim_ifp1;
   struct pim_interface *pim_ifp2;
 
-  if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr))
-    return -1;
-
-  if (ntohl(ch1->sg.grp.s_addr) > ntohl(ch2->sg.grp.s_addr))
-    return 1;
+  pim_ifp1 = ch1->interface->info;
+  pim_ifp2 = ch2->interface->info;
 
-  if (ntohl(ch1->sg.src.s_addr) < ntohl(ch2->sg.src.s_addr))
+  if (pim_ifp1->mroute_vif_index < pim_ifp2->mroute_vif_index)
     return -1;
 
-  if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr))
+  if (pim_ifp1->mroute_vif_index > pim_ifp2->mroute_vif_index)
     return 1;
 
-  pim_ifp1 = ch1->interface->info;
-  pim_ifp2 = ch2->interface->info;
-  if (ntohl(pim_ifp1->primary_address.s_addr) < ntohl(pim_ifp2->primary_address.s_addr))
+  if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr))
     return -1;
 
-  if (ntohl(pim_ifp1->primary_address.s_addr) > ntohl(pim_ifp2->primary_address.s_addr))
+  if (ntohl(ch1->sg.grp.s_addr) > ntohl(ch2->sg.grp.s_addr))
     return 1;
 
-  if (pim_ifp1->mroute_vif_index < pim_ifp2->mroute_vif_index)
+  if (ntohl(ch1->sg.src.s_addr) < ntohl(ch2->sg.src.s_addr))
     return -1;
 
-  if (pim_ifp1->mroute_vif_index > pim_ifp2->mroute_vif_index)
+  if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr))
     return 1;
 
   return 0;
@@ -174,6 +170,8 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
   if (ch->sources)
     list_delete (ch->sources);
 
+  listnode_delete(ch->upstream->ifchannels, ch);
+
   if (ch->ifjoin_state != PIM_IFJOIN_NOINFO) {
     pim_upstream_update_join_desired(ch->upstream);
   }
@@ -568,6 +566,8 @@ pim_ifchannel_add(struct interface *ifp,
   ch = hash_get (pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern);
   listnode_add_sort(pim_ifchannel_list, ch);
 
+  listnode_add_sort(up->ifchannels, ch);
+
   return ch;
 }
 
@@ -958,7 +958,7 @@ int
 pim_ifchannel_local_membership_add(struct interface *ifp,
                                   struct prefix_sg *sg)
 {
-  struct pim_ifchannel *ch;
+  struct pim_ifchannel *ch, *starch;
   struct pim_interface *pim_ifp;
 
   /* PIM enabled on interface? */
@@ -993,21 +993,41 @@ pim_ifchannel_local_membership_add(struct interface *ifp,
       struct pim_upstream *child;
       struct listnode *up_node;
 
+      starch = ch;
+
       for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child))
         {
-         if (PIM_DEBUG_EVENTS)
-           zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s",
-                      __FILE__, __PRETTY_FUNCTION__,
-                      child->sg_str, ifp->name, up->sg_str);
+          if (PIM_DEBUG_EVENTS)
+            zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s",
+                       __FILE__, __PRETTY_FUNCTION__,
+                       child->sg_str, ifp->name, up->sg_str);
 
-         if (pim_upstream_evaluate_join_desired_interface (child, ch))
-           {
-             pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_STAR);
-             pim_upstream_switch (child, PIM_UPSTREAM_JOINED);
-           }
+          ch = pim_ifchannel_find (ifp, &child->sg);
+          if (pim_upstream_evaluate_join_desired_interface (child, ch, starch))
+            {
+              pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_STAR);
+              pim_upstream_switch (child, PIM_UPSTREAM_JOINED);
+            }
         }
-      if (pimg->spt_switchover != PIM_SPT_INFINITY)
-        pim_channel_add_oif(up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
+
+      if (pimg->spt.switchover == PIM_SPT_INFINITY)
+        {
+          if (pimg->spt.plist)
+            {
+              struct prefix_list *plist = prefix_list_lookup (AFI_IP, pimg->spt.plist);
+              struct prefix g;
+              g.family = AF_INET;
+              g.prefixlen = IPV4_MAX_PREFIXLEN;
+              g.u.prefix4 = up->sg.grp;
+
+              if (prefix_list_apply (plist, &g) == PREFIX_DENY)
+                {
+                  pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
+                }
+            }
+         }
+       else
+         pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
     }
 
   return 1;
@@ -1016,7 +1036,7 @@ pim_ifchannel_local_membership_add(struct interface *ifp,
 void pim_ifchannel_local_membership_del(struct interface *ifp,
                                        struct prefix_sg *sg)
 {
-  struct pim_ifchannel *ch;
+  struct pim_ifchannel *starch, *ch, *orig;
   struct pim_interface *pim_ifp;
 
   /* PIM enabled on interface? */
@@ -1026,7 +1046,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
   if (!PIM_IF_TEST_PIM(pim_ifp->options))
     return;
 
-  ch = pim_ifchannel_find(ifp, sg);
+  orig = ch = pim_ifchannel_find(ifp, sg);
   if (!ch)
     return;
 
@@ -1036,9 +1056,11 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
     {
       struct pim_upstream *up = pim_upstream_find (sg);
       struct pim_upstream *child;
-      struct listnode *up_node;
+      struct listnode *up_node, *up_nnode;
 
-      for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child))
+      starch = ch;
+
+      for (ALL_LIST_ELEMENTS (up->sources, up_node, up_nnode, child))
         {
          struct channel_oil *c_oil = child->channel_oil;
          struct pim_ifchannel *chchannel = pim_ifchannel_find (ifp, &child->sg);
@@ -1049,7 +1071,8 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
                       __FILE__, __PRETTY_FUNCTION__,
                       up->sg_str, ifp->name, child->sg_str);
 
-         if (c_oil && !pim_upstream_evaluate_join_desired_interface (child, ch))
+          ch = pim_ifchannel_find (ifp, &child->sg);
+         if (c_oil && !pim_upstream_evaluate_join_desired_interface (child, ch, starch))
             pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR);
 
          /*
@@ -1059,9 +1082,12 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
           */
          if (!chchannel && c_oil && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index])
             pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR);
+
+          if (c_oil->oil_size == 0)
+            pim_upstream_del (child, __PRETTY_FUNCTION__);
         }
     }
-  delete_on_noinfo(ch);
+  delete_on_noinfo(orig);
 }
 
 void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch)
@@ -1223,20 +1249,55 @@ pim_ifchannel_scan_forward_start (struct interface *new_ifp)
  * we get End of Message
  */
 void
-pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom)
+pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join)
 {
   struct pim_ifchannel *child;
   struct listnode *ch_node;
 
   if (PIM_DEBUG_PIM_TRACE)
-    zlog_debug ("%s: %s %s eom: %d", __PRETTY_FUNCTION__,
+    zlog_debug ("%s: %s %s eom: %d join %u", __PRETTY_FUNCTION__,
                 pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
-                ch->sg_str, eom);
+                ch->sg_str, eom, join);
   if (!ch->sources)
     return;
 
   for (ALL_LIST_ELEMENTS_RO (ch->sources, ch_node, child))
     {
+      /* Only *,G Join received and no (SG-RPT) prune.
+         Scan all S,G associated to G and if any SG-RPT
+         remove the SG-RPT flag.
+      */
+      if (join && (source_flags & PIM_RPT_BIT_MASK) &&
+          (source_flags & PIM_WILDCARD_BIT_MASK))
+        {
+          if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags))
+            {
+              struct pim_upstream *up = child->upstream;
+
+              PIM_IF_FLAG_UNSET_S_G_RPT(child->flags);
+              if (up)
+                {
+                  if (PIM_DEBUG_TRACE)
+                    zlog_debug ("%s: add inherit oif to up %s ", __PRETTY_FUNCTION__, up->sg_str);
+                  pim_channel_add_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR);
+                }
+            }
+        }
+      /* Received SG-RPT Prune delete oif from S,G */
+      else if (join == 0 && (source_flags & PIM_RPT_BIT_MASK) &&
+               !(source_flags & PIM_WILDCARD_BIT_MASK))
+        {
+          struct pim_upstream *up = child->upstream;
+
+          PIM_IF_FLAG_SET_S_G_RPT(child->flags);
+          if (up)
+            {
+              if (PIM_DEBUG_TRACE)
+                zlog_debug ("%s: del inherit oif from up %s", __PRETTY_FUNCTION__, up->sg_str);
+              pim_channel_del_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR);
+            }
+        }
+
       if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags))
         continue;
 
index fe9fb9a7f10d6a086cb9544ccb6e475c9fafa862..3ffb9190fb336eb50dbf20af9a11e9b76a6aa33f 100644 (file)
@@ -151,7 +151,7 @@ void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch);
 void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch);
 
 void pim_ifchannel_scan_forward_start (struct interface *new_ifp);
-void pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom);
+void pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join);
 
 int pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2);
 
index 884aa35bc563d3d6b21e1154f71e81a38597dd3f..a9ca349102297bd2e7859e7bb00284a861c02b05 100644 (file)
@@ -276,7 +276,7 @@ int pim_joinprune_recv(struct interface *ifp,
         {
           ch = pim_ifchannel_find (ifp, &sg);
          if (ch)
-           pim_ifchannel_set_star_g_join_state (ch, 0);
+           pim_ifchannel_set_star_g_join_state (ch, 0, msg_source_flags, 1);
         }
     }
 
@@ -297,7 +297,7 @@ int pim_joinprune_recv(struct interface *ifp,
                 msg_source_flags);
     }
     if (ch)
-      pim_ifchannel_set_star_g_join_state (ch, 1);
+      pim_ifchannel_set_star_g_join_state (ch, 1, msg_source_flags, 0);
     ch = NULL;
   } /* scan groups */
 
@@ -387,7 +387,13 @@ int pim_joinprune_send(struct pim_rpf *rpf,
 
   on_trace (__PRETTY_FUNCTION__, rpf->source_nexthop.interface, rpf->rpf_addr.u.prefix4);
 
-  pim_ifp = rpf->source_nexthop.interface->info;
+  if (rpf->source_nexthop.interface)
+    pim_ifp = rpf->source_nexthop.interface->info;
+  else
+    {
+      zlog_warn ("%s: RPF interface is not present", __PRETTY_FUNCTION__);
+      return -1;
+    }
 
   if (!pim_ifp) {
     zlog_warn("%s: multicast not enabled on interface %s",
index 251e67a35195e3d33b6b9a1d2fc697c9d64b6d7a..ce4ddfd4a4a20baa4ba904982ad1fac49bd40ab8 100644 (file)
@@ -343,8 +343,9 @@ pim_jp_agg_single_upstream_send (struct pim_rpf *rpf,
   static bool first = true;
 
   /* skip JP upstream messages if source is directly connected */
-  if (pim_if_connected_to_source (rpf->source_nexthop.interface, up->sg.src))
-      return;
+  if (!rpf->source_nexthop.interface ||
+      pim_if_connected_to_source (rpf->source_nexthop.interface, up->sg.src))
+    return;
 
   if (first)
     {
index 2acca6f49be879483ee3cdc56db6fa8c4eaac0d0..ab92665b97939469f4fbab9eb6998d135488024e 100644 (file)
@@ -52,3 +52,4 @@ DEFINE_MTYPE(PIMD, PIM_JP_AGG_SOURCE,     "PIM JP AGG Source")
 DEFINE_MTYPE(PIMD, PIM_PIM_INSTANCE,      "PIM global state")
 DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE,     "PIM nexthop cache state")
 DEFINE_MTYPE(PIMD, PIM_SSM_INFO,          "PIM SSM configuration")
+DEFINE_MTYPE(PIMD, PIM_SPT_PLIST_NAME,    "PIM SPT Prefix List Name")
index 02446de46a65f93d48c725d129490a15ba10cb86..e366377c87b5dae6ee2f8c75139b23ecb424ceaa 100644 (file)
@@ -51,5 +51,6 @@ DECLARE_MTYPE(PIM_JP_AGG_SOURCE)
 DECLARE_MTYPE(PIM_PIM_INSTANCE)
 DECLARE_MTYPE(PIM_NEXTHOP_CACHE)
 DECLARE_MTYPE(PIM_SSM_INFO)
+DECLARE_MTYPE(PIM_SPT_PLIST_NAME);
 
 #endif /* _QUAGGA_PIM_MEMORY_H */
index c04a6254851960344e9e9565800cd7abaf7fa982..de0f75e38072f96057a32d5f68def74cc06eab99 100644 (file)
@@ -455,6 +455,9 @@ struct pim_neighbor *pim_neighbor_find(struct interface *ifp,
   struct listnode      *node;
   struct pim_neighbor  *neigh;
 
+  if (!ifp)
+    return NULL;
+
   pim_ifp = ifp->info;
   if (!pim_ifp)
     return NULL;
index 23efd554ea0f2bbe294a0bf4d5b33be4c38f6409..98c98cdf24da1eb391d6d42f62e839da6a268a0a 100644 (file)
@@ -276,7 +276,6 @@ pim_update_rp_nh (struct pim_nexthop_cache *pnc)
 {
   struct listnode *node = NULL;
   struct rp_info *rp_info = NULL;
-  int ret = 0;
 
   /*Traverse RP list and update each RP Nexthop info */
   for (ALL_LIST_ELEMENTS_RO (pnc->rp_list, node, rp_info))
@@ -299,11 +298,7 @@ pim_update_rp_nh (struct pim_nexthop_cache *pnc)
         }
     }
 
-  if (ret)
-    return 0;
-
-  return 1;
-
+  return 0;
 }
 
 /* This API is used to traverse nexthop cache of RPF addr
@@ -670,7 +665,10 @@ pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc,
 
     }
 
-  return 0;
+  if (found)
+    return 0;
+  else
+    return -1;
 }
 
 /* This API is used to parse Registered address nexthop update coming from Zebra */
index 12f8dd53f268683cd52af94f2888a0399d8f8f32..8dc179c1444ccec91166b93a72e5ee3a35c5de33 100644 (file)
@@ -190,7 +190,7 @@ pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct
   if (PIM_DEBUG_PIM_REG)
     {
       char rp_str[INET_ADDRSTRLEN];
-      strcpy (rp_str, inet_ntoa (rpg->rpf_addr.u.prefix4));
+      strncpy (rp_str, inet_ntoa (rpg->rpf_addr.u.prefix4), INET_ADDRSTRLEN-1);
       zlog_debug ("%s: Sending %s %sRegister Packet to %s on %s",
               __PRETTY_FUNCTION__, up->sg_str,
               null_register ? "NULL " : "", rp_str, ifp->name);
index 1dd5dae303cfc2ead9b49c6e378afdb36898a61f..feddb8d8d54f9424cb2a521f6f2fb905d7afb577 100644 (file)
@@ -281,7 +281,7 @@ pim_rp_check_interfaces (struct rp_info *rp_info)
 int
 pim_rp_new (const char *rp, const char *group_range, const char *plist)
 {
-  int result, ret = 0;
+  int result;
   struct rp_info *rp_info;
   struct rp_info *rp_all;
   struct prefix group_all;
@@ -400,12 +400,12 @@ pim_rp_new (const char *rp, const char *group_range, const char *plist)
                           __PRETTY_FUNCTION__, buf, buf1);
             }
           memset (&pnc, 0, sizeof (struct pim_nexthop_cache));
-          if ((ret =
-               pim_find_or_track_nexthop (&nht_p, NULL, rp_all, &pnc)) == 1)
+          if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_all, &pnc)) == 1)
             {
               //Compute PIM RPF using Cached nexthop
-              pim_ecmp_nexthop_search (&pnc, &rp_all->rp.source_nexthop,
-                                       &nht_p, &rp_all->group, 1);
+              if ((pim_ecmp_nexthop_search (&pnc, &rp_all->rp.source_nexthop,
+                                       &nht_p, &rp_all->group, 1)) != 0)
+                return PIM_RP_NO_PATH;
             }
           else
             {
@@ -471,11 +471,12 @@ pim_rp_new (const char *rp, const char *group_range, const char *plist)
     }
 
   memset (&pnc, 0, sizeof (struct pim_nexthop_cache));
-  if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1)
+  if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1)
     {
       //Compute PIM RPF using Cached nexthop
-      pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop,
-                               &nht_p, &rp_info->group, 1);
+      if (pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop,
+                               &nht_p, &rp_info->group, 1) != 0)
+        return PIM_RP_NO_PATH;
     }
   else
     {
@@ -575,8 +576,9 @@ pim_rp_setup (void)
       if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1)
         {
           //Compute PIM RPF using Cached nexthop
-          pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop,
-                                   &nht_p, &rp_info->group, 1);
+          if ((pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop,
+                                   &nht_p, &rp_info->group, 1)) != 0)
+            ret++;
         }
       else
         {
@@ -727,7 +729,6 @@ pim_rp_g (struct in_addr group)
 
   if (rp_info)
     {
-      int ret = 0;
       struct prefix nht_p;
       struct pim_nexthop_cache pnc;
       /* Register addr with Zebra NHT */
@@ -744,7 +745,7 @@ pim_rp_g (struct in_addr group)
                       __PRETTY_FUNCTION__, buf, buf1);
         }
       memset (&pnc, 0, sizeof (struct pim_nexthop_cache));
-      if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1)
+      if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1)
         {
           //Compute PIM RPF using Cached nexthop
           pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop,
index 0f5fab0d93596fa81721638322e02ba5aa14578e..f454ac59c1ac476b55f5c1c201923b5894d56131 100644 (file)
@@ -225,11 +225,14 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old,
       if (pnc.nexthop_num)
         {
           //Compute PIM RPF using Cached nexthop
-          pim_ecmp_nexthop_search (&pnc, &up->rpf.source_nexthop,
-                                   &src, &grp,
-                                   !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) &&
-                                   !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->
-                                                                     flags));
+          if (pim_ecmp_nexthop_search (&pnc, &up->rpf.source_nexthop,
+                                       &src, &grp,
+                                       !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) &&
+                                       !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags)))
+
+            {
+              return PIM_RPF_FAILURE;
+            }
         }
     }
   else
index 71634ebfe546211bef2dc6ccd1d3e1b28b8bf6a7..1e31a3aba1e3459e200548632607ca833ee0200e 100644 (file)
@@ -214,6 +214,8 @@ pim_upstream_del(struct pim_upstream *up, const char *name)
     }
   up->sources = NULL;
 
+  list_delete (up->ifchannels);
+
   /*
     notice that listnode_delete() can't be moved
     into pim_upstream_free() because the later is
@@ -439,18 +441,10 @@ static void forward_on(struct pim_upstream *up)
 {
   struct listnode      *chnode;
   struct listnode      *chnextnode;
-  struct pim_interface *pim_ifp;
-  struct pim_ifchannel *ch;
+  struct pim_ifchannel *ch = NULL;
 
   /* scan (S,G) state */
-  for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
-    pim_ifp = ch->interface->info;
-    if (!pim_ifp)
-      continue;
-
-    if (ch->upstream != up)
-      continue;
-
+  for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
     if (pim_macro_chisin_oiflist(ch))
       pim_forward_start(ch);
 
@@ -461,17 +455,10 @@ static void forward_off(struct pim_upstream *up)
 {
   struct listnode      *chnode;
   struct listnode      *chnextnode;
-  struct pim_interface *pim_ifp;
   struct pim_ifchannel *ch;
 
   /* scan per-interface (S,G) state */
-  for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
-    pim_ifp = ch->interface->info;
-    if (!pim_ifp)
-      continue;
-
-    if (ch->upstream != up)
-      continue;
+  for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
 
     pim_forward_stop(ch);
 
@@ -481,7 +468,15 @@ static void forward_off(struct pim_upstream *up)
 static int
 pim_upstream_could_register (struct pim_upstream *up)
 {
-  struct pim_interface *pim_ifp = up->rpf.source_nexthop.interface->info;
+  struct pim_interface *pim_ifp = NULL;
+
+  if (up->rpf.source_nexthop.interface)
+    pim_ifp = up->rpf.source_nexthop.interface->info;
+  else
+    {
+      if (PIM_DEBUG_TRACE)
+        zlog_debug ("%s: up %s RPF is not present", __PRETTY_FUNCTION__, up->sg_str);
+    }
 
   if (pim_ifp && PIM_I_am_DR (pim_ifp) &&
       pim_if_connected_to_source (up->rpf.source_nexthop.interface, up->sg.src))
@@ -673,6 +668,9 @@ pim_upstream_new (struct prefix_sg *sg,
   up->rpf.rpf_addr.family                         = AF_INET;
   up->rpf.rpf_addr.u.prefix4.s_addr               = PIM_NET_INADDR_ANY;
 
+  up->ifchannels                 = list_new();
+  up->ifchannels->cmp            = (int (*)(void *, void *))pim_ifchannel_compare;
+
   if (up->sg.src.s_addr != INADDR_ANY)
     wheel_add_item (pim_upstream_sg_wheel, up);
 
@@ -800,38 +798,34 @@ struct pim_upstream *pim_upstream_add(struct prefix_sg *sg,
   return up;
 }
 
+/*
+ * Passed in up must be the upstream for ch.  starch is NULL if no
+ * information
+ */
 int
 pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up,
-                                             struct pim_ifchannel *ch)
+                                              struct pim_ifchannel *ch,
+                                              struct pim_ifchannel *starch)
 {
-  struct pim_upstream *parent = up->parent;
-
-  if (ch->upstream == up)
+  if (ch)
     {
       if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
-       return 0;
+        return 0;
 
       if (!pim_macro_ch_lost_assert(ch) && pim_macro_chisin_joins_or_include(ch))
-       return 1;
+        return 1;
     }
 
   /*
    * joins (*,G)
    */
-  if (parent && ch->upstream == parent)
+  if (starch)
     {
-      struct listnode *ch_node;
-      struct pim_ifchannel *child;
-      for (ALL_LIST_ELEMENTS_RO (ch->sources, ch_node, child))
-        {
-          if (child->upstream == up)
-            {
-               if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags))
-                 return 0;
-             }
-        }
-      if (!pim_macro_ch_lost_assert (ch) && pim_macro_chisin_joins_or_include (ch))
-       return 1;
+      if (PIM_IF_FLAG_TEST_S_G_RPT (starch->upstream->flags))
+        return 0;
+
+      if (!pim_macro_ch_lost_assert (starch) && pim_macro_chisin_joins_or_include (starch))
+        return 1;
     }
 
   return 0;
@@ -862,20 +856,28 @@ pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up,
  */
 int pim_upstream_evaluate_join_desired(struct pim_upstream *up)
 {
-  struct listnode      *chnode;
-  struct listnode      *chnextnode;
-  struct pim_interface *pim_ifp;
-  struct pim_ifchannel *ch;
+  struct interface     *ifp;
+  struct listnode      *node;
+  struct pim_ifchannel *ch, *starch;
+  struct pim_upstream  *starup = up->parent;
   int                  ret = 0;
 
-  /* scan per-interface (S,G) state */
-  for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch))
+  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
     {
-      pim_ifp = ch->interface->info;
-      if (!pim_ifp)
-       continue;
+      if (!ifp->info)
+        continue;
+
+      ch = pim_ifchannel_find (ifp, &up->sg);
+
+      if (starup)
+        starch = pim_ifchannel_find (ifp, &starup->sg);
+      else
+        starch = NULL;
 
-      ret += pim_upstream_evaluate_join_desired_interface (up, ch);
+      if (!ch && !starch)
+        continue;
+
+      ret += pim_upstream_evaluate_join_desired_interface (up, ch, starch);
     } /* scan iface channel list */
 
   return ret; /* false */
@@ -962,18 +964,9 @@ void pim_upstream_rpf_interface_changed(struct pim_upstream *up,
   struct listnode      *chnode;
   struct listnode      *chnextnode;
   struct pim_ifchannel *ch;
-  struct pim_interface *pim_ifp;
 
   /* search all ifchannels */
-  for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
-
-    pim_ifp = ch->interface->info;
-    if (!pim_ifp)
-      continue;
-
-    if (ch->upstream != up)
-      continue;
-
+  for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
     if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) {
       if (
          /* RPF_interface(S) was NOT I */
@@ -994,18 +987,10 @@ void pim_upstream_update_could_assert(struct pim_upstream *up)
 {
   struct listnode      *chnode;
   struct listnode      *chnextnode;
-  struct pim_interface *pim_ifp;
   struct pim_ifchannel *ch;
 
   /* scan per-interface (S,G) state */
-  for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
-    pim_ifp = ch->interface->info;
-    if (!pim_ifp)
-      continue;
-
-    if (ch->upstream != up)
-      continue;
-
+  for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
     pim_ifchannel_update_could_assert(ch);
   } /* scan iface channel list */
 }
@@ -1014,18 +999,10 @@ void pim_upstream_update_my_assert_metric(struct pim_upstream *up)
 {
   struct listnode      *chnode;
   struct listnode      *chnextnode;
-  struct pim_interface *pim_ifp;
   struct pim_ifchannel *ch;
 
   /* scan per-interface (S,G) state */
-  for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
-    pim_ifp = ch->interface->info;
-    if (!pim_ifp)
-      continue;
-
-    if (ch->upstream != up)
-      continue;
-
+  for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
     pim_ifchannel_update_my_assert_metric(ch);
 
   } /* scan iface channel list */
@@ -1039,14 +1016,11 @@ static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up)
   struct pim_ifchannel *ch;
 
   /* scan per-interface (S,G) state */
-  for (ALL_LIST_ELEMENTS(pim_ifchannel_list, chnode, chnextnode, ch)) {
+  for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
     pim_ifp = ch->interface->info;
     if (!pim_ifp)
       continue;
 
-    if (ch->upstream != up)
-      continue;
-
     pim_ifchannel_update_assert_tracking_desired(ch);
 
   } /* scan iface channel list */
@@ -1216,11 +1190,10 @@ pim_upstream_is_sg_rpt (struct pim_upstream *up)
   struct listnode *chnode;
   struct pim_ifchannel *ch;
 
-  for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, chnode, ch))
+  for (ALL_LIST_ELEMENTS_RO(up->ifchannels, chnode, ch))
     {
-      if ((ch->upstream == up) &&
-         (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)))
-       return 1;
+      if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
+        return 1;
     }
 
   return 0;
@@ -1439,31 +1412,48 @@ pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_regist
 int
 pim_upstream_inherited_olist_decide (struct pim_upstream *up)
 {
-  struct pim_interface *pim_ifp;
-  struct listnode *chnextnode;
-  struct pim_ifchannel *ch;
-  struct listnode *chnode;
+  struct interface *ifp;
+  struct pim_interface *pim_ifp = NULL;
+  struct pim_ifchannel *ch, *starch;
+  struct listnode *node;
+  struct pim_upstream *starup = up->parent;
   int output_intf = 0;
 
-  pim_ifp = up->rpf.source_nexthop.interface->info;
+  if (up->rpf.source_nexthop.interface)
+    pim_ifp = up->rpf.source_nexthop.interface->info;
+  else
+    {
+      if (PIM_DEBUG_TRACE)
+        zlog_debug ("%s: up %s RPF is not present", __PRETTY_FUNCTION__, up->sg_str);
+    }
   if (pim_ifp && !up->channel_oil)
     up->channel_oil = pim_channel_oil_add (&up->sg, pim_ifp->mroute_vif_index);
 
-  for (ALL_LIST_ELEMENTS (pim_ifchannel_list, chnode, chnextnode, ch))
+  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
     {
-      pim_ifp = ch->interface->info;
-      if (!pim_ifp)
-       continue;
+      if (!ifp->info)
+        continue;
 
-      if (pim_upstream_evaluate_join_desired_interface (up, ch))
-       {
+      ch = pim_ifchannel_find (ifp, &up->sg);
+
+      if (starup)
+        starch = pim_ifchannel_find (ifp, &starup->sg);
+      else
+        starch = NULL;
+
+      if (!ch && !starch)
+        continue;
+
+      if (pim_upstream_evaluate_join_desired_interface (up, ch, starch))
+        {
           int flag = PIM_OIF_FLAG_PROTO_PIM;
 
-          if (ch->sg.src.s_addr == INADDR_ANY && ch->upstream != up)
+          if (!ch)
             flag = PIM_OIF_FLAG_PROTO_STAR;
-          pim_channel_add_oif (up->channel_oil, ch->interface, flag);
-         output_intf++;
-       }
+
+          pim_channel_add_oif (up->channel_oil, ifp, flag);
+          output_intf++;
+        }
     }
 
   return output_intf;
@@ -1701,10 +1691,41 @@ pim_upstream_add_lhr_star_pimreg (void)
 }
 
 void
-pim_upstream_remove_lhr_star_pimreg (void)
+pim_upstream_spt_prefix_list_update (struct prefix_list *pl)
+{
+  const char *pname = prefix_list_name (pl);
+
+  if (pimg->spt.plist && strcmp (pimg->spt.plist, pname) == 0)
+    {
+      pim_upstream_remove_lhr_star_pimreg (pname);
+    }
+}
+
+/*
+ * nlist -> The new prefix list
+ *
+ * Per Group Application of pimreg to the OIL
+ * If the prefix list tells us DENY then
+ * we need to Switchover to SPT immediate
+ * so add the pimreg.
+ * If the prefix list tells us to ACCEPT than
+ * we need to Never do the SPT so remove
+ * the interface
+ *
+ */
+void
+pim_upstream_remove_lhr_star_pimreg (const char *nlist)
 {
   struct pim_upstream *up;
   struct listnode *node;
+  struct prefix_list *np;
+  struct prefix g;
+  enum prefix_list_type apply_new;
+
+  np = prefix_list_lookup (AFI_IP, nlist);
+
+  g.family = AF_INET;
+  g.prefixlen = IPV4_MAX_PREFIXLEN;
 
   for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, node, up))
     {
@@ -1714,7 +1735,17 @@ pim_upstream_remove_lhr_star_pimreg (void)
       if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags))
         continue;
 
-      pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
+      if (!nlist)
+        {
+          pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
+          continue;
+        }
+      g.u.prefix4 = up->sg.grp;
+      apply_new = prefix_list_apply (np, &g);
+      if (apply_new == PREFIX_DENY)
+        pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
+      else
+        pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
     }
 }
 
index a1af4483acd703695705ace44c8b66ef7e328fcd..f1c8df35b1671dfa668c72108cd671f55bae1639 100644 (file)
@@ -100,6 +100,7 @@ struct pim_upstream {
   uint32_t                 flags;
   struct channel_oil      *channel_oil;
   struct list             *sources;
+  struct list             *ifchannels;
 
   enum pim_upstream_state  join_state;
   enum pim_reg_state       reg_state;
@@ -149,7 +150,8 @@ struct pim_upstream *pim_upstream_del(struct pim_upstream *up, const char *name)
 
 int pim_upstream_evaluate_join_desired(struct pim_upstream *up);
 int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up,
-                                                 struct pim_ifchannel *ch);
+                                                 struct pim_ifchannel *ch,
+                                                 struct pim_ifchannel *starch);
 void pim_upstream_update_join_desired(struct pim_upstream *up);
 
 void pim_upstream_join_suppress(struct pim_upstream *up,
@@ -200,5 +202,7 @@ int pim_upstream_compare (void *arg1, void *arg2);
 void pim_upstream_register_reevaluate (void);
 
 void pim_upstream_add_lhr_star_pimreg (void);
-void pim_upstream_remove_lhr_star_pimreg (void);
+void pim_upstream_remove_lhr_star_pimreg (const char *nlist);
+
+void pim_upstream_spt_prefix_list_update (struct prefix_list *pl);
 #endif /* PIM_UPSTREAM_H */
index ea67039c02ae8a80f9557b18c98aaddb30fba4eb..62d1f936ecf5aeaeaa4a1c8da0ed59edfa574fde 100644 (file)
@@ -188,10 +188,14 @@ int pim_global_config_write(struct vty *vty)
                ssm->plist_name, VTY_NEWLINE);
       ++writes;
     }
-  if (pimg->spt_switchover == PIM_SPT_INFINITY)
+  if (pimg->spt.switchover == PIM_SPT_INFINITY)
     {
-      vty_out (vty, "ip pim spt-switchover infinity-and-beyond%s",
-               VTY_NEWLINE);
+      if (pimg->spt.plist)
+        vty_out (vty, "ip pim spt-switchover infinity-and-beyond prefix-list %s%s",
+                 pimg->spt.plist, VTY_NEWLINE);
+      else
+        vty_out (vty, "ip pim spt-switchover infinity-and-beyond%s",
+                 VTY_NEWLINE);
       ++writes;
     }
 
index 7b100ffa4e8e9d21f82e48a84501b832f389277a..fc6663776b9e861620e6b5f3d51ab23f1b4fc35c 100644 (file)
@@ -199,6 +199,7 @@ pim_prefix_list_update (struct prefix_list *plist)
 {
     pim_rp_prefix_list_update (plist);
     pim_ssm_prefix_list_update (plist);
+    pim_upstream_spt_prefix_list_update (plist);
 }
 
 static void
@@ -254,7 +255,9 @@ pim_instance_init (vrf_id_t vrf_id, afi_t afi)
   pim->vrf_id = vrf_id;
   pim->afi = afi;
 
-  pim->spt_switchover = PIM_SPT_IMMEDIATE;
+  pim->spt.switchover = PIM_SPT_IMMEDIATE;
+  pim->spt.plist = NULL;
+
   pim->rpf_hash = hash_create_size (256, pim_rpf_hash_key, pim_rpf_equal);
 
   if (PIM_DEBUG_ZEBRA)
index 0db7a7ad165b24b767d163c52f67f5adf4474ab9..e10155c209b3c35451de3e22ff2ac688c90712c8 100644 (file)
@@ -251,7 +251,10 @@ struct pim_instance
   afi_t afi;
   vrf_id_t vrf_id;
 
-  enum pim_spt_switchover spt_switchover;
+  struct {
+    enum pim_spt_switchover switchover;
+    char *plist;
+  } spt;
 
   struct hash *rpf_hash;
 
index 75f768e942b896aa169746af592bfa901502dcfb..a8220670d19c391080e311a5f59839468bff732f 100644 (file)
@@ -1,25 +1,8 @@
 EXTRA_DIST = snapcraft.yaml \
        README.snap_build.md \
        README.usage.md \
-       scripts/Makefile \
-       scripts/bgpd-service \
-       scripts/isisd-service \
-       scripts/ldpd-service \
-       scripts/ospf6d-service \
-       scripts/ospfd-service \
-       scripts/pimd-service \
-       scripts/ripd-service \
-       scripts/ripngd-service \
-       scripts/zebra-service \
-       defaults/bgpd.conf.default \
-       defaults/isisd.conf.default \
-       defaults/ldpd.conf.default \
-       defaults/ospf6d.conf.default \
-       defaults/ospfd.conf.default \
-       defaults/pimd.conf.default \
-       defaults/ripd.conf.default \
-       defaults/ripngd.conf.default \
-       defaults/vtysh.conf.default \
-       defaults/zebra.conf.default \
+       extra_version_info.txt \
+       scripts \
+       defaults \
        helpers \
        snap
index e1f2ce82da350e65c3222db06e52cbfecde89349..eeee6a17ad727aa1ae2d3093189532ac908c6309 100644 (file)
@@ -12,7 +12,12 @@ which uses earlier versions of snaps)
         git clone https://github.com/frrouting/frr.git
         cd frr
 
-3. Run Bootstrap and make distribution tar.gz
+3. (Optional) Add extra version information to 
+   `snapcraft/extra_version_info.txt`. Information in this file will
+   be displayed with the frr.version command (simple `cat` after
+   the display of the `zebra --version` output)
+
+4. Run Bootstrap and make distribution tar.gz
 
         ./bootstrap.sh
         ./configure --with-pkg-extra-version=-MySnapVersion
@@ -25,7 +30,7 @@ which uses earlier versions of snaps)
     This will build `frr-something.tar.gz` - the distribution tar and 
     the snapcraft/snapcraft.yaml with the matching version number
 
-4. Create snap
+5. Create snap
 
         cd snapcraft
         snapcraft
diff --git a/snapcraft/extra_version_info.txt b/snapcraft/extra_version_info.txt
new file mode 100644 (file)
index 0000000..e69de29
index 2a60d4d6522642a1493ead01dd0c203baaacdf83..966623d11dd630ee07fbc6b8064950e02c1850a6 100644 (file)
@@ -13,3 +13,5 @@ install:
        install -D -m 0755 ldpd-service $(DESTDIR)/bin/
        install -D -m 0755 nhrpd-service $(DESTDIR)/bin/
        install -D -m 0755 set-options $(DESTDIR)/bin/
+       install -D -m 0755 show_version $(DESTDIR)/bin/
+
diff --git a/snapcraft/scripts/show_version b/snapcraft/scripts/show_version
new file mode 100644 (file)
index 0000000..ca1c2aa
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+$SNAP/sbin/zebra --version
+$SNAP/bin/cat $SNAP/doc/extra_version_info.txt
+
+exit 0
index b5fb24a36163d92cb9b9b801bb6e39703e44ca32..eb61301953402fe4cd18b388b04d42e85b8b5881 100644 (file)
@@ -17,7 +17,7 @@ apps:
             - network-bind
             - network-control
     version:
-        command: sbin/zebra --version
+        command: bin/show_version
     readme:
         command: bin/cat $SNAP/doc/README.usage.md
     zebra:
@@ -192,12 +192,6 @@ parts:
         plugin: autotools
         source: ../frr-@PACKAGE_VERSION@.tar.gz
         configflags:
-            - --with-cflags=-g
-            - --with-cflags=-O0
-            - --with-cflags=-std=gnu99
-            - --with-cflags=-fpie
-            - --with-cflags=-fno-omit-frame-pointer
-            - --with-cflags=-Wall
             - --enable-vtysh
             - --enable-isisd
             - --enable-watchfrr
@@ -206,7 +200,6 @@ parts:
             - --enable-multipath=64
             - --enable-rtadv
             - --enable-irdp
-            - --enable-gcc-rdynamic
             - --enable-user=root
             - --enable-group=root
             - --enable-pimd
@@ -254,4 +247,5 @@ parts:
         organize:
             README.usage.md: doc/README.usage.md
             README.snap_build.md: doc/README.snap_build.md
+            extra_version_info.txt: doc/extra_version_info.txt
 
index 544b467e324692b7086c3d28837a15cea276a680..9b81f99607f59e5cb7d639d525abb9614a4f1b66 100644 (file)
@@ -76,6 +76,7 @@ endif
 
 if OSPF6D
 vtysh_scan += $(top_srcdir)/ospf6d/ospf6_abr.c
+vtysh_scan += $(top_srcdir)/ospf6d/ospf6_asbr.c
 vtysh_scan += $(top_srcdir)/ospf6d/ospf6_area.c
 vtysh_scan += $(top_srcdir)/ospf6d/ospf6_bfd.c
 vtysh_scan += $(top_srcdir)/ospf6d/ospf6_flood.c
index 3374f4d852817f70e9845b30f601d6419acc34b2..e90228b424362f8e8053022861a471ed33cf2859 100644 (file)
@@ -1147,23 +1147,25 @@ DEFUNSH (VTYSH_BGPD,
 }
 
 DEFUNSH (VTYSH_BGPD,
-        address_family_encapv4,
-        address_family_encapv4_cmd,
-        "address-family <encap|encapv4>",
-        "Enter Address Family command mode\n"
+         address_family_encapv4,
+         address_family_encapv4_cmd,
+         "address-family [ipv4] <encap|encapv4>",
+         "Enter Address Family command mode\n"
          "Address Family\n"
-        "Address Family\n")
+         "Address Family\n"
+         "Address Family\n")
 {
   vty->node = BGP_ENCAP_NODE;
   return CMD_SUCCESS;
 }
 
 DEFUNSH (VTYSH_BGPD,
-        address_family_encapv6,
-        address_family_encapv6_cmd,
-        "address-family encapv6",
-        "Enter Address Family command mode\n"
-        "Address Family\n")
+         address_family_encapv6,
+         address_family_encapv6_cmd,
+         "address-family [ipv6] encapv6",
+         "Enter Address Family command mode\n"
+         "Address Family\n"
+         "Address Family\n")
 {
   vty->node = BGP_ENCAPV6_NODE;
   return CMD_SUCCESS;
@@ -1172,64 +1174,96 @@ DEFUNSH (VTYSH_BGPD,
 DEFUNSH (VTYSH_BGPD,
          address_family_ipv4,
          address_family_ipv4_cmd,
-         "address-family ipv4 [<unicast|multicast|vpn|encap|labeled-unicast>]",
+         "address-family ipv4 [unicast]",
          "Enter Address Family command mode\n"
          "Address Family\n"
-         "Address Family modifier\n"
-         "Address Family modifier\n"
-         "Address Family modifier\n"
-         "Address Family modifier\n"
-         "Address Family modifier\n")
+         "Address Family Modifier\n")
 {
-  int idx = 0;
-
-  if (argv_find (argv, argc, "multicast", &idx))
-    vty->node = BGP_IPV4M_NODE;
-
-  else if (argv_find (argv, argc, "encap", &idx))
-    vty->node = BGP_ENCAP_NODE;
-
-  else if (argv_find (argv, argc, "vpn", &idx))
-    vty->node = BGP_VPNV4_NODE;
+  vty->node = BGP_IPV4_NODE;
+  return CMD_SUCCESS;
+}
 
-  else if (argv_find (argv, argc, "labeled-unicast", &idx))
-    vty->node = BGP_IPV4L_NODE;
+DEFUNSH (VTYSH_BGPD,
+         address_family_ipv4_multicast,
+         address_family_ipv4_multicast_cmd,
+         "address-family ipv4 multicast",
+         "Enter Address Family command mode\n"
+         "Address Family\n"
+         "Address Family modifier\n")
+{
+  vty->node = BGP_IPV4M_NODE;
+  return CMD_SUCCESS;
+}
 
-  else
-    vty->node = BGP_IPV4_NODE;
+DEFUNSH (VTYSH_BGPD,
+         address_family_ipv4_vpn,
+         address_family_ipv4_vpn_cmd,
+         "address-family ipv4 vpn",
+         "Enter Address Family command mode\n"
+         "Address Family\n"
+         "Address Family modifier\n")
+{
+  vty->node = BGP_VPNV4_NODE;
+  return CMD_SUCCESS;
+}
 
+DEFUNSH (VTYSH_BGPD,
+         address_family_ipv4_labeled_unicast,
+         address_family_ipv4_labeled_unicast_cmd,
+         "address-family ipv4 labeled_unicast",
+         "Enter Address Family command mode\n"
+         "Address Family\n"
+         "Address Family modifier\n")
+{
+  vty->node = BGP_IPV4L_NODE;
   return CMD_SUCCESS;
 }
 
 DEFUNSH (VTYSH_BGPD,
          address_family_ipv6,
          address_family_ipv6_cmd,
-         "address-family ipv6 [<unicast|multicast|vpn|encap|labeled-unicast>]",
+         "address-family ipv6 [unicast]",
          "Enter Address Family command mode\n"
          "Address Family\n"
-         "Address Family modifier\n"
-         "Address Family modifier\n"
-         "Address Family modifier\n"
-         "Address Family modifier\n"
          "Address Family modifier\n")
 {
-  int idx = 0;
-
-  if (argv_find (argv, argc, "multicast", &idx))
-    vty->node = BGP_IPV6M_NODE;
-
-  else if (argv_find (argv, argc, "encap", &idx))
-    vty->node = BGP_ENCAPV6_NODE;
-
-  else if (argv_find (argv, argc, "vpn", &idx))
-    vty->node = BGP_VPNV6_NODE;
+  vty->node = BGP_IPV6_NODE;
+  return CMD_SUCCESS;
+}
 
-  else if (argv_find (argv, argc, "labeled-unicast", &idx))
-    vty->node = BGP_IPV6L_NODE;
+DEFUNSH (VTYSH_BGPD,
+         address_family_ipv6_multicast,
+         address_family_ipv6_multicast_cmd,
+         "address-family ipv6 multicast",
+         "Enter Address Family command mode\n"
+         "Address Family\n"
+         "Address Family modifier\n")
+{
+  vty->node = BGP_IPV6M_NODE;
+  return CMD_SUCCESS;
+}
 
-  else
-    vty->node = BGP_IPV6_NODE;
+DEFUNSH (VTYSH_BGPD,
+         address_family_ipv6_vpn,
+         address_family_ipv6_vpn_cmd,
+         "address-family ipv6 vpn",
+         "Enter Address Family command mode\n"
+         "Address Family\n"
+         "Address Family modifier\n")
+{
+  vty->node = BGP_VPNV6_NODE;
+  return CMD_SUCCESS;
+}
 
+DEFUNSH (VTYSH_BGPD,
+         address_family_ipv6_labeled_unicast,
+         address_family_ipv6_labeled_unicast_cmd,
+         "address-family ipv6 labeled_unicast",
+         "Enter Address Family command mode\n"
+         "Address Family\n"
+         "Address Family modifier\n")
+{
+  vty->node = BGP_IPV6L_NODE;
   return CMD_SUCCESS;
 }
 
@@ -3371,7 +3405,13 @@ vtysh_init_vty (void)
   install_element (BGP_NODE, &vnc_l2_group_cmd);
 #endif
   install_element (BGP_NODE, &address_family_ipv4_cmd);
+  install_element (BGP_NODE, &address_family_ipv4_multicast_cmd);
+  install_element (BGP_NODE, &address_family_ipv4_vpn_cmd);
+  install_element (BGP_NODE, &address_family_ipv4_labeled_unicast_cmd);
   install_element (BGP_NODE, &address_family_ipv6_cmd);
+  install_element (BGP_NODE, &address_family_ipv6_multicast_cmd);
+  install_element (BGP_NODE, &address_family_ipv6_vpn_cmd);
+  install_element (BGP_NODE, &address_family_ipv6_labeled_unicast_cmd);
   install_element (BGP_NODE, &address_family_evpn_cmd);
   install_element (BGP_VPNV4_NODE, &exit_address_family_cmd);
   install_element (BGP_VPNV6_NODE, &exit_address_family_cmd);
index 28538fabdf6770748190e8d2947e72dbba5ea812..006fcf16f40c128b4a954d37eb99a65b3cc745af 100644 (file)
@@ -746,7 +746,7 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
     }
 
   /* See if interface is present. */
-  ifp = if_lookup_by_index_per_ns (zns, ifi->ifi_index);
+  ifp = if_lookup_by_name_per_ns (zns, name);
 
   if (h->nlmsg_type == RTM_NEWLINK)
     {
index 1eefe1339ce74998ffcd9219563208d5b50353dc..c3d303736204c1539415d335d8ef9b158f022190 100644 (file)
@@ -190,6 +190,7 @@ if_unlink_per_ns (struct interface *ifp)
 {
   ifp->node->info = NULL;
   route_unlock_node(ifp->node);
+  ifp->node = NULL;
 }
 
 /* Look up an interface by identifier within a NS */
@@ -210,6 +211,23 @@ if_lookup_by_index_per_ns (struct zebra_ns *ns, u_int32_t ifindex)
   return ifp;
 }
 
+/* Look up an interface by name within a NS */
+struct interface *
+if_lookup_by_name_per_ns (struct zebra_ns *ns, const char *ifname)
+{
+  struct route_node *rn;
+  struct interface *ifp;
+
+  for (rn = route_top (ns->if_table); rn; rn = route_next (rn))
+    {
+      ifp = (struct interface *)rn->info;
+      if (ifp && strcmp (ifp->name, ifname) == 0)
+       return (ifp);
+    }
+
+  return NULL;
+}
+
 const char *
 ifindex2ifname_per_ns (struct zebra_ns *zns, unsigned int ifindex)
 {
index 6039e2d37907d1a61c4fc8b9c8b93ee24c0bca9c..9f108760d62eee070878ddda7aa2f9292151b397 100644 (file)
@@ -236,6 +236,7 @@ struct zebra_if
 
 
 extern struct interface *if_lookup_by_index_per_ns (struct zebra_ns *, u_int32_t);
+extern struct interface *if_lookup_by_name_per_ns (struct zebra_ns *, const char *);
 extern struct interface *if_link_per_ns (struct zebra_ns *, struct interface *);
 extern const char *ifindex2ifname_per_ns (struct zebra_ns *, unsigned int);
 
index bc18ee5863650caee2eaa4f0a74522b3d55804d7..6b36891056944cf2e8c1fb60aedd94129cd68021 100644 (file)
@@ -265,6 +265,7 @@ zebra_vrf_delete (struct vrf *vrf)
            {
              route_unlock_node (rnode);
              list_delete_node (zebrad.mq->subq[i], lnode);
+             zebrad.mq->size--;
            }
        }
     }