summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2017-05-02 21:52:09 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2017-05-02 21:52:09 +0200
commit05ba625af7cbeb08322a1ea761732521816245bd (patch)
treeb5501ff31d67ec53a0da4935f59a17478b637255
parentMerge remote-tracking branch 'origin/stable/2.0' (diff)
parentupdate doc of ubuntu 12.04 (diff)
downloadfrr-05ba625af7cbeb08322a1ea761732521816245bd.tar.xz
frr-05ba625af7cbeb08322a1ea761732521816245bd.zip
Merge remote-tracking branch 'origin/stable/3.0'
-rw-r--r--bgpd/bgp_mplsvpn.c19
-rw-r--r--bgpd/bgp_route.c25
-rw-r--r--bgpd/bgp_vty.c110
-rwxr-xr-xconfigure.ac4
-rw-r--r--ldpd/interface.c26
-rw-r--r--ldpd/l2vpn.c4
-rw-r--r--ldpd/ldp_zebra.c21
-rw-r--r--ldpd/ldpd.h7
-rw-r--r--nhrpd/nhrp_main.c8
-rw-r--r--ospf6d/ospf6d.c18
-rw-r--r--ospfd/ospf_interface.c40
-rw-r--r--ospfd/ospf_vty.c20
-rw-r--r--pimd/pim_cmd.c154
-rw-r--r--pimd/pim_ifchannel.c129
-rw-r--r--pimd/pim_ifchannel.h2
-rw-r--r--pimd/pim_join.c12
-rw-r--r--pimd/pim_jp_agg.c5
-rw-r--r--pimd/pim_memory.c1
-rw-r--r--pimd/pim_memory.h1
-rw-r--r--pimd/pim_neighbor.c3
-rw-r--r--pimd/pim_nht.c12
-rw-r--r--pimd/pim_register.c2
-rw-r--r--pimd/pim_rp.c25
-rw-r--r--pimd/pim_rpf.c13
-rw-r--r--pimd/pim_upstream.c233
-rw-r--r--pimd/pim_upstream.h8
-rw-r--r--pimd/pim_vty.c10
-rw-r--r--pimd/pimd.c5
-rw-r--r--pimd/pimd.h5
-rw-r--r--snapcraft/Makefile.am23
-rw-r--r--snapcraft/README.snap_build.md9
-rw-r--r--snapcraft/extra_version_info.txt0
-rw-r--r--snapcraft/scripts/Makefile2
-rw-r--r--snapcraft/scripts/show_version6
-rw-r--r--snapcraft/snapcraft.yaml.in10
-rw-r--r--vtysh/Makefile.am1
-rw-r--r--vtysh/vtysh.c138
-rw-r--r--zebra/if_netlink.c2
-rw-r--r--zebra/interface.c18
-rw-r--r--zebra/interface.h1
-rw-r--r--zebra/zebra_vrf.c1
41 files changed, 682 insertions, 451 deletions
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index d29fb2603..88cde15e8 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -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]",
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 2666644c7..3e51831d1 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -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));
}
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 44389b99c..361ab3396 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -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))
diff --git a/configure.ac b/configure.ac
index bef74c726..c7dc641af 100755
--- a/configure.ac
+++ b/configure.ac
@@ -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
diff --git a/ldpd/interface.c b/ldpd/interface.c
index 767815247..440bb2dca 100644
--- a/ldpd/interface.c
+++ b/ldpd/interface.c
@@ -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);
diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c
index 92d865210..27948f5a1 100644
--- a/ldpd/l2vpn.c
+++ b/ldpd/l2vpn.c
@@ -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) {
diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c
index 241603b8e..3320238a0 100644
--- a/ldpd/ldp_zebra.c
+++ b/ldpd/ldp_zebra.c
@@ -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));
diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h
index cba1939d9..3acc4fbe2 100644
--- a/ldpd/ldpd.h
+++ b/ldpd/ldpd.h
@@ -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;
diff --git a/nhrpd/nhrp_main.c b/nhrpd/nhrp_main.c
index 2f6ee1c04..a44ce35bb 100644
--- a/nhrpd/nhrp_main.c
+++ b/nhrpd/nhrp_main.c
@@ -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,
diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c
index 036cc6d4c..aa219c780 100644
--- a/ospf6d/ospf6d.c
+++ b/ospf6d/ospf6d.c
@@ -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
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index b4a282a52..aeb12a59f 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -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)
{
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 8e6ecb57e..23a0e682c 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -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"
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 53a080a3a..f1a73afa9 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -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);
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index ebd36f878..d267ee9fb 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -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;
diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h
index fe9fb9a7f..3ffb9190f 100644
--- a/pimd/pim_ifchannel.h
+++ b/pimd/pim_ifchannel.h
@@ -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);
diff --git a/pimd/pim_join.c b/pimd/pim_join.c
index 884aa35bc..a9ca34910 100644
--- a/pimd/pim_join.c
+++ b/pimd/pim_join.c
@@ -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",
diff --git a/pimd/pim_jp_agg.c b/pimd/pim_jp_agg.c
index 251e67a35..ce4ddfd4a 100644
--- a/pimd/pim_jp_agg.c
+++ b/pimd/pim_jp_agg.c
@@ -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)
{
diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c
index 2acca6f49..ab92665b9 100644
--- a/pimd/pim_memory.c
+++ b/pimd/pim_memory.c
@@ -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")
diff --git a/pimd/pim_memory.h b/pimd/pim_memory.h
index 02446de46..e366377c8 100644
--- a/pimd/pim_memory.h
+++ b/pimd/pim_memory.h
@@ -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 */
diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c
index c04a62548..de0f75e38 100644
--- a/pimd/pim_neighbor.c
+++ b/pimd/pim_neighbor.c
@@ -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;
diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c
index 23efd554e..98c98cdf2 100644
--- a/pimd/pim_nht.c
+++ b/pimd/pim_nht.c
@@ -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 */
diff --git a/pimd/pim_register.c b/pimd/pim_register.c
index 12f8dd53f..8dc179c14 100644
--- a/pimd/pim_register.c
+++ b/pimd/pim_register.c
@@ -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);
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index 1dd5dae30..feddb8d8d 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -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,
diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c
index 0f5fab0d9..f454ac59c 100644
--- a/pimd/pim_rpf.c
+++ b/pimd/pim_rpf.c
@@ -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
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index 71634ebfe..1e31a3aba 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -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);
}
}
diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h
index a1af4483a..f1c8df35b 100644
--- a/pimd/pim_upstream.h
+++ b/pimd/pim_upstream.h
@@ -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 */
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index ea67039c0..62d1f936e 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -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;
}
diff --git a/pimd/pimd.c b/pimd/pimd.c
index 7b100ffa4..fc6663776 100644
--- a/pimd/pimd.c
+++ b/pimd/pimd.c
@@ -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)
diff --git a/pimd/pimd.h b/pimd/pimd.h
index 0db7a7ad1..e10155c20 100644
--- a/pimd/pimd.h
+++ b/pimd/pimd.h
@@ -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;
diff --git a/snapcraft/Makefile.am b/snapcraft/Makefile.am
index 75f768e94..a8220670d 100644
--- a/snapcraft/Makefile.am
+++ b/snapcraft/Makefile.am
@@ -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
diff --git a/snapcraft/README.snap_build.md b/snapcraft/README.snap_build.md
index e1f2ce82d..eeee6a17a 100644
--- a/snapcraft/README.snap_build.md
+++ b/snapcraft/README.snap_build.md
@@ -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
index 000000000..e69de29bb
--- /dev/null
+++ b/snapcraft/extra_version_info.txt
diff --git a/snapcraft/scripts/Makefile b/snapcraft/scripts/Makefile
index 2a60d4d65..966623d11 100644
--- a/snapcraft/scripts/Makefile
+++ b/snapcraft/scripts/Makefile
@@ -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
index 000000000..ca1c2aa28
--- /dev/null
+++ b/snapcraft/scripts/show_version
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+$SNAP/sbin/zebra --version
+$SNAP/bin/cat $SNAP/doc/extra_version_info.txt
+
+exit 0
diff --git a/snapcraft/snapcraft.yaml.in b/snapcraft/snapcraft.yaml.in
index b5fb24a36..eb6130195 100644
--- a/snapcraft/snapcraft.yaml.in
+++ b/snapcraft/snapcraft.yaml.in
@@ -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
diff --git a/vtysh/Makefile.am b/vtysh/Makefile.am
index 544b467e3..9b81f9960 100644
--- a/vtysh/Makefile.am
+++ b/vtysh/Makefile.am
@@ -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
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 3374f4d85..e90228b42 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -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);
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 28538fabd..006fcf16f 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -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)
{
diff --git a/zebra/interface.c b/zebra/interface.c
index 1eefe1339..c3d303736 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -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)
{
diff --git a/zebra/interface.h b/zebra/interface.h
index 6039e2d37..9f108760d 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -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);
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index bc18ee586..6b3689105 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -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--;
}
}
}