diff options
author | Donald Sharp <sharpd@cumulusnetworks.com> | 2017-05-02 21:52:09 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2017-05-02 21:52:09 +0200 |
commit | 05ba625af7cbeb08322a1ea761732521816245bd (patch) | |
tree | b5501ff31d67ec53a0da4935f59a17478b637255 | |
parent | Merge remote-tracking branch 'origin/stable/2.0' (diff) | |
parent | update doc of ubuntu 12.04 (diff) | |
download | frr-05ba625af7cbeb08322a1ea761732521816245bd.tar.xz frr-05ba625af7cbeb08322a1ea761732521816245bd.zip |
Merge remote-tracking branch 'origin/stable/3.0'
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--; } } } |