return ret;
}
-DEFPY (interface_ipv6_mld_join,
- interface_ipv6_mld_join_cmd,
- "ipv6 mld join X:X::X:X$group [X:X::X:X$source]",
+DEFPY_YANG_HIDDEN (interface_ipv6_mld_join,
+ interface_ipv6_mld_join_cmd,
+ "[no] ipv6 mld join X:X::X:X$grp [X:X::X:X]$src",
+ NO_STR
+ IPV6_STR
+ IFACE_MLD_STR
+ "MLD join multicast group\n"
+ "Multicast group address\n"
+ "Source address\n")
+{
+ nb_cli_enqueue_change(vty, ".", (!no ? NB_OP_CREATE : NB_OP_DESTROY),
+ NULL);
+ return nb_cli_apply_changes(vty, FRR_GMP_JOIN_GROUP_XPATH,
+ "frr-routing:ipv6", grp_str,
+ (src_str ? src_str : "::"));
+}
+ALIAS (interface_ipv6_mld_join,
+ interface_ipv6_mld_join_group_cmd,
+ "[no] ipv6 mld join-group X:X::X:X$grp [X:X::X:X]$src",
+ NO_STR
IPV6_STR
IFACE_MLD_STR
"MLD join multicast group\n"
"Multicast group address\n"
- "Source address\n")
-{
- char xpath[XPATH_MAXLEN];
-
- if (!IN6_IS_ADDR_MULTICAST(&group)) {
- vty_out(vty, "Invalid Multicast Address\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (source_str) {
- if (IPV6_ADDR_SAME(&source, &in6addr_any)) {
- vty_out(vty, "Bad source address %s\n", source_str);
- return CMD_WARNING_CONFIG_FAILED;
- }
- } else
- source_str = "::";
-
- snprintf(xpath, sizeof(xpath), FRR_GMP_JOIN_XPATH, "frr-routing:ipv6",
- group_str, source_str);
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
-
- return nb_cli_apply_changes(vty, NULL);
-}
-
-DEFPY (interface_no_ipv6_mld_join,
- interface_no_ipv6_mld_join_cmd,
- "no ipv6 mld join X:X::X:X$group [X:X::X:X$source]",
+ "Source address\n");
+
+DEFPY_YANG (interface_ipv6_mld_static_group,
+ interface_ipv6_mld_static_group_cmd,
+ "[no] ipv6 mld static-group X:X::X:X$grp [X:X::X:X]$src",
+ NO_STR
+ IPV6_STR
+ IFACE_MLD_STR
+ "Static multicast group\n"
+ "Multicast group address\n"
+ "Source address\n")
+{
+ nb_cli_enqueue_change(vty, ".", (!no ? NB_OP_CREATE : NB_OP_DESTROY),
+ NULL);
+ return nb_cli_apply_changes(vty, FRR_GMP_STATIC_GROUP_XPATH,
+ "frr-routing:ipv6", grp_str,
+ (src_str ? src_str : "::"));
+}
+
+DEFPY (interface_no_ipv6_mld_static_group,
+ interface_no_ipv6_mld_static_group_cmd,
+ "no ipv6 mld static-group X:X::X:X$group [X:X::X:X$source]",
NO_STR
IPV6_STR
IFACE_MLD_STR
- "MLD join multicast group\n"
+ "Static multicast group\n"
"Multicast group address\n"
"Source address\n")
{
} else
source_str = "::";
- snprintf(xpath, sizeof(xpath), FRR_GMP_JOIN_XPATH, "frr-routing:ipv6",
- group_str, source_str);
+ snprintf(xpath, sizeof(xpath), FRR_GMP_STATIC_GROUP_XPATH,
+ "frr-routing:ipv6", group_str, source_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
install_element(INTERFACE_NODE, &interface_ipv6_mld_cmd);
install_element(INTERFACE_NODE, &interface_no_ipv6_mld_cmd);
install_element(INTERFACE_NODE, &interface_ipv6_mld_join_cmd);
- install_element(INTERFACE_NODE, &interface_no_ipv6_mld_join_cmd);
+ install_element(INTERFACE_NODE, &interface_ipv6_mld_join_group_cmd);
+ install_element(INTERFACE_NODE, &interface_ipv6_mld_static_group_cmd);
install_element(INTERFACE_NODE, &interface_ipv6_mld_version_cmd);
install_element(INTERFACE_NODE, &interface_no_ipv6_mld_version_cmd);
install_element(INTERFACE_NODE, &interface_ipv6_mld_query_interval_cmd);
vty_json(vty, json);
}
+static void igmp_show_interface_static_group(struct pim_instance *pim,
+ struct vty *vty, bool uj)
+{
+ struct interface *ifp;
+ json_object *json = NULL;
+ json_object *json_iface = NULL;
+ json_object *json_grp = NULL;
+ json_object *json_grp_arr = NULL;
+
+ if (uj) {
+ json = json_object_new_object();
+ json_object_string_add(json, "vrf",
+ vrf_id_to_name(pim->vrf->vrf_id));
+ } else {
+ vty_out(vty,
+ "Interface Address Source Group\n");
+ }
+
+ FOR_ALL_INTERFACES (pim->vrf, ifp) {
+ struct pim_interface *pim_ifp;
+ struct listnode *node;
+ struct static_group *stgrp;
+ struct in_addr pri_addr;
+ char pri_addr_str[INET_ADDRSTRLEN];
+
+ pim_ifp = ifp->info;
+
+ if (!pim_ifp)
+ continue;
+
+ if (!pim_ifp->static_group_list)
+ continue;
+
+ pri_addr = pim_find_primary_addr(ifp);
+ pim_inet4_dump("<pri?>", pri_addr, pri_addr_str,
+ sizeof(pri_addr_str));
+
+ for (ALL_LIST_ELEMENTS_RO(pim_ifp->static_group_list, node,
+ stgrp)) {
+ char group_str[INET_ADDRSTRLEN];
+ char source_str[INET_ADDRSTRLEN];
+
+ pim_inet4_dump("<grp?>", stgrp->group_addr, group_str,
+ sizeof(group_str));
+ pim_inet4_dump("<src?>", stgrp->source_addr, source_str,
+ sizeof(source_str));
+
+ if (uj) {
+ json_object_object_get_ex(json, ifp->name,
+ &json_iface);
+
+ if (!json_iface) {
+ json_iface = json_object_new_object();
+ json_object_string_add(json_iface,
+ "name",
+ ifp->name);
+ json_object_object_add(json, ifp->name,
+ json_iface);
+ json_grp_arr = json_object_new_array();
+ json_object_object_add(json_iface,
+ "groups",
+ json_grp_arr);
+ }
+
+ json_grp = json_object_new_object();
+ json_object_string_add(json_grp, "source",
+ source_str);
+ json_object_string_add(json_grp, "group",
+ group_str);
+ json_object_string_add(json_grp, "primaryAddr",
+ pri_addr_str);
+ json_object_array_add(json_grp_arr, json_grp);
+ } else {
+ vty_out(vty, "%-16s %-15s %-15s %-15s\n",
+ ifp->name, pri_addr_str, source_str,
+ group_str);
+ }
+ } /* for (pim_ifp->static_group_list) */
+
+ } /* for (iflist) */
+
+ if (uj)
+ vty_json(vty, json);
+}
+
static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty,
const char *ifname, bool uj)
{
return CMD_SUCCESS;
}
+ALIAS (show_ip_igmp_join,
+ show_ip_igmp_join_group_cmd,
+ "show ip igmp [vrf NAME] join-group [json]",
+ SHOW_STR
+ IP_STR
+ IGMP_STR
+ VRF_CMD_HELP_STR
+ "IGMP static join information\n"
+ JSON_STR);
DEFUN (show_ip_igmp_join_vrf_all,
show_ip_igmp_join_vrf_all_cmd,
return CMD_SUCCESS;
}
+ALIAS (show_ip_igmp_join_vrf_all,
+ show_ip_igmp_join_group_vrf_all_cmd,
+ "show ip igmp vrf all join-group [json]",
+ SHOW_STR
+ IP_STR
+ IGMP_STR
+ VRF_CMD_HELP_STR
+ "IGMP static join information\n"
+ JSON_STR);
+
+DEFUN (show_ip_igmp_static_group,
+ show_ip_igmp_static_group_cmd,
+ "show ip igmp [vrf NAME] static-group [json]",
+ SHOW_STR
+ IP_STR
+ IGMP_STR
+ VRF_CMD_HELP_STR
+ "Static group information\n"
+ JSON_STR)
+{
+ int idx = 2;
+ bool uj = use_json(argc, argv);
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx, uj);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ igmp_show_interface_static_group(vrf->info, vty, uj);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_igmp_static_group_vrf_all,
+ show_ip_igmp_static_group_vrf_all_cmd,
+ "show ip igmp vrf all static-group [json]",
+ SHOW_STR
+ IP_STR
+ IGMP_STR
+ VRF_CMD_HELP_STR
+ "Static group information\n"
+ JSON_STR)
+{
+ bool uj = use_json(argc, argv);
+ struct vrf *vrf;
+ bool first = true;
+
+ if (uj)
+ vty_out(vty, "{ ");
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ if (uj) {
+ if (!first)
+ vty_out(vty, ", ");
+ vty_out(vty, " \"%s\": ", vrf->name);
+ first = false;
+ } else
+ vty_out(vty, "VRF: %s\n", vrf->name);
+ igmp_show_interface_static_group(vrf->info, vty, uj);
+ }
+ if (uj)
+ vty_out(vty, "}\n");
+
+ return CMD_SUCCESS;
+}
DEFPY(show_ip_igmp_groups,
show_ip_igmp_groups_cmd,
"frr-routing:ipv4");
}
-DEFUN (interface_ip_igmp_join,
- interface_ip_igmp_join_cmd,
- "ip igmp join A.B.C.D [A.B.C.D]",
- IP_STR
- IFACE_IGMP_STR
- "IGMP join multicast group\n"
- "Multicast group address\n"
- "Source address\n")
+DEFPY_YANG_HIDDEN (interface_ip_igmp_join,
+ interface_ip_igmp_join_cmd,
+ "[no] ip igmp join A.B.C.D$grp [A.B.C.D]$src",
+ NO_STR
+ IP_STR
+ IFACE_IGMP_STR
+ "IGMP join multicast group\n"
+ "Multicast group address\n"
+ "Source address\n")
{
- int idx_group = 3;
- int idx_source = 4;
- const char *source_str;
- char xpath[XPATH_MAXLEN];
-
- if (argc == 5) {
- source_str = argv[idx_source]->arg;
-
- if (strcmp(source_str, "0.0.0.0") == 0) {
- vty_out(vty, "Bad source address %s\n",
- argv[idx_source]->arg);
- return CMD_WARNING_CONFIG_FAILED;
- }
- } else
- source_str = "0.0.0.0";
-
- snprintf(xpath, sizeof(xpath), FRR_GMP_JOIN_XPATH,
- "frr-routing:ipv4", argv[idx_group]->arg, source_str);
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
-
- return nb_cli_apply_changes(vty, NULL);
+ nb_cli_enqueue_change(vty, ".", (!no ? NB_OP_CREATE : NB_OP_DESTROY),
+ NULL);
+ return nb_cli_apply_changes(vty, FRR_GMP_JOIN_GROUP_XPATH,
+ "frr-routing:ipv4", grp_str,
+ (src_str ? src_str : "0.0.0.0"));
}
-
-DEFUN (interface_no_ip_igmp_join,
- interface_no_ip_igmp_join_cmd,
- "no ip igmp join A.B.C.D [A.B.C.D]",
- NO_STR
- IP_STR
- IFACE_IGMP_STR
- "IGMP join multicast group\n"
- "Multicast group address\n"
- "Source address\n")
-{
- int idx_group = 4;
- int idx_source = 5;
- const char *source_str;
- char xpath[XPATH_MAXLEN];
-
- if (argc == 6) {
- source_str = argv[idx_source]->arg;
-
- if (strcmp(source_str, "0.0.0.0") == 0) {
- vty_out(vty, "Bad source address %s\n",
- argv[idx_source]->arg);
- return CMD_WARNING_CONFIG_FAILED;
- }
- } else
- source_str = "0.0.0.0";
-
- snprintf(xpath, sizeof(xpath), FRR_GMP_JOIN_XPATH,
- "frr-routing:ipv4", argv[idx_group]->arg, source_str);
-
- nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-
- return nb_cli_apply_changes(vty, NULL);
+ALIAS(interface_ip_igmp_join,
+ interface_ip_igmp_join_group_cmd,
+ "[no] ip igmp join-group A.B.C.D$grp [A.B.C.D]$src",
+ NO_STR
+ IP_STR
+ IFACE_IGMP_STR
+ "IGMP join multicast group\n"
+ "Multicast group address\n"
+ "Source address\n");
+
+DEFPY_YANG (interface_ip_igmp_static_group,
+ interface_ip_igmp_static_group_cmd,
+ "[no] ip igmp static-group A.B.C.D$grp [A.B.C.D]$src",
+ NO_STR
+ IP_STR
+ IFACE_IGMP_STR
+ "Static multicast group\n"
+ "Multicast group address\n"
+ "Source address\n")
+{
+ nb_cli_enqueue_change(vty, ".", (!no ? NB_OP_CREATE : NB_OP_DESTROY),
+ NULL);
+ return nb_cli_apply_changes(vty, FRR_GMP_STATIC_GROUP_XPATH,
+ "frr-routing:ipv4", grp_str,
+ (src_str ? src_str : "0.0.0.0"));
}
DEFUN (interface_ip_igmp_query_interval,
install_element(INTERFACE_NODE, &interface_ip_igmp_cmd);
install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd);
install_element(INTERFACE_NODE, &interface_ip_igmp_join_cmd);
- install_element(INTERFACE_NODE, &interface_no_ip_igmp_join_cmd);
+ install_element(INTERFACE_NODE, &interface_ip_igmp_join_group_cmd);
+ install_element(INTERFACE_NODE, &interface_ip_igmp_static_group_cmd);
install_element(INTERFACE_NODE, &interface_ip_igmp_version_cmd);
install_element(INTERFACE_NODE, &interface_no_ip_igmp_version_cmd);
install_element(INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd);
install_element(VIEW_NODE, &show_ip_igmp_interface_cmd);
install_element(VIEW_NODE, &show_ip_igmp_interface_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_igmp_join_cmd);
+ install_element(VIEW_NODE, &show_ip_igmp_join_group_cmd);
install_element(VIEW_NODE, &show_ip_igmp_join_vrf_all_cmd);
+ install_element(VIEW_NODE, &show_ip_igmp_join_group_vrf_all_cmd);
+ install_element(VIEW_NODE, &show_ip_igmp_static_group_cmd);
+ install_element(VIEW_NODE, &show_ip_igmp_static_group_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_igmp_groups_cmd);
install_element(VIEW_NODE, &show_ip_igmp_groups_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd);
#include "pim_jp_agg.h"
#include "pim_igmp_join.h"
#include "pim_vxlan.h"
+#include "pim_tib.h"
#include "pim6_mld.h"
static void pim_if_gm_join_del_all(struct interface *ifp);
+static void pim_if_static_group_del_all(struct interface *ifp);
static int gm_join_sock(const char *ifname, ifindex_t ifindex,
pim_addr group_addr, pim_addr source_addr,
pim_ifp->gm_enable = gm;
pim_ifp->gm_join_list = NULL;
+ pim_ifp->static_group_list = NULL;
pim_ifp->pim_neighbor_list = NULL;
pim_ifp->upstream_switch_list = NULL;
pim_ifp->pim_generation_id = 0;
assert(pim_ifp);
pim_ifp->pim->mcast_if_count--;
- if (pim_ifp->gm_join_list) {
+ if (pim_ifp->gm_join_list)
pim_if_gm_join_del_all(ifp);
- }
+
+ if (pim_ifp->static_group_list)
+ pim_if_static_group_del_all(ifp);
pim_ifchannel_delete_all(ifp);
#if PIM_IPV == 4
XFREE(MTYPE_PIM_IGMP_JOIN, ij);
}
+static void static_group_free(struct static_group *stgrp)
+{
+ XFREE(MTYPE_PIM_STATIC_GROUP, stgrp);
+}
+
static struct gm_join *gm_join_find(struct list *join_list, pim_addr group_addr,
pim_addr source_addr)
{
return ij;
}
- return 0;
+ return NULL;
+}
+
+static struct static_group *static_group_find(struct list *static_group_list,
+ pim_addr group_addr,
+ pim_addr source_addr)
+{
+ struct listnode *node;
+ struct static_group *stgrp;
+
+ assert(static_group_list);
+
+ for (ALL_LIST_ELEMENTS_RO(static_group_list, node, stgrp)) {
+ if ((!pim_addr_cmp(group_addr, stgrp->group_addr)) &&
+ (!pim_addr_cmp(source_addr, stgrp->source_addr)))
+ return stgrp;
+ }
+
+ return NULL;
}
static int gm_join_sock(const char *ifname, ifindex_t ifindex,
return ij;
}
+static struct static_group *static_group_new(struct interface *ifp,
+ pim_addr group_addr,
+ pim_addr source_addr)
+{
+ struct pim_interface *pim_ifp;
+ struct static_group *stgrp;
+ pim_sgaddr sg;
+
+ pim_ifp = ifp->info;
+ assert(pim_ifp);
+
+ stgrp = XCALLOC(MTYPE_PIM_STATIC_GROUP, sizeof(*stgrp));
+
+ stgrp->group_addr = group_addr;
+ stgrp->source_addr = source_addr;
+ stgrp->oilp = NULL;
+
+ memset(&sg, 0, sizeof(sg));
+ sg.src = source_addr;
+ sg.grp = group_addr;
+
+ tib_sg_gm_join(pim_ifp->pim, sg, ifp, &(stgrp->oilp));
+
+ listnode_add(pim_ifp->static_group_list, stgrp);
+
+ return stgrp;
+}
+
ferr_r pim_if_gm_join_add(struct interface *ifp, pim_addr group_addr,
pim_addr source_addr)
{
return 0;
}
-__attribute__((unused))
static void pim_if_gm_join_del_all(struct interface *ifp)
{
struct pim_interface *pim_ifp;
pim_if_gm_join_del(ifp, ij->group_addr, ij->source_addr);
}
+ferr_r pim_if_static_group_add(struct interface *ifp, pim_addr group_addr,
+ pim_addr source_addr)
+{
+ struct pim_interface *pim_ifp;
+ struct static_group *stgrp;
+
+ pim_ifp = ifp->info;
+ if (!pim_ifp) {
+ return ferr_cfg_invalid("multicast not enabled on interface %s",
+ ifp->name);
+ }
+
+ if (!pim_ifp->static_group_list) {
+ pim_ifp->static_group_list = list_new();
+ pim_ifp->static_group_list->del =
+ (void (*)(void *))static_group_free;
+ }
+
+ stgrp = static_group_find(pim_ifp->static_group_list, group_addr,
+ source_addr);
+
+ /* This interface has already been configured with this static group
+ */
+ if (stgrp)
+ return ferr_ok();
+
+ (void)static_group_new(ifp, group_addr, source_addr);
+
+ if (PIM_DEBUG_GM_EVENTS) {
+ zlog_debug("%s: Added static group (S,G)=(%pPA,%pPA) on interface %s",
+ __func__, &source_addr, &group_addr, ifp->name);
+ }
+
+ return ferr_ok();
+}
+
+int pim_if_static_group_del(struct interface *ifp, pim_addr group_addr,
+ pim_addr source_addr)
+{
+ struct pim_interface *pim_ifp;
+ struct static_group *stgrp;
+ pim_sgaddr sg;
+
+ pim_ifp = ifp->info;
+ if (!pim_ifp) {
+ zlog_warn("%s: multicast not enabled on interface %s", __func__,
+ ifp->name);
+ return -1;
+ }
+
+ if (!pim_ifp->static_group_list) {
+ zlog_warn("%s: no static groups on interface %s", __func__,
+ ifp->name);
+ return -2;
+ }
+
+ stgrp = static_group_find(pim_ifp->static_group_list, group_addr,
+ source_addr);
+ if (!stgrp) {
+ zlog_warn("%s: could not find static group %pPAs source %pPAs on interface %s",
+ __func__, &group_addr, &source_addr, ifp->name);
+ return -3;
+ }
+
+ memset(&sg, 0, sizeof(sg));
+ sg.src = source_addr;
+ sg.grp = group_addr;
+
+ tib_sg_gm_prune(pim_ifp->pim, sg, ifp, &(stgrp->oilp));
+
+ listnode_delete(pim_ifp->static_group_list, stgrp);
+ static_group_free(stgrp);
+ if (listcount(pim_ifp->static_group_list) < 1) {
+ list_delete(&pim_ifp->static_group_list);
+ pim_ifp->static_group_list = 0;
+ }
+
+ return 0;
+}
+
+static void pim_if_static_group_del_all(struct interface *ifp)
+{
+ struct pim_interface *pim_ifp;
+ struct listnode *node;
+ struct listnode *nextnode;
+ struct static_group *stgrp;
+
+ pim_ifp = ifp->info;
+ if (!pim_ifp) {
+ zlog_warn("%s: multicast not enabled on interface %s", __func__,
+ ifp->name);
+ return;
+ }
+
+ if (!pim_ifp->static_group_list)
+ return;
+
+ for (ALL_LIST_ELEMENTS(pim_ifp->static_group_list, node, nextnode,
+ stgrp))
+ pim_if_static_group_del(ifp, stgrp->group_addr,
+ stgrp->source_addr);
+}
+
/*
RFC 4601
*/
struct list *gm_socket_list; /* list of struct IGMP or MLD sock */
struct list *gm_join_list; /* list of struct IGMP or MLD join */
+ struct list *static_group_list; /* list of struct static group */
struct list *gm_group_list; /* list of struct IGMP or MLD group */
struct hash *gm_group_hash;
int pim_if_gm_join_del(struct interface *ifp, pim_addr group_addr,
pim_addr source_addr);
+ferr_r pim_if_static_group_add(struct interface *ifp, pim_addr group_addr,
+ pim_addr source_addr);
+int pim_if_static_group_del(struct interface *ifp, pim_addr group_addr,
+ pim_addr source_addr);
+
void pim_if_update_could_assert(struct interface *ifp);
void pim_if_assert_on_neighbor_down(struct interface *ifp, pim_addr neigh_addr);
time_t sock_creation;
};
+struct static_group {
+ pim_addr group_addr;
+ pim_addr source_addr;
+ struct channel_oil *oilp;
+};
+
struct gm_sock {
int fd;
struct interface *interface;
DEFINE_MTYPE(PIMD, PIM_CHANNEL_OIL, "PIM SSM (S,G) channel OIL");
DEFINE_MTYPE(PIMD, PIM_INTERFACE, "PIM interface");
DEFINE_MTYPE(PIMD, PIM_IGMP_JOIN, "PIM interface IGMP static join");
+DEFINE_MTYPE(PIMD, PIM_STATIC_GROUP, "PIM interface IGMP static group");
DEFINE_MTYPE(PIMD, PIM_IGMP_SOCKET, "PIM interface IGMP socket");
DEFINE_MTYPE(PIMD, PIM_IGMP_GROUP, "PIM interface IGMP group");
DEFINE_MTYPE(PIMD, PIM_IGMP_GROUP_SOURCE, "PIM interface IGMP source");
DECLARE_MTYPE(PIM_CHANNEL_OIL);
DECLARE_MTYPE(PIM_INTERFACE);
DECLARE_MTYPE(PIM_IGMP_JOIN);
+DECLARE_MTYPE(PIM_STATIC_GROUP);
DECLARE_MTYPE(PIM_IGMP_SOCKET);
DECLARE_MTYPE(PIM_IGMP_GROUP);
DECLARE_MTYPE(PIM_IGMP_GROUP_SOURCE);
.modify = lib_interface_gmp_address_family_robustness_variable_modify,
}
},
+ {
+ .xpath = "/frr-interface:lib/interface/frr-gmp:gmp/address-family/join-group",
+ .cbs = {
+ .create = lib_interface_gmp_address_family_join_group_create,
+ .destroy = lib_interface_gmp_address_family_join_group_destroy,
+ }
+ },
{
.xpath = "/frr-interface:lib/interface/frr-gmp:gmp/address-family/static-group",
.cbs = {
},
}
};
-
struct nb_cb_modify_args *args);
int lib_interface_gmp_address_family_robustness_variable_modify(
struct nb_cb_modify_args *args);
+int lib_interface_gmp_address_family_join_group_create(
+ struct nb_cb_create_args *args);
+int lib_interface_gmp_address_family_join_group_destroy(
+ struct nb_cb_destroy_args *args);
int lib_interface_gmp_address_family_static_group_create(
struct nb_cb_create_args *args);
int lib_interface_gmp_address_family_static_group_destroy(
"./frr-gmp:gmp/address-family[address-family='%s']"
#define FRR_GMP_ENABLE_XPATH \
"%s/frr-gmp:gmp/address-family[address-family='%s']/enable"
-#define FRR_GMP_JOIN_XPATH \
- "./frr-gmp:gmp/address-family[address-family='%s']/" \
+#define FRR_GMP_JOIN_GROUP_XPATH \
+ "./frr-gmp:gmp/address-family[address-family='%s']/" \
+ "join-group[group-addr='%s'][source-addr='%s']"
+#define FRR_GMP_STATIC_GROUP_XPATH \
+ "./frr-gmp:gmp/address-family[address-family='%s']/" \
"static-group[group-addr='%s'][source-addr='%s']"
#endif /* _FRR_PIM_NB_H_ */
}
/*
- * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/static-group
+ * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/join-group
*/
-int lib_interface_gmp_address_family_static_group_create(
+int lib_interface_gmp_address_family_join_group_create(
struct nb_cb_create_args *args)
{
struct interface *ifp;
return NB_OK;
}
-int lib_interface_gmp_address_family_static_group_destroy(
+int lib_interface_gmp_address_family_join_group_destroy(
struct nb_cb_destroy_args *args)
{
struct interface *ifp;
return NB_OK;
}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/static-group
+ */
+int lib_interface_gmp_address_family_static_group_create(
+ struct nb_cb_create_args *args)
+{
+ struct interface *ifp;
+ pim_addr source_addr;
+ pim_addr group_addr;
+ int result;
+ const char *ifp_name;
+ const struct lyd_node *if_dnode;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ if_dnode = yang_dnode_get_parent(args->dnode, "interface");
+ if (!is_pim_interface(if_dnode)) {
+ ifp_name = yang_dnode_get_string(if_dnode, "name");
+ snprintf(args->errmsg, args->errmsg_len,
+ "multicast not enabled on interface %s",
+ ifp_name);
+ return NB_ERR_VALIDATION;
+ }
+
+ yang_dnode_get_pimaddr(&group_addr, args->dnode, "./group-addr");
+#if PIM_IPV == 4
+ if (pim_is_group_224_0_0_0_24(group_addr)) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "Groups within 224.0.0.0/24 are reserved and cannot be joined");
+ return NB_ERR_VALIDATION;
+ }
+#else
+ if (ipv6_mcast_reserved(&group_addr)) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "Groups within ffx2::/16 are reserved and cannot be joined");
+ return NB_ERR_VALIDATION;
+ }
+#endif
+ break;
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ yang_dnode_get_pimaddr(&source_addr, args->dnode,
+ "./source-addr");
+ yang_dnode_get_pimaddr(&group_addr, args->dnode, "./group-addr");
+ result = pim_if_static_group_add(ifp, group_addr, source_addr);
+ if (result) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "Failure adding static group");
+ return NB_ERR_INCONSISTENCY;
+ }
+ }
+ return NB_OK;
+}
+
+int lib_interface_gmp_address_family_static_group_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+ pim_addr source_addr;
+ pim_addr group_addr;
+ int result;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ yang_dnode_get_pimaddr(&source_addr, args->dnode,
+ "./source-addr");
+ yang_dnode_get_pimaddr(&group_addr, args->dnode, "./group-addr");
+ result = pim_if_static_group_del(ifp, group_addr, source_addr);
+
+ if (result) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "%% Failure removing static group %pPAs %pPAs on interface %s: %d",
+ &source_addr, &group_addr, ifp->name, result);
+
+ return NB_ERR_INCONSISTENCY;
+ }
+
+ break;
+ }
+
+ return NB_OK;
+}
++writes;
}
- /* IF ip igmp join */
+ /* IF ip igmp join-group */
if (pim_ifp->gm_join_list) {
struct listnode *node;
struct gm_join *ij;
for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_join_list, node, ij)) {
if (pim_addr_is_any(ij->source_addr))
- vty_out(vty, " ip igmp join %pPAs\n",
+ vty_out(vty, " ip igmp join-group %pPAs\n",
&ij->group_addr);
else
- vty_out(vty, " ip igmp join %pPAs %pPAs\n",
+ vty_out(vty, " ip igmp join-group %pPAs %pPAs\n",
&ij->group_addr, &ij->source_addr);
++writes;
}
}
+ /* IF ip igmp static-group */
+ if (pim_ifp->static_group_list) {
+ struct listnode *node;
+ struct static_group *stgrp;
+ for (ALL_LIST_ELEMENTS_RO(pim_ifp->static_group_list, node,
+ stgrp)) {
+ if (pim_addr_is_any(stgrp->source_addr))
+ vty_out(vty, " ip igmp static-group %pPAs\n",
+ &stgrp->group_addr);
+ else
+ vty_out(vty,
+ " ip igmp static-group %pPAs %pPAs\n",
+ &stgrp->group_addr, &stgrp->source_addr);
+ ++writes;
+ }
+ }
+
return writes;
}
#else
vty_out(vty, " ipv6 mld last-member-query-interval %d\n",
pim_ifp->gm_specific_query_max_response_time_dsec);
- /* IF ipv6 mld join */
+ /* IF ipv6 mld join-group */
if (pim_ifp->gm_join_list) {
struct listnode *node;
struct gm_join *ij;
+
for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_join_list, node, ij)) {
if (pim_addr_is_any(ij->source_addr))
- vty_out(vty, " ipv6 mld join %pPAs\n",
+ vty_out(vty, " ipv6 mld join-group %pPAs\n",
&ij->group_addr);
else
- vty_out(vty, " ipv6 mld join %pPAs %pPAs\n",
+ vty_out(vty,
+ " ipv6 mld join-group %pPAs %pPAs\n",
&ij->group_addr, &ij->source_addr);
++writes;
}
}
+ /* IF ipv6 mld static-group */
+ if (pim_ifp->static_group_list) {
+ struct listnode *node;
+ struct static_group *stgrp;
+
+ for (ALL_LIST_ELEMENTS_RO(pim_ifp->static_group_list, node,
+ stgrp)) {
+ if (pim_addr_is_any(stgrp->source_addr))
+ vty_out(vty, " ipv6 mld static-group %pPAs\n",
+ &stgrp->group_addr);
+ else
+ vty_out(vty,
+ " ipv6 mld static-group %pPAs %pPAs\n",
+ &stgrp->group_addr, &stgrp->source_addr);
+ ++writes;
+ }
+ }
+
return writes;
}
#endif
expected packet loss on a network.";
}
- list static-group {
+ list join-group {
key "group-addr source-addr";
description
- "A static multicast route, (*,G) or (S,G).
+ "A static GMP join, (*,G) or (S,G).
The version of IGMP must be 3 to support (S,G).";
leaf group-addr {
"Multicast source address.";
}
}
+
+ list static-group {
+ key "group-addr source-addr";
+ description
+ "A static multicast group without GMP, (*,G) or (S,G).";
+
+ leaf group-addr {
+ type rt-types:ip-multicast-group-address;
+ description
+ "Multicast group address.";
+ }
+ leaf source-addr {
+ type inet:ip-address;
+ description
+ "Multicast source address.";
+ }
+ }
} // interface-config-attributes
/*