mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-26 08:38:47 +00:00
Merge pull request #16634 from nabahr/autorp
PIM: Implement AutoRP functionality
This commit is contained in:
commit
c0ccf381d4
@ -71,6 +71,31 @@ PIM Routers
|
|||||||
prefix of group ranges covered. This command is vrf aware, to configure for
|
prefix of group ranges covered. This command is vrf aware, to configure for
|
||||||
a vrf, specify the vrf in the router pim block.
|
a vrf, specify the vrf in the router pim block.
|
||||||
|
|
||||||
|
.. clicmd:: no autorp discovery
|
||||||
|
|
||||||
|
In order to use pim, it is necessary to configure a RP for join messages to
|
||||||
|
be sent to. FRR supports learning RP information dynamically via the AutoRP
|
||||||
|
protocol and performs discovery by default. This command will disable the
|
||||||
|
AutoRP discovery protocol.
|
||||||
|
All routers in the pim network must agree on the network RP information, so
|
||||||
|
all routers in the network should have AutoRP either enabled or disabled.
|
||||||
|
This command is vrf aware, to configure for a vrf, specify the vrf in the
|
||||||
|
router pim block.
|
||||||
|
|
||||||
|
.. clicmd:: autorp announce A.B.C.D [A.B.C.D/M | group-list PREFIX_LIST]
|
||||||
|
|
||||||
|
Configure the router to advertise itself as a candidate PIM-SM RP via AutoRP.
|
||||||
|
The supported groups can be defined as a single group range, or multiple
|
||||||
|
group ranges can be defined via a prefix list.
|
||||||
|
|
||||||
|
.. clicmd:: autorp announce {scope (1-255) | interval (1-65535) | holdtime (0-65535)}
|
||||||
|
|
||||||
|
Configure the AutoRP advertise messages. The scope defines the TTL value in the
|
||||||
|
messages to limit the scope, defaults to 31. Interval defines the number of
|
||||||
|
seconds elapsed between advertise messages sent, defaults to 60. Hold time defines
|
||||||
|
how long the AutoRP mapping agent will consider the information valid, setting to
|
||||||
|
0 will disable expiration of the candidate RP information, defaults to 3 * interval.
|
||||||
|
|
||||||
.. clicmd:: rp keep-alive-timer (1-65535)
|
.. clicmd:: rp keep-alive-timer (1-65535)
|
||||||
|
|
||||||
Modify the time out value for a S,G flow from 1-65535 seconds at RP.
|
Modify the time out value for a S,G flow from 1-65535 seconds at RP.
|
||||||
@ -616,6 +641,11 @@ cause great confusion.
|
|||||||
192.168.10.123 239.0.0.0/8 eth2 yes Static ASM
|
192.168.10.123 239.0.0.0/8 eth2 yes Static ASM
|
||||||
192.168.10.123 239.4.0.0/24 eth2 yes Static SSM
|
192.168.10.123 239.4.0.0/24 eth2 yes Static SSM
|
||||||
|
|
||||||
|
.. clicmd:: show ip pim [vrf NAME] autorp [json]
|
||||||
|
|
||||||
|
Display information about AutoRP. Including state of AutoRP Discovery parsing
|
||||||
|
and configured AutoRP candidate RP information.
|
||||||
|
|
||||||
.. clicmd:: show ip pim rpf
|
.. clicmd:: show ip pim rpf
|
||||||
|
|
||||||
Display information about currently being used S,G's and their RPF lookup
|
Display information about currently being used S,G's and their RPF lookup
|
||||||
@ -761,6 +791,10 @@ the config was written out.
|
|||||||
|
|
||||||
This gathers data about events from zebra that come up through the ZAPI.
|
This gathers data about events from zebra that come up through the ZAPI.
|
||||||
|
|
||||||
|
.. clicmd:: debug pim autorp
|
||||||
|
|
||||||
|
This turns on debugging for PIM AutoRP protocol events.
|
||||||
|
|
||||||
PIM Clear Commands
|
PIM Clear Commands
|
||||||
==================
|
==================
|
||||||
Clear commands reset various variables.
|
Clear commands reset various variables.
|
||||||
|
1147
pimd/pim_autorp.c
Normal file
1147
pimd/pim_autorp.c
Normal file
File diff suppressed because it is too large
Load Diff
158
pimd/pim_autorp.h
Normal file
158
pimd/pim_autorp.h
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
/*
|
||||||
|
* pim_autorp.h: PIM Auto RP handling related
|
||||||
|
*
|
||||||
|
* Copyright (C) 20224 ATCorp.
|
||||||
|
* Nathan Bahr
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PIM_AUTORP_H__
|
||||||
|
#define __PIM_AUTORP_H__
|
||||||
|
|
||||||
|
#include <typesafe.h>
|
||||||
|
|
||||||
|
#define AUTORP_VERSION 1
|
||||||
|
#define AUTORP_ANNOUNCEMENT_TYPE 1
|
||||||
|
#define AUTORP_DISCOVERY_TYPE 2
|
||||||
|
#define PIM_VUNKNOWN 0
|
||||||
|
#define PIM_V1 1
|
||||||
|
#define PIM_V2 2
|
||||||
|
#define PIM_V1_2 3
|
||||||
|
|
||||||
|
#define DEFAULT_ANNOUNCE_INTERVAL 60
|
||||||
|
#define DEFAULT_ANNOUNCE_SCOPE 31
|
||||||
|
#define DEFAULT_ANNOUNCE_HOLDTIME -1
|
||||||
|
|
||||||
|
PREDECL_SORTLIST_UNIQ(pim_autorp_rp);
|
||||||
|
|
||||||
|
struct autorp_pkt_grp {
|
||||||
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
|
uint8_t negprefix : 1;
|
||||||
|
uint8_t reserved : 7;
|
||||||
|
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||||
|
uint8_t reserved : 7;
|
||||||
|
uint8_t negprefix : 1;
|
||||||
|
#else
|
||||||
|
#error "Please fix <bits/endian.h>"
|
||||||
|
#endif
|
||||||
|
uint8_t masklen;
|
||||||
|
uint32_t addr;
|
||||||
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
struct autorp_pkt_rp {
|
||||||
|
uint32_t addr;
|
||||||
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
|
uint8_t pimver : 2;
|
||||||
|
uint8_t reserved : 6;
|
||||||
|
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||||
|
uint8_t reserved : 6;
|
||||||
|
uint8_t pimver : 2;
|
||||||
|
#else
|
||||||
|
#error "Please fix <bits/endian.h>"
|
||||||
|
#endif
|
||||||
|
uint8_t grpcnt;
|
||||||
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
struct autorp_pkt_hdr {
|
||||||
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
|
uint8_t type : 4;
|
||||||
|
uint8_t version : 4;
|
||||||
|
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||||
|
uint8_t version : 4;
|
||||||
|
uint8_t type : 4;
|
||||||
|
#else
|
||||||
|
#error "Please fix <bits/endian.h>"
|
||||||
|
#endif
|
||||||
|
uint8_t rpcnt;
|
||||||
|
uint16_t holdtime;
|
||||||
|
uint32_t reserved;
|
||||||
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
#define MIN_AUTORP_PKT_SZ \
|
||||||
|
(sizeof(struct autorp_pkt_hdr) + sizeof(struct autorp_pkt_rp) + \
|
||||||
|
sizeof(struct autorp_pkt_grp))
|
||||||
|
|
||||||
|
struct pim_autorp_rp {
|
||||||
|
struct pim_autorp *autorp;
|
||||||
|
struct in_addr addr;
|
||||||
|
uint16_t holdtime;
|
||||||
|
struct event *hold_timer;
|
||||||
|
struct prefix grp;
|
||||||
|
char grplist[32];
|
||||||
|
struct pim_autorp_rp_item list;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pim_autorp {
|
||||||
|
/* backpointer to pim instance */
|
||||||
|
struct pim_instance *pim;
|
||||||
|
|
||||||
|
/* UDP socket bound to AutoRP port, used for sending and receiving all AutoRP packets */
|
||||||
|
int sock;
|
||||||
|
|
||||||
|
/* Event for reading AutoRP packets */
|
||||||
|
struct event *read_event;
|
||||||
|
|
||||||
|
/* Event for sending announcement packets */
|
||||||
|
struct event *announce_timer;
|
||||||
|
|
||||||
|
/* Event for sending discovery packets*/
|
||||||
|
/* struct event *discovery_timer; */
|
||||||
|
|
||||||
|
/* Flag enabling reading discovery packets */
|
||||||
|
bool do_discovery;
|
||||||
|
|
||||||
|
/* Flag enabling mapping agent (reading announcements and sending discovery)*/
|
||||||
|
/* bool do_mapping; */
|
||||||
|
|
||||||
|
/* List of RP's in received discovery packets */
|
||||||
|
struct pim_autorp_rp_head discovery_rp_list;
|
||||||
|
|
||||||
|
/* List of configured candidate RP's to send in announcement packets */
|
||||||
|
struct pim_autorp_rp_head candidate_rp_list;
|
||||||
|
|
||||||
|
/* List of announced RP's to send in discovery packets */
|
||||||
|
/* struct pim_autorp_rp_head mapping_rp_list; */
|
||||||
|
|
||||||
|
/* Packet parameters for sending announcement packets */
|
||||||
|
uint8_t announce_scope;
|
||||||
|
uint16_t announce_interval;
|
||||||
|
int32_t announce_holdtime;
|
||||||
|
|
||||||
|
/* Pre-built announcement packet, only changes when configured RP's or packet parameters change */
|
||||||
|
uint8_t *annouce_pkt;
|
||||||
|
uint16_t annouce_pkt_sz;
|
||||||
|
|
||||||
|
/* TODO: Packet parameters for sending discovery packets
|
||||||
|
* int discovery_scope;
|
||||||
|
* int discovery_interval;
|
||||||
|
* int discovery_holdtime;
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
#define AUTORP_GRPLEN 6
|
||||||
|
#define AUTORP_RPLEN 6
|
||||||
|
#define AUTORP_HDRLEN 8
|
||||||
|
|
||||||
|
bool pim_autorp_rm_candidate_rp(struct pim_instance *pim, pim_addr rpaddr);
|
||||||
|
void pim_autorp_add_candidate_rp_group(struct pim_instance *pim,
|
||||||
|
pim_addr rpaddr, struct prefix group);
|
||||||
|
bool pim_autorp_rm_candidate_rp_group(struct pim_instance *pim, pim_addr rpaddr,
|
||||||
|
struct prefix group);
|
||||||
|
void pim_autorp_add_candidate_rp_plist(struct pim_instance *pim,
|
||||||
|
pim_addr rpaddr, const char *plist);
|
||||||
|
bool pim_autorp_rm_candidate_rp_plist(struct pim_instance *pim, pim_addr rpaddr,
|
||||||
|
const char *plist);
|
||||||
|
void pim_autorp_announce_scope(struct pim_instance *pim, uint8_t scope);
|
||||||
|
void pim_autorp_announce_interval(struct pim_instance *pim, uint16_t interval);
|
||||||
|
void pim_autorp_announce_holdtime(struct pim_instance *pim, int32_t holdtime);
|
||||||
|
void pim_autorp_add_ifp(struct interface *ifp);
|
||||||
|
void pim_autorp_rm_ifp(struct interface *ifp);
|
||||||
|
void pim_autorp_start_discovery(struct pim_instance *pim);
|
||||||
|
void pim_autorp_stop_discovery(struct pim_instance *pim);
|
||||||
|
void pim_autorp_init(struct pim_instance *pim);
|
||||||
|
void pim_autorp_finish(struct pim_instance *pim);
|
||||||
|
int pim_autorp_config_write(struct pim_instance *pim, struct vty *vty);
|
||||||
|
void pim_autorp_show_autorp(struct vty *vty, struct pim_instance *pim,
|
||||||
|
json_object *json);
|
||||||
|
|
||||||
|
#endif
|
147
pimd/pim_cmd.c
147
pimd/pim_cmd.c
@ -2820,6 +2820,75 @@ DEFPY (show_ip_pim_rp_vrf_all,
|
|||||||
(struct prefix *)group, !!json);
|
(struct prefix *)group, !!json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFPY (show_ip_pim_autorp,
|
||||||
|
show_ip_pim_autorp_cmd,
|
||||||
|
"show ip pim [vrf NAME] autorp [json$json]",
|
||||||
|
SHOW_STR
|
||||||
|
IP_STR
|
||||||
|
PIM_STR
|
||||||
|
VRF_CMD_HELP_STR
|
||||||
|
"PIM AutoRP information\n"
|
||||||
|
JSON_STR)
|
||||||
|
{
|
||||||
|
struct vrf *v;
|
||||||
|
json_object *json_parent = NULL;
|
||||||
|
|
||||||
|
v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
|
||||||
|
if (!v || !v->info) {
|
||||||
|
if (!json)
|
||||||
|
vty_out(vty, "%% Unable to find pim instance\n");
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json)
|
||||||
|
json_parent = json_object_new_object();
|
||||||
|
|
||||||
|
pim_autorp_show_autorp(vty, v->info, json_parent);
|
||||||
|
|
||||||
|
if (json)
|
||||||
|
vty_json(vty, json_parent);
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFPY (show_ip_pim_autorp_vrf_all,
|
||||||
|
show_ip_pim_autorp_vrf_all_cmd,
|
||||||
|
"show ip pim vrf all autorp [json$json]",
|
||||||
|
SHOW_STR
|
||||||
|
IP_STR
|
||||||
|
PIM_STR
|
||||||
|
VRF_CMD_HELP_STR
|
||||||
|
"PIM AutoRP information\n"
|
||||||
|
JSON_STR)
|
||||||
|
{
|
||||||
|
struct vrf *vrf;
|
||||||
|
json_object *json_parent = NULL;
|
||||||
|
json_object *json_vrf = NULL;
|
||||||
|
|
||||||
|
if (json)
|
||||||
|
json_parent = json_object_new_object();
|
||||||
|
|
||||||
|
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
||||||
|
if (vrf->info) {
|
||||||
|
if (!json)
|
||||||
|
vty_out(vty, "VRF: %s\n", vrf->name);
|
||||||
|
else
|
||||||
|
json_vrf = json_object_new_object();
|
||||||
|
|
||||||
|
pim_autorp_show_autorp(vty, vrf->info, json_vrf);
|
||||||
|
|
||||||
|
if (json)
|
||||||
|
json_object_object_add(json_parent, vrf->name,
|
||||||
|
json_vrf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json)
|
||||||
|
vty_json(vty, json_parent);
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
DEFPY (show_ip_pim_rpf,
|
DEFPY (show_ip_pim_rpf,
|
||||||
show_ip_pim_rpf_cmd,
|
show_ip_pim_rpf_cmd,
|
||||||
"show ip pim [vrf NAME] rpf [json$json]",
|
"show ip pim [vrf NAME] rpf [json$json]",
|
||||||
@ -4516,6 +4585,52 @@ DEFPY_ATTR(no_ip_pim_rp_prefix_list,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFPY (pim_autorp_discovery,
|
||||||
|
pim_autorp_discovery_cmd,
|
||||||
|
"[no] autorp discovery",
|
||||||
|
NO_STR
|
||||||
|
"AutoRP\n"
|
||||||
|
"Enable AutoRP discovery\n")
|
||||||
|
{
|
||||||
|
if (no)
|
||||||
|
return pim_process_no_autorp_cmd(vty);
|
||||||
|
else
|
||||||
|
return pim_process_autorp_cmd(vty);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFPY (pim_autorp_announce_rp,
|
||||||
|
pim_autorp_announce_rp_cmd,
|
||||||
|
"[no] autorp announce A.B.C.D$rpaddr ![A.B.C.D/M$grp|group-list PREFIX_LIST$plist]",
|
||||||
|
NO_STR
|
||||||
|
"AutoRP\n"
|
||||||
|
"AutoRP Candidate RP announcement\n"
|
||||||
|
"AutoRP Candidate RP address\n"
|
||||||
|
"Group prefix\n"
|
||||||
|
"Prefix list\n"
|
||||||
|
"List name\n")
|
||||||
|
{
|
||||||
|
return pim_process_autorp_candidate_rp_cmd(vty, no, rpaddr_str, grp,
|
||||||
|
plist);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFPY (pim_autorp_announce_scope_int,
|
||||||
|
pim_autorp_announce_scope_int_cmd,
|
||||||
|
"[no] autorp announce ![{scope (1-255) | interval (1-65535) | holdtime (0-65535)}]",
|
||||||
|
NO_STR
|
||||||
|
"AutoRP\n"
|
||||||
|
"AutoRP Candidate RP announcement\n"
|
||||||
|
"Packet scope (TTL)\n"
|
||||||
|
"TTL value\n"
|
||||||
|
"Announcement interval\n"
|
||||||
|
"Time in seconds\n"
|
||||||
|
"Announcement holdtime\n"
|
||||||
|
"Time in seconds\n")
|
||||||
|
{
|
||||||
|
return pim_process_autorp_announce_scope_int_cmd(vty, no, scope_str,
|
||||||
|
interval_str,
|
||||||
|
holdtime_str);
|
||||||
|
}
|
||||||
|
|
||||||
DEFPY (pim_bsr_candidate_bsr,
|
DEFPY (pim_bsr_candidate_bsr,
|
||||||
pim_bsr_candidate_bsr_cmd,
|
pim_bsr_candidate_bsr_cmd,
|
||||||
"[no] bsr candidate-bsr [{priority (0-255)|source <address A.B.C.D|interface IFNAME|loopback$loopback|any$any>}]",
|
"[no] bsr candidate-bsr [{priority (0-255)|source <address A.B.C.D|interface IFNAME|loopback$loopback|any$any>}]",
|
||||||
@ -6377,6 +6492,29 @@ DEFUN (no_debug_bsm,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN (debug_autorp,
|
||||||
|
debug_autorp_cmd,
|
||||||
|
"debug pim autorp",
|
||||||
|
DEBUG_STR
|
||||||
|
DEBUG_PIM_STR
|
||||||
|
DEBUG_PIM_AUTORP_STR)
|
||||||
|
{
|
||||||
|
PIM_DO_DEBUG_AUTORP;
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (no_debug_autorp,
|
||||||
|
no_debug_autorp_cmd,
|
||||||
|
"no debug pim autorp",
|
||||||
|
NO_STR
|
||||||
|
DEBUG_STR
|
||||||
|
DEBUG_PIM_STR
|
||||||
|
DEBUG_PIM_AUTORP_STR)
|
||||||
|
{
|
||||||
|
PIM_DONT_DEBUG_AUTORP;
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DEFUN_NOSH (show_debugging_pim,
|
DEFUN_NOSH (show_debugging_pim,
|
||||||
show_debugging_pim_cmd,
|
show_debugging_pim_cmd,
|
||||||
@ -8714,6 +8852,9 @@ void pim_cmd_init(void)
|
|||||||
install_element(PIM_NODE, &no_pim_rp_cmd);
|
install_element(PIM_NODE, &no_pim_rp_cmd);
|
||||||
install_element(PIM_NODE, &pim_rp_prefix_list_cmd);
|
install_element(PIM_NODE, &pim_rp_prefix_list_cmd);
|
||||||
install_element(PIM_NODE, &no_pim_rp_prefix_list_cmd);
|
install_element(PIM_NODE, &no_pim_rp_prefix_list_cmd);
|
||||||
|
install_element(PIM_NODE, &pim_autorp_discovery_cmd);
|
||||||
|
install_element(PIM_NODE, &pim_autorp_announce_rp_cmd);
|
||||||
|
install_element(PIM_NODE, &pim_autorp_announce_scope_int_cmd);
|
||||||
install_element(PIM_NODE, &no_pim_ssm_prefix_list_cmd);
|
install_element(PIM_NODE, &no_pim_ssm_prefix_list_cmd);
|
||||||
install_element(PIM_NODE, &no_pim_ssm_prefix_list_name_cmd);
|
install_element(PIM_NODE, &no_pim_ssm_prefix_list_name_cmd);
|
||||||
install_element(PIM_NODE, &pim_ssm_prefix_list_cmd);
|
install_element(PIM_NODE, &pim_ssm_prefix_list_cmd);
|
||||||
@ -8868,6 +9009,8 @@ void pim_cmd_init(void)
|
|||||||
install_element(VIEW_NODE, &show_ip_pim_upstream_rpf_cmd);
|
install_element(VIEW_NODE, &show_ip_pim_upstream_rpf_cmd);
|
||||||
install_element(VIEW_NODE, &show_ip_pim_rp_cmd);
|
install_element(VIEW_NODE, &show_ip_pim_rp_cmd);
|
||||||
install_element(VIEW_NODE, &show_ip_pim_rp_vrf_all_cmd);
|
install_element(VIEW_NODE, &show_ip_pim_rp_vrf_all_cmd);
|
||||||
|
install_element(VIEW_NODE, &show_ip_pim_autorp_cmd);
|
||||||
|
install_element(VIEW_NODE, &show_ip_pim_autorp_vrf_all_cmd);
|
||||||
install_element(VIEW_NODE, &show_ip_pim_bsr_cmd);
|
install_element(VIEW_NODE, &show_ip_pim_bsr_cmd);
|
||||||
install_element(VIEW_NODE, &show_ip_multicast_cmd);
|
install_element(VIEW_NODE, &show_ip_multicast_cmd);
|
||||||
install_element(VIEW_NODE, &show_ip_multicast_vrf_all_cmd);
|
install_element(VIEW_NODE, &show_ip_multicast_vrf_all_cmd);
|
||||||
@ -8975,6 +9118,8 @@ void pim_cmd_init(void)
|
|||||||
install_element(CONFIG_NODE, &debug_pim_trace_detail_cmd);
|
install_element(CONFIG_NODE, &debug_pim_trace_detail_cmd);
|
||||||
install_element(ENABLE_NODE, &debug_ssmpingd_cmd);
|
install_element(ENABLE_NODE, &debug_ssmpingd_cmd);
|
||||||
install_element(CONFIG_NODE, &debug_ssmpingd_cmd);
|
install_element(CONFIG_NODE, &debug_ssmpingd_cmd);
|
||||||
|
install_element(ENABLE_NODE, &debug_autorp_cmd);
|
||||||
|
install_element(ENABLE_NODE, &no_debug_autorp_cmd);
|
||||||
install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd);
|
install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd);
|
||||||
install_element(CONFIG_NODE, &no_debug_ssmpingd_cmd);
|
install_element(CONFIG_NODE, &no_debug_ssmpingd_cmd);
|
||||||
install_element(ENABLE_NODE, &debug_pim_zebra_cmd);
|
install_element(ENABLE_NODE, &debug_pim_zebra_cmd);
|
||||||
@ -9007,6 +9152,8 @@ void pim_cmd_init(void)
|
|||||||
install_element(CONFIG_NODE, &debug_bsm_cmd);
|
install_element(CONFIG_NODE, &debug_bsm_cmd);
|
||||||
install_element(ENABLE_NODE, &no_debug_bsm_cmd);
|
install_element(ENABLE_NODE, &no_debug_bsm_cmd);
|
||||||
install_element(CONFIG_NODE, &no_debug_bsm_cmd);
|
install_element(CONFIG_NODE, &no_debug_bsm_cmd);
|
||||||
|
install_element(CONFIG_NODE, &debug_autorp_cmd);
|
||||||
|
install_element(CONFIG_NODE, &no_debug_autorp_cmd);
|
||||||
|
|
||||||
install_element(CONFIG_NODE, &ip_igmp_group_watermark_cmd);
|
install_element(CONFIG_NODE, &ip_igmp_group_watermark_cmd);
|
||||||
install_element(VRF_NODE, &ip_igmp_group_watermark_cmd);
|
install_element(VRF_NODE, &ip_igmp_group_watermark_cmd);
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
#define DEBUG_MSDP_PACKETS_STR "MSDP protocol packets\n"
|
#define DEBUG_MSDP_PACKETS_STR "MSDP protocol packets\n"
|
||||||
#define DEBUG_MTRACE_STR "Mtrace protocol activity\n"
|
#define DEBUG_MTRACE_STR "Mtrace protocol activity\n"
|
||||||
#define DEBUG_PIM_BSM_STR "BSR message processing activity\n"
|
#define DEBUG_PIM_BSM_STR "BSR message processing activity\n"
|
||||||
|
#define DEBUG_PIM_AUTORP_STR "AutoRP message processing activity\n"
|
||||||
|
|
||||||
|
|
||||||
void pim_cmd_init(void);
|
void pim_cmd_init(void);
|
||||||
|
@ -606,6 +606,165 @@ int pim_process_no_rp_plist_cmd(struct vty *vty, const char *rp_str,
|
|||||||
return nb_cli_apply_changes(vty, NULL);
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int pim_process_autorp_cmd(struct vty *vty)
|
||||||
|
{
|
||||||
|
char xpath[XPATH_MAXLEN];
|
||||||
|
|
||||||
|
snprintf(xpath, sizeof(xpath), "%s/%s", FRR_PIM_AUTORP_XPATH,
|
||||||
|
"discovery-enabled");
|
||||||
|
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, "true");
|
||||||
|
|
||||||
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pim_process_no_autorp_cmd(struct vty *vty)
|
||||||
|
{
|
||||||
|
char xpath[XPATH_MAXLEN];
|
||||||
|
|
||||||
|
snprintf(xpath, sizeof(xpath), "%s/%s", FRR_PIM_AUTORP_XPATH,
|
||||||
|
"discovery-enabled");
|
||||||
|
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
|
||||||
|
|
||||||
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pim_process_autorp_candidate_rp_cmd(struct vty *vty, bool no,
|
||||||
|
const char *rpaddr_str,
|
||||||
|
const struct prefix_ipv4 *grp,
|
||||||
|
const char *plist)
|
||||||
|
{
|
||||||
|
char xpath[XPATH_MAXLEN];
|
||||||
|
char grpstr[64];
|
||||||
|
|
||||||
|
if (no) {
|
||||||
|
if (!is_default_prefix((const struct prefix *)grp) || plist) {
|
||||||
|
/* If any single values are set, only destroy those */
|
||||||
|
if (!is_default_prefix((const struct prefix *)grp)) {
|
||||||
|
snprintfrr(xpath, sizeof(xpath),
|
||||||
|
"%s/candidate-rp-list[rp-address='%s']/group",
|
||||||
|
FRR_PIM_AUTORP_XPATH, rpaddr_str);
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
if (plist) {
|
||||||
|
snprintfrr(xpath, sizeof(xpath),
|
||||||
|
"%s/candidate-rp-list[rp-address='%s']/prefix-list",
|
||||||
|
FRR_PIM_AUTORP_XPATH, rpaddr_str);
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* No values set, remove the entire RP */
|
||||||
|
snprintfrr(xpath, sizeof(xpath),
|
||||||
|
"%s/candidate-rp-list[rp-address='%s']",
|
||||||
|
FRR_PIM_AUTORP_XPATH, rpaddr_str);
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!is_default_prefix((const struct prefix *)grp) || plist) {
|
||||||
|
snprintfrr(xpath, sizeof(xpath),
|
||||||
|
"%s/candidate-rp-list[rp-address='%s']",
|
||||||
|
FRR_PIM_AUTORP_XPATH, rpaddr_str);
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
|
||||||
|
if (!is_default_prefix((const struct prefix *)grp)) {
|
||||||
|
snprintfrr(xpath, sizeof(xpath),
|
||||||
|
"%s/candidate-rp-list[rp-address='%s']/group",
|
||||||
|
FRR_PIM_AUTORP_XPATH, rpaddr_str);
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
|
||||||
|
prefix2str(grp, grpstr,
|
||||||
|
sizeof(grpstr)));
|
||||||
|
}
|
||||||
|
if (plist) {
|
||||||
|
snprintfrr(xpath, sizeof(xpath),
|
||||||
|
"%s/candidate-rp-list[rp-address='%s']/prefix-list",
|
||||||
|
FRR_PIM_AUTORP_XPATH, rpaddr_str);
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
|
||||||
|
plist);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pim_process_autorp_announce_scope_int_cmd(struct vty *vty, bool no,
|
||||||
|
const char *scope,
|
||||||
|
const char *interval,
|
||||||
|
const char *holdtime)
|
||||||
|
{
|
||||||
|
char xpath[XPATH_MAXLEN];
|
||||||
|
|
||||||
|
if (no) {
|
||||||
|
if (scope || interval || holdtime) {
|
||||||
|
/* If any single values are set, only destroy those */
|
||||||
|
if (scope) {
|
||||||
|
snprintfrr(xpath, sizeof(xpath), "%s/%s",
|
||||||
|
FRR_PIM_AUTORP_XPATH,
|
||||||
|
"announce-scope");
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
if (interval) {
|
||||||
|
snprintfrr(xpath, sizeof(xpath), "%s/%s",
|
||||||
|
FRR_PIM_AUTORP_XPATH,
|
||||||
|
"announce-interval");
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
if (holdtime) {
|
||||||
|
snprintfrr(xpath, sizeof(xpath), "%s/%s",
|
||||||
|
FRR_PIM_AUTORP_XPATH,
|
||||||
|
"announce-holdtime");
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* No values set, remove all */
|
||||||
|
snprintfrr(xpath, sizeof(xpath), "%s/%s",
|
||||||
|
FRR_PIM_AUTORP_XPATH, "announce-scope");
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
|
||||||
|
snprintfrr(xpath, sizeof(xpath), "%s/%s",
|
||||||
|
FRR_PIM_AUTORP_XPATH, "announce-interval");
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
|
||||||
|
snprintfrr(xpath, sizeof(xpath), "%s/%s",
|
||||||
|
FRR_PIM_AUTORP_XPATH, "announce-holdtime");
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (scope || interval || holdtime) {
|
||||||
|
if (scope) {
|
||||||
|
snprintfrr(xpath, sizeof(xpath), "%s/%s",
|
||||||
|
FRR_PIM_AUTORP_XPATH,
|
||||||
|
"announce-scope");
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
|
||||||
|
scope);
|
||||||
|
}
|
||||||
|
if (interval) {
|
||||||
|
snprintfrr(xpath, sizeof(xpath), "%s/%s",
|
||||||
|
FRR_PIM_AUTORP_XPATH,
|
||||||
|
"announce-interval");
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
|
||||||
|
interval);
|
||||||
|
}
|
||||||
|
if (holdtime) {
|
||||||
|
snprintfrr(xpath, sizeof(xpath), "%s/%s",
|
||||||
|
FRR_PIM_AUTORP_XPATH,
|
||||||
|
"announce-holdtime");
|
||||||
|
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
|
||||||
|
holdtime);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
bool pim_sgaddr_match(pim_sgaddr item, pim_sgaddr match)
|
bool pim_sgaddr_match(pim_sgaddr item, pim_sgaddr match)
|
||||||
{
|
{
|
||||||
return (pim_addr_is_any(match.grp) ||
|
return (pim_addr_is_any(match.grp) ||
|
||||||
|
@ -35,7 +35,16 @@ int pim_process_rp_plist_cmd(struct vty *vty, const char *rp_str,
|
|||||||
const char *prefix_list);
|
const char *prefix_list);
|
||||||
int pim_process_no_rp_plist_cmd(struct vty *vty, const char *rp_str,
|
int pim_process_no_rp_plist_cmd(struct vty *vty, const char *rp_str,
|
||||||
const char *prefix_list);
|
const char *prefix_list);
|
||||||
|
int pim_process_autorp_cmd(struct vty *vty);
|
||||||
|
int pim_process_no_autorp_cmd(struct vty *vty);
|
||||||
|
int pim_process_autorp_candidate_rp_cmd(struct vty *vty, bool no,
|
||||||
|
const char *rpaddr_str,
|
||||||
|
const struct prefix_ipv4 *grp,
|
||||||
|
const char *plist);
|
||||||
|
int pim_process_autorp_announce_scope_int_cmd(struct vty *vty, bool no,
|
||||||
|
const char *scope,
|
||||||
|
const char *interval,
|
||||||
|
const char *holdtime);
|
||||||
int pim_process_ip_pim_cmd(struct vty *vty);
|
int pim_process_ip_pim_cmd(struct vty *vty);
|
||||||
int pim_process_no_ip_pim_cmd(struct vty *vty);
|
int pim_process_no_ip_pim_cmd(struct vty *vty);
|
||||||
int pim_process_ip_pim_passive_cmd(struct vty *vty, bool enable);
|
int pim_process_ip_pim_passive_cmd(struct vty *vty, bool enable);
|
||||||
|
@ -1914,6 +1914,12 @@ static int pim_ifp_up(struct interface *ifp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
if (pim->autorp && pim->autorp->do_discovery && pim_ifp &&
|
||||||
|
pim_ifp->pim_enable)
|
||||||
|
pim_autorp_add_ifp(ifp);
|
||||||
|
#endif
|
||||||
|
|
||||||
pim_cand_addrs_changed();
|
pim_cand_addrs_changed();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1951,6 +1957,10 @@ static int pim_ifp_down(struct interface *ifp)
|
|||||||
pim_ifstat_reset(ifp);
|
pim_ifstat_reset(ifp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
pim_autorp_rm_ifp(ifp);
|
||||||
|
#endif
|
||||||
|
|
||||||
pim_cand_addrs_changed();
|
pim_cand_addrs_changed();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2023,6 +2033,11 @@ void pim_pim_interface_delete(struct interface *ifp)
|
|||||||
if (!pim_ifp)
|
if (!pim_ifp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
if (pim_ifp->pim_enable)
|
||||||
|
pim_autorp_rm_ifp(ifp);
|
||||||
|
#endif
|
||||||
|
|
||||||
pim_ifp->pim_enable = false;
|
pim_ifp->pim_enable = false;
|
||||||
|
|
||||||
pim_if_membership_clear(ifp);
|
pim_if_membership_clear(ifp);
|
||||||
|
@ -57,6 +57,10 @@ static void pim_instance_terminate(struct pim_instance *pim)
|
|||||||
|
|
||||||
pim_mroute_socket_disable(pim);
|
pim_mroute_socket_disable(pim);
|
||||||
|
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
pim_autorp_finish(pim);
|
||||||
|
#endif
|
||||||
|
|
||||||
XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
|
XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
|
||||||
XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
|
XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
|
||||||
|
|
||||||
@ -125,6 +129,10 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf)
|
|||||||
pim->msdp.keep_alive = PIM_MSDP_PEER_KA_TIME;
|
pim->msdp.keep_alive = PIM_MSDP_PEER_KA_TIME;
|
||||||
pim->msdp.connection_retry = PIM_MSDP_PEER_CONNECT_RETRY_TIME;
|
pim->msdp.connection_retry = PIM_MSDP_PEER_CONNECT_RETRY_TIME;
|
||||||
|
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
pim_autorp_init(pim);
|
||||||
|
#endif
|
||||||
|
|
||||||
return pim;
|
return pim;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "pim_oil.h"
|
#include "pim_oil.h"
|
||||||
#include "pim_upstream.h"
|
#include "pim_upstream.h"
|
||||||
#include "pim_mroute.h"
|
#include "pim_mroute.h"
|
||||||
|
#include "pim_autorp.h"
|
||||||
|
|
||||||
enum pim_spt_switchover {
|
enum pim_spt_switchover {
|
||||||
PIM_SPT_IMMEDIATE,
|
PIM_SPT_IMMEDIATE,
|
||||||
@ -152,6 +153,8 @@ struct pim_instance {
|
|||||||
struct pim_msdp msdp;
|
struct pim_msdp msdp;
|
||||||
struct pim_vxlan_instance vxlan;
|
struct pim_vxlan_instance vxlan;
|
||||||
|
|
||||||
|
struct pim_autorp *autorp;
|
||||||
|
|
||||||
struct list *ssmpingd_list;
|
struct list *ssmpingd_list;
|
||||||
pim_addr ssmpingd_group_addr;
|
pim_addr ssmpingd_group_addr;
|
||||||
|
|
||||||
|
@ -379,6 +379,55 @@ const struct frr_yang_module_info frr_pim_rp_info = {
|
|||||||
.destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_destroy,
|
.destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_destroy,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/discovery-enabled",
|
||||||
|
.cbs = {
|
||||||
|
.modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_discovery_enabled_modify,
|
||||||
|
.destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_discovery_enabled_destroy,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/announce-scope",
|
||||||
|
.cbs = {
|
||||||
|
.modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_scope_modify,
|
||||||
|
.destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_scope_destroy,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/announce-interval",
|
||||||
|
.cbs = {
|
||||||
|
.modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_interval_modify,
|
||||||
|
.destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_interval_destroy,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/announce-holdtime",
|
||||||
|
.cbs = {
|
||||||
|
.modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_holdtime_modify,
|
||||||
|
.destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_holdtime_destroy,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/candidate-rp-list",
|
||||||
|
.cbs = {
|
||||||
|
.create = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_create,
|
||||||
|
.destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_destroy,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/candidate-rp-list/group",
|
||||||
|
.cbs = {
|
||||||
|
.modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_group_modify,
|
||||||
|
.destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_group_destroy,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/candidate-rp-list/prefix-list",
|
||||||
|
.cbs = {
|
||||||
|
.modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_prefix_list_modify,
|
||||||
|
.destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_prefix_list_destroy,
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.xpath = NULL,
|
.xpath = NULL,
|
||||||
},
|
},
|
||||||
|
@ -159,6 +159,34 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp
|
|||||||
struct nb_cb_modify_args *args);
|
struct nb_cb_modify_args *args);
|
||||||
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_destroy(
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_destroy(
|
||||||
struct nb_cb_destroy_args *args);
|
struct nb_cb_destroy_args *args);
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_discovery_enabled_modify(
|
||||||
|
struct nb_cb_modify_args *args);
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_discovery_enabled_destroy(
|
||||||
|
struct nb_cb_destroy_args *args);
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_scope_modify(
|
||||||
|
struct nb_cb_modify_args *args);
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_scope_destroy(
|
||||||
|
struct nb_cb_destroy_args *args);
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_interval_modify(
|
||||||
|
struct nb_cb_modify_args *args);
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_interval_destroy(
|
||||||
|
struct nb_cb_destroy_args *args);
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_holdtime_modify(
|
||||||
|
struct nb_cb_modify_args *args);
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_holdtime_destroy(
|
||||||
|
struct nb_cb_destroy_args *args);
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_create(
|
||||||
|
struct nb_cb_create_args *args);
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_destroy(
|
||||||
|
struct nb_cb_destroy_args *args);
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_group_modify(
|
||||||
|
struct nb_cb_modify_args *args);
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_group_destroy(
|
||||||
|
struct nb_cb_destroy_args *args);
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_prefix_list_modify(
|
||||||
|
struct nb_cb_modify_args *args);
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_prefix_list_destroy(
|
||||||
|
struct nb_cb_destroy_args *args);
|
||||||
|
|
||||||
/* frr-cand-bsr */
|
/* frr-cand-bsr */
|
||||||
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_bsr_create(
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_bsr_create(
|
||||||
@ -258,6 +286,7 @@ int routing_control_plane_protocols_name_validate(
|
|||||||
"mroute[source-addr='%s'][group-addr='%s']"
|
"mroute[source-addr='%s'][group-addr='%s']"
|
||||||
#define FRR_PIM_STATIC_RP_XPATH \
|
#define FRR_PIM_STATIC_RP_XPATH \
|
||||||
"frr-pim-rp:rp/static-rp/rp-list[rp-address='%s']"
|
"frr-pim-rp:rp/static-rp/rp-list[rp-address='%s']"
|
||||||
|
#define FRR_PIM_AUTORP_XPATH "./frr-pim-rp:rp/auto-rp"
|
||||||
#define FRR_GMP_INTERFACE_XPATH \
|
#define FRR_GMP_INTERFACE_XPATH \
|
||||||
"./frr-gmp:gmp/address-family[address-family='%s']"
|
"./frr-gmp:gmp/address-family[address-family='%s']"
|
||||||
#define FRR_GMP_ENABLE_XPATH \
|
#define FRR_GMP_ENABLE_XPATH \
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "lib_errors.h"
|
#include "lib_errors.h"
|
||||||
#include "pim_util.h"
|
#include "pim_util.h"
|
||||||
#include "pim6_mld.h"
|
#include "pim6_mld.h"
|
||||||
|
#include "pim_autorp.h"
|
||||||
#include "pim_igmp.h"
|
#include "pim_igmp.h"
|
||||||
|
|
||||||
#if PIM_IPV == 6
|
#if PIM_IPV == 6
|
||||||
@ -147,6 +148,11 @@ static int pim_cmd_interface_add(struct interface *ifp)
|
|||||||
pim_if_membership_refresh(ifp);
|
pim_if_membership_refresh(ifp);
|
||||||
|
|
||||||
pim_if_create_pimreg(pim_ifp->pim);
|
pim_if_create_pimreg(pim_ifp->pim);
|
||||||
|
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
pim_autorp_add_ifp(ifp);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2680,6 +2686,365 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp
|
|||||||
return NB_OK;
|
return NB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/discovery-enabled
|
||||||
|
*/
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_discovery_enabled_modify(
|
||||||
|
struct nb_cb_modify_args *args)
|
||||||
|
{
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
struct vrf *vrf;
|
||||||
|
struct pim_instance *pim;
|
||||||
|
bool enabled;
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
pim = vrf->info;
|
||||||
|
enabled = yang_dnode_get_bool(args->dnode, NULL);
|
||||||
|
if (enabled)
|
||||||
|
pim_autorp_start_discovery(pim);
|
||||||
|
else
|
||||||
|
pim_autorp_stop_discovery(pim);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_discovery_enabled_destroy(
|
||||||
|
struct nb_cb_destroy_args *args)
|
||||||
|
{
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
struct vrf *vrf;
|
||||||
|
struct pim_instance *pim;
|
||||||
|
bool enabled;
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
pim = vrf->info;
|
||||||
|
enabled = yang_dnode_get_bool(args->dnode, NULL);
|
||||||
|
/* Run AutoRP discovery by default */
|
||||||
|
if (!enabled)
|
||||||
|
pim_autorp_start_discovery(pim);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/announce-scope
|
||||||
|
*/
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_scope_modify(
|
||||||
|
struct nb_cb_modify_args *args)
|
||||||
|
{
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
struct vrf *vrf;
|
||||||
|
struct pim_instance *pim;
|
||||||
|
uint8_t scope;
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
pim = vrf->info;
|
||||||
|
scope = yang_dnode_get_uint8(args->dnode, NULL);
|
||||||
|
pim_autorp_announce_scope(pim, scope);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_scope_destroy(
|
||||||
|
struct nb_cb_destroy_args *args)
|
||||||
|
{
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
struct vrf *vrf;
|
||||||
|
struct pim_instance *pim;
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
pim = vrf->info;
|
||||||
|
pim_autorp_announce_scope(pim, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/announce-interval
|
||||||
|
*/
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_interval_modify(
|
||||||
|
struct nb_cb_modify_args *args)
|
||||||
|
{
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
struct vrf *vrf;
|
||||||
|
struct pim_instance *pim;
|
||||||
|
uint16_t interval;
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
pim = vrf->info;
|
||||||
|
interval = yang_dnode_get_uint16(args->dnode, NULL);
|
||||||
|
pim_autorp_announce_interval(pim, interval);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_interval_destroy(
|
||||||
|
struct nb_cb_destroy_args *args)
|
||||||
|
{
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
struct vrf *vrf;
|
||||||
|
struct pim_instance *pim;
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
pim = vrf->info;
|
||||||
|
pim_autorp_announce_interval(pim, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/announce-holdtime
|
||||||
|
*/
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_holdtime_modify(
|
||||||
|
struct nb_cb_modify_args *args)
|
||||||
|
{
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
struct vrf *vrf;
|
||||||
|
struct pim_instance *pim;
|
||||||
|
uint16_t holdtime;
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
pim = vrf->info;
|
||||||
|
holdtime = yang_dnode_get_uint16(args->dnode, NULL);
|
||||||
|
pim_autorp_announce_holdtime(pim, holdtime);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_holdtime_destroy(
|
||||||
|
struct nb_cb_destroy_args *args)
|
||||||
|
{
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
struct vrf *vrf;
|
||||||
|
struct pim_instance *pim;
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
pim = vrf->info;
|
||||||
|
/* 0 is a valid value, so -1 indicates deleting (go back to default) */
|
||||||
|
pim_autorp_announce_holdtime(pim, -1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/candidate-rp-list
|
||||||
|
*/
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_create(
|
||||||
|
struct nb_cb_create_args *args)
|
||||||
|
{
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_destroy(
|
||||||
|
struct nb_cb_destroy_args *args)
|
||||||
|
{
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
struct vrf *vrf;
|
||||||
|
struct pim_instance *pim;
|
||||||
|
pim_addr rp_addr;
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
pim = vrf->info;
|
||||||
|
yang_dnode_get_pimaddr(&rp_addr, args->dnode, "rp-address");
|
||||||
|
if (!pim_autorp_rm_candidate_rp(pim, rp_addr))
|
||||||
|
return NB_ERR_INCONSISTENCY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/candidate-rp-list/group
|
||||||
|
*/
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_group_modify(
|
||||||
|
struct nb_cb_modify_args *args)
|
||||||
|
{
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
struct vrf *vrf;
|
||||||
|
struct pim_instance *pim;
|
||||||
|
struct prefix group;
|
||||||
|
pim_addr rp_addr;
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
pim = vrf->info;
|
||||||
|
yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
|
||||||
|
yang_dnode_get_prefix(&group, args->dnode, NULL);
|
||||||
|
apply_mask(&group);
|
||||||
|
pim_autorp_add_candidate_rp_group(pim, rp_addr, group);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_group_destroy(
|
||||||
|
struct nb_cb_destroy_args *args)
|
||||||
|
{
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
struct vrf *vrf;
|
||||||
|
struct pim_instance *pim;
|
||||||
|
struct prefix group;
|
||||||
|
pim_addr rp_addr;
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
pim = vrf->info;
|
||||||
|
yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
|
||||||
|
yang_dnode_get_prefix(&group, args->dnode, NULL);
|
||||||
|
apply_mask(&group);
|
||||||
|
if (!pim_autorp_rm_candidate_rp_group(pim, rp_addr, group))
|
||||||
|
return NB_ERR_INCONSISTENCY;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/candidate-rp-list/prefix-list
|
||||||
|
*/
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_prefix_list_modify(
|
||||||
|
struct nb_cb_modify_args *args)
|
||||||
|
{
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
struct vrf *vrf;
|
||||||
|
struct pim_instance *pim;
|
||||||
|
pim_addr rp_addr;
|
||||||
|
const char *plist;
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
pim = vrf->info;
|
||||||
|
plist = yang_dnode_get_string(args->dnode, NULL);
|
||||||
|
yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
|
||||||
|
pim_autorp_add_candidate_rp_plist(pim, rp_addr, plist);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_prefix_list_destroy(
|
||||||
|
struct nb_cb_destroy_args *args)
|
||||||
|
{
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
struct vrf *vrf;
|
||||||
|
struct pim_instance *pim;
|
||||||
|
pim_addr rp_addr;
|
||||||
|
const char *plist;
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
pim = vrf->info;
|
||||||
|
yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
|
||||||
|
plist = yang_dnode_get_string(args->dnode, NULL);
|
||||||
|
if (!pim_autorp_rm_candidate_rp_plist(pim, rp_addr, plist))
|
||||||
|
return NB_ERR_INCONSISTENCY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static void yang_addrsel(struct cand_addrsel *addrsel,
|
static void yang_addrsel(struct cand_addrsel *addrsel,
|
||||||
const struct lyd_node *node)
|
const struct lyd_node *node)
|
||||||
{
|
{
|
||||||
|
@ -1140,7 +1140,8 @@ int pim_rp_config_write(struct pim_instance *pim, struct vty *vty)
|
|||||||
if (pim_rpf_addr_is_inaddr_any(&rp_info->rp))
|
if (pim_rpf_addr_is_inaddr_any(&rp_info->rp))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (rp_info->rp_src == RP_SRC_BSR)
|
if (rp_info->rp_src != RP_SRC_NONE &&
|
||||||
|
rp_info->rp_src != RP_SRC_STATIC)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rp_addr = rp_info->rp.rpf_addr;
|
rp_addr = rp_info->rp.rpf_addr;
|
||||||
@ -1200,6 +1201,8 @@ void pim_rp_show_information(struct pim_instance *pim, struct prefix *range,
|
|||||||
strlcpy(source, "Static", sizeof(source));
|
strlcpy(source, "Static", sizeof(source));
|
||||||
else if (rp_info->rp_src == RP_SRC_BSR)
|
else if (rp_info->rp_src == RP_SRC_BSR)
|
||||||
strlcpy(source, "BSR", sizeof(source));
|
strlcpy(source, "BSR", sizeof(source));
|
||||||
|
else if (rp_info->rp_src == RP_SRC_AUTORP)
|
||||||
|
strlcpy(source, "AutoRP", sizeof(source));
|
||||||
else
|
else
|
||||||
strlcpy(source, "None", sizeof(source));
|
strlcpy(source, "None", sizeof(source));
|
||||||
if (json) {
|
if (json) {
|
||||||
|
@ -16,11 +16,7 @@
|
|||||||
|
|
||||||
struct pim_interface;
|
struct pim_interface;
|
||||||
|
|
||||||
enum rp_source {
|
enum rp_source { RP_SRC_NONE = 0, RP_SRC_STATIC, RP_SRC_BSR, RP_SRC_AUTORP };
|
||||||
RP_SRC_NONE = 0,
|
|
||||||
RP_SRC_STATIC,
|
|
||||||
RP_SRC_BSR
|
|
||||||
};
|
|
||||||
|
|
||||||
struct rp_info {
|
struct rp_info {
|
||||||
struct prefix group;
|
struct prefix group;
|
||||||
|
@ -292,6 +292,36 @@ int pim_socket_join(int fd, pim_addr group, pim_addr ifaddr, ifindex_t ifindex,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int pim_socket_leave(int fd, pim_addr group, pim_addr ifaddr, ifindex_t ifindex,
|
||||||
|
struct pim_interface *pim_ifp)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
ret = setsockopt_ipv4_multicast(fd, IP_DROP_MEMBERSHIP, ifaddr,
|
||||||
|
group.s_addr, ifindex);
|
||||||
|
#else
|
||||||
|
struct ipv6_mreq opt;
|
||||||
|
|
||||||
|
memcpy(&opt.ipv6mr_multiaddr, &group, 16);
|
||||||
|
opt.ipv6mr_interface = ifindex;
|
||||||
|
ret = setsockopt(fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &opt, sizeof(opt));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
flog_err(EC_LIB_SOCKET,
|
||||||
|
"Failure socket leaving fd=%d group %pPAs on interface address %pPAs: %m",
|
||||||
|
fd, &group, &ifaddr);
|
||||||
|
pim_ifp->igmp_ifstat_joins_failed++;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PIM_DEBUG_TRACE)
|
||||||
|
zlog_debug("Socket fd=%d left group %pPAs on interface address %pPAs",
|
||||||
|
fd, &group, &ifaddr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#if PIM_IPV == 4
|
#if PIM_IPV == 4
|
||||||
static void cmsg_getdstaddr(struct msghdr *mh, struct sockaddr_storage *dst,
|
static void cmsg_getdstaddr(struct msghdr *mh, struct sockaddr_storage *dst,
|
||||||
ifindex_t *ifindex)
|
ifindex_t *ifindex)
|
||||||
|
@ -32,6 +32,8 @@ int pim_socket_mcast(int protocol, pim_addr ifaddr, struct interface *ifp,
|
|||||||
uint8_t loop);
|
uint8_t loop);
|
||||||
int pim_socket_join(int fd, pim_addr group, pim_addr ifaddr, ifindex_t ifindex,
|
int pim_socket_join(int fd, pim_addr group, pim_addr ifaddr, ifindex_t ifindex,
|
||||||
struct pim_interface *pim_ifp);
|
struct pim_interface *pim_ifp);
|
||||||
|
int pim_socket_leave(int fd, pim_addr group, pim_addr ifaddr, ifindex_t ifindex,
|
||||||
|
struct pim_interface *pim_ifp);
|
||||||
int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len,
|
int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len,
|
||||||
struct sockaddr_storage *from, socklen_t *fromlen,
|
struct sockaddr_storage *from, socklen_t *fromlen,
|
||||||
struct sockaddr_storage *to, socklen_t *tolen,
|
struct sockaddr_storage *to, socklen_t *tolen,
|
||||||
|
@ -165,6 +165,11 @@ int pim_debug_config_write(struct vty *vty)
|
|||||||
++writes;
|
++writes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PIM_DEBUG_AUTORP) {
|
||||||
|
vty_out(vty, "debug pim autorp\n");
|
||||||
|
++writes;
|
||||||
|
}
|
||||||
|
|
||||||
return writes;
|
return writes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,6 +187,9 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty)
|
|||||||
}
|
}
|
||||||
|
|
||||||
writes += pim_rp_config_write(pim, vty);
|
writes += pim_rp_config_write(pim, vty);
|
||||||
|
#if PIM_IPV == 4
|
||||||
|
writes += pim_autorp_config_write(pim, vty);
|
||||||
|
#endif
|
||||||
writes += pim_cand_config_write(pim, vty);
|
writes += pim_cand_config_write(pim, vty);
|
||||||
|
|
||||||
if (pim->vrf->vrf_id == VRF_DEFAULT) {
|
if (pim->vrf->vrf_id == VRF_DEFAULT) {
|
||||||
|
@ -95,6 +95,7 @@
|
|||||||
#define PIM_MASK_VXLAN (1 << 26)
|
#define PIM_MASK_VXLAN (1 << 26)
|
||||||
#define PIM_MASK_BSM_PROC (1 << 27)
|
#define PIM_MASK_BSM_PROC (1 << 27)
|
||||||
#define PIM_MASK_MLAG (1 << 28)
|
#define PIM_MASK_MLAG (1 << 28)
|
||||||
|
#define PIM_MASK_AUTORP (1 << 29)
|
||||||
/* Remember 32 bits!!! */
|
/* Remember 32 bits!!! */
|
||||||
|
|
||||||
/* PIM error codes */
|
/* PIM error codes */
|
||||||
@ -167,6 +168,7 @@ extern uint8_t qpim_ecmp_rebalance_enable;
|
|||||||
#define PIM_DEBUG_MTRACE (router->debugs & PIM_MASK_MTRACE)
|
#define PIM_DEBUG_MTRACE (router->debugs & PIM_MASK_MTRACE)
|
||||||
#define PIM_DEBUG_VXLAN (router->debugs & PIM_MASK_VXLAN)
|
#define PIM_DEBUG_VXLAN (router->debugs & PIM_MASK_VXLAN)
|
||||||
#define PIM_DEBUG_BSM (router->debugs & PIM_MASK_BSM_PROC)
|
#define PIM_DEBUG_BSM (router->debugs & PIM_MASK_BSM_PROC)
|
||||||
|
#define PIM_DEBUG_AUTORP (router->debugs & PIM_MASK_AUTORP)
|
||||||
|
|
||||||
#define PIM_DEBUG_EVENTS \
|
#define PIM_DEBUG_EVENTS \
|
||||||
(router->debugs & (PIM_MASK_PIM_EVENTS | PIM_MASK_GM_EVENTS | \
|
(router->debugs & (PIM_MASK_PIM_EVENTS | PIM_MASK_GM_EVENTS | \
|
||||||
@ -209,6 +211,7 @@ extern uint8_t qpim_ecmp_rebalance_enable;
|
|||||||
#define PIM_DO_DEBUG_PIM_NHT_RP (router->debugs |= PIM_MASK_PIM_NHT_RP)
|
#define PIM_DO_DEBUG_PIM_NHT_RP (router->debugs |= PIM_MASK_PIM_NHT_RP)
|
||||||
#define PIM_DO_DEBUG_MTRACE (router->debugs |= PIM_MASK_MTRACE)
|
#define PIM_DO_DEBUG_MTRACE (router->debugs |= PIM_MASK_MTRACE)
|
||||||
#define PIM_DO_DEBUG_VXLAN (router->debugs |= PIM_MASK_VXLAN)
|
#define PIM_DO_DEBUG_VXLAN (router->debugs |= PIM_MASK_VXLAN)
|
||||||
|
#define PIM_DO_DEBUG_AUTORP (router->debugs |= PIM_MASK_AUTORP)
|
||||||
|
|
||||||
#define PIM_DONT_DEBUG_PIM_EVENTS (router->debugs &= ~PIM_MASK_PIM_EVENTS)
|
#define PIM_DONT_DEBUG_PIM_EVENTS (router->debugs &= ~PIM_MASK_PIM_EVENTS)
|
||||||
#define PIM_DONT_DEBUG_PIM_PACKETS (router->debugs &= ~PIM_MASK_PIM_PACKETS)
|
#define PIM_DONT_DEBUG_PIM_PACKETS (router->debugs &= ~PIM_MASK_PIM_PACKETS)
|
||||||
@ -243,6 +246,7 @@ extern uint8_t qpim_ecmp_rebalance_enable;
|
|||||||
#define PIM_DONT_DEBUG_MTRACE (router->debugs &= ~PIM_MASK_MTRACE)
|
#define PIM_DONT_DEBUG_MTRACE (router->debugs &= ~PIM_MASK_MTRACE)
|
||||||
#define PIM_DONT_DEBUG_VXLAN (router->debugs &= ~PIM_MASK_VXLAN)
|
#define PIM_DONT_DEBUG_VXLAN (router->debugs &= ~PIM_MASK_VXLAN)
|
||||||
#define PIM_DONT_DEBUG_BSM (router->debugs &= ~PIM_MASK_BSM_PROC)
|
#define PIM_DONT_DEBUG_BSM (router->debugs &= ~PIM_MASK_BSM_PROC)
|
||||||
|
#define PIM_DONT_DEBUG_AUTORP (router->debugs &= ~PIM_MASK_AUTORP)
|
||||||
|
|
||||||
/* RFC 3376: 8.1. Robustness Variable - Default: 2 for IGMP */
|
/* RFC 3376: 8.1. Robustness Variable - Default: 2 for IGMP */
|
||||||
/* RFC 2710: 7.1. Robustness Variable - Default: 2 for MLD */
|
/* RFC 2710: 7.1. Robustness Variable - Default: 2 for MLD */
|
||||||
|
@ -59,6 +59,7 @@ pim_common = \
|
|||||||
|
|
||||||
pimd_pimd_SOURCES = \
|
pimd_pimd_SOURCES = \
|
||||||
$(pim_common) \
|
$(pim_common) \
|
||||||
|
pimd/pim_autorp.c \
|
||||||
pimd/pim_cmd.c \
|
pimd/pim_cmd.c \
|
||||||
pimd/pim_igmp.c \
|
pimd/pim_igmp.c \
|
||||||
pimd/pim_igmp_mtrace.c \
|
pimd/pim_igmp_mtrace.c \
|
||||||
@ -98,6 +99,7 @@ nodist_pimd_pim6d_SOURCES = \
|
|||||||
noinst_HEADERS += \
|
noinst_HEADERS += \
|
||||||
pimd/pim_addr.h \
|
pimd/pim_addr.h \
|
||||||
pimd/pim_assert.h \
|
pimd/pim_assert.h \
|
||||||
|
pimd/pim_autorp.h \
|
||||||
pimd/pim_bfd.h \
|
pimd/pim_bfd.h \
|
||||||
pimd/pim_bsm.h \
|
pimd/pim_bsm.h \
|
||||||
pimd/pim_cmd.h \
|
pimd/pim_cmd.h \
|
||||||
|
@ -1745,6 +1745,49 @@ def verify_pim_rp_info(
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@retry(retry_timeout=60, diag_pct=0)
|
||||||
|
def verify_pim_rp_info_is_empty(tgen, dut, af="ipv4"):
|
||||||
|
"""
|
||||||
|
Verify pim rp info by running "show ip pim rp-info" cli
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
* `tgen`: topogen object
|
||||||
|
* `dut`: device under test
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
dut = "r1"
|
||||||
|
result = verify_pim_rp_info_is_empty(tgen, dut)
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
errormsg(str) or True
|
||||||
|
"""
|
||||||
|
|
||||||
|
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
|
||||||
|
|
||||||
|
if dut not in tgen.routers():
|
||||||
|
return False
|
||||||
|
|
||||||
|
rnode = tgen.routers()[dut]
|
||||||
|
|
||||||
|
ip_cmd = "ip"
|
||||||
|
if af == "ipv6":
|
||||||
|
ip_cmd = "ipv6"
|
||||||
|
|
||||||
|
logger.info("[DUT: %s]: Verifying %s rp info", dut, ip_cmd)
|
||||||
|
cmd = "show {} pim rp-info json".format(ip_cmd)
|
||||||
|
show_ip_rp_info_json = run_frr_cmd(rnode, cmd, isjson=True)
|
||||||
|
|
||||||
|
if show_ip_rp_info_json:
|
||||||
|
errormsg = "[DUT %s]: Verifying empty rp-info [FAILED]!!" % (dut)
|
||||||
|
return errormsg
|
||||||
|
|
||||||
|
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
@retry(retry_timeout=60, diag_pct=0)
|
@retry(retry_timeout=60, diag_pct=0)
|
||||||
def verify_pim_state(
|
def verify_pim_state(
|
||||||
tgen,
|
tgen,
|
||||||
@ -2411,10 +2454,11 @@ def clear_igmp_interfaces(tgen, dut):
|
|||||||
|
|
||||||
# Verify uptime for groups
|
# Verify uptime for groups
|
||||||
for group in group_before_clear.keys():
|
for group in group_before_clear.keys():
|
||||||
d1 = datetime.datetime.strptime(group_before_clear[group], "%H:%M:%S")
|
if group in group_after_clear:
|
||||||
d2 = datetime.datetime.strptime(group_after_clear[group], "%H:%M:%S")
|
d1 = datetime.datetime.strptime(group_before_clear[group], "%H:%M:%S")
|
||||||
if d2 >= d1:
|
d2 = datetime.datetime.strptime(group_after_clear[group], "%H:%M:%S")
|
||||||
errormsg = ("[DUT: %s]: IGMP group is not cleared", " [FAILED!!]", dut)
|
if d2 >= d1:
|
||||||
|
errormsg = ("[DUT: %s]: IGMP group is not cleared", " [FAILED!!]", dut)
|
||||||
|
|
||||||
logger.info("[DUT: %s]: IGMP group is cleared [PASSED!!]")
|
logger.info("[DUT: %s]: IGMP group is cleared [PASSED!!]")
|
||||||
|
|
||||||
@ -2751,6 +2795,48 @@ def scapy_send_bsr_raw_packet(tgen, topo, senderRouter, receiverRouter, packet=N
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def scapy_send_autorp_raw_packet(tgen, senderRouter, senderInterface, packet=None):
|
||||||
|
"""
|
||||||
|
Using scapy Raw() method to send AutoRP raw packet from one FRR
|
||||||
|
to other
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
-----------
|
||||||
|
* `tgen` : Topogen object
|
||||||
|
* `senderRouter` : Sender router
|
||||||
|
* `senderInterface` : SenderInterface
|
||||||
|
* `packet` : AutoRP packet in raw format
|
||||||
|
|
||||||
|
returns:
|
||||||
|
--------
|
||||||
|
errormsg or True
|
||||||
|
"""
|
||||||
|
|
||||||
|
global CWD
|
||||||
|
result = ""
|
||||||
|
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
|
||||||
|
|
||||||
|
python3_path = tgen.net.get_exec_path(["python3", "python"])
|
||||||
|
# send_bsr_packet.py has no direct ties to bsr, just sends a raw packet out
|
||||||
|
# a given interface, so just reuse it
|
||||||
|
script_path = os.path.join(CWD, "send_bsr_packet.py")
|
||||||
|
node = tgen.net[senderRouter]
|
||||||
|
|
||||||
|
cmd = [
|
||||||
|
python3_path,
|
||||||
|
script_path,
|
||||||
|
packet,
|
||||||
|
senderInterface,
|
||||||
|
"--interval=1",
|
||||||
|
"--count=1",
|
||||||
|
]
|
||||||
|
logger.info("Scapy cmd: \n %s", cmd)
|
||||||
|
node.cmd_raises(cmd)
|
||||||
|
|
||||||
|
logger.debug("Exiting lib API: scapy_send_autorp_raw_packet")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def find_rp_from_bsrp_info(tgen, dut, bsr, grp=None):
|
def find_rp_from_bsrp_info(tgen, dut, bsr, grp=None):
|
||||||
"""
|
"""
|
||||||
Find which RP is having lowest prioriy and returns rp IP
|
Find which RP is having lowest prioriy and returns rp IP
|
||||||
|
@ -1 +1 @@
|
|||||||
{"totalGroups":5,"watermarkLimit":0,"l1-i1-eth1":{"name":"l1-i1-eth1","state":"up","address":"10.0.8.2","index":"*","flagMulticast":true,"flagBroadcast":true,"lanDelayEnabled":true,"groups":[{"group":"225.1.1.2","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.1","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.3","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.5","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.4","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]}]}}
|
{"watermarkLimit":0,"l1-i1-eth1":{"name":"l1-i1-eth1","state":"up","address":"10.0.8.2","index":"*","flagMulticast":true,"flagBroadcast":true,"lanDelayEnabled":true,"groups":[{"group":"225.1.1.2","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.1","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.3","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.5","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.4","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]}]}}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"totalGroups":5,
|
|
||||||
"watermarkLimit":0,
|
"watermarkLimit":0,
|
||||||
"l1-i1-eth1":{
|
"l1-i1-eth1":{
|
||||||
"name":"l1-i1-eth1",
|
"name":"l1-i1-eth1",
|
||||||
@ -48,4 +47,3 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
{"totalGroups":5,"watermarkLimit":0,"l1-i1-eth1":{"name":"l1-i1-eth1","state":"up","address":"10.0.8.2","index":"*","flagMulticast":true,"flagBroadcast":true,"lanDelayEnabled":true,"groups":[{"group":"225.1.1.1","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.2","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.3","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.4","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.5","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]}]}}
|
{"watermarkLimit":0,"l1-i1-eth1":{"name":"l1-i1-eth1","state":"up","address":"10.0.8.2","index":"*","flagMulticast":true,"flagBroadcast":true,"lanDelayEnabled":true,"groups":[{"group":"225.1.1.1","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.2","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.3","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.4","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]},{"group":"225.1.1.5","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]}]}}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"totalGroups":5,
|
|
||||||
"watermarkLimit":0,
|
"watermarkLimit":0,
|
||||||
"l1-i1-eth1":{
|
"l1-i1-eth1":{
|
||||||
"name":"l1-i1-eth1",
|
"name":"l1-i1-eth1",
|
||||||
|
@ -1 +1 @@
|
|||||||
{"totalGroups":5,"watermarkLimit":0,"l1-i1-eth1":{"name":"l1-i1-eth1","state":"up","address":"10.0.8.2","index":"*","flagMulticast":true,"flagBroadcast":true,"lanDelayEnabled":true,"groups":[{"group":"225.1.1.5","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]}]}}
|
{"watermarkLimit":0,"l1-i1-eth1":{"name":"l1-i1-eth1","state":"up","address":"10.0.8.2","index":"*","flagMulticast":true,"flagBroadcast":true,"lanDelayEnabled":true,"groups":[{"group":"225.1.1.5","timer":"*","sourcesCount":1,"version":2,"uptime":"*","sources":[{"source":"*","timer":"*","forwarded":true,"uptime":"*"}]}]}}
|
||||||
|
0
tests/topotests/pim_autorp/__init__.py
Executable file
0
tests/topotests/pim_autorp/__init__.py
Executable file
16
tests/topotests/pim_autorp/r1/frr.conf
Normal file
16
tests/topotests/pim_autorp/r1/frr.conf
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
!
|
||||||
|
hostname r1
|
||||||
|
password zebra
|
||||||
|
log file /tmp/r1-frr.log
|
||||||
|
debug pim autorp
|
||||||
|
!
|
||||||
|
interface r1-eth0
|
||||||
|
ip address 10.10.76.1/24
|
||||||
|
ip igmp
|
||||||
|
ip pim
|
||||||
|
!
|
||||||
|
ip forwarding
|
||||||
|
!
|
||||||
|
router pim
|
||||||
|
autorp discovery
|
||||||
|
!
|
16
tests/topotests/pim_autorp/r2/frr.conf
Normal file
16
tests/topotests/pim_autorp/r2/frr.conf
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
!
|
||||||
|
hostname r2
|
||||||
|
password zebra
|
||||||
|
log file /tmp/r2-frr.log
|
||||||
|
debug pim autorp
|
||||||
|
!
|
||||||
|
interface r2-eth0
|
||||||
|
ip address 10.10.76.2/24
|
||||||
|
ip igmp
|
||||||
|
ip pim
|
||||||
|
!
|
||||||
|
ip forwarding
|
||||||
|
!
|
||||||
|
router pim
|
||||||
|
autorp discovery
|
||||||
|
!
|
207
tests/topotests/pim_autorp/test_pim_autorp.py
Normal file
207
tests/topotests/pim_autorp/test_pim_autorp.py
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# SPDX-License-Identifier: ISC
|
||||||
|
|
||||||
|
#
|
||||||
|
# test_pim_autorp.py
|
||||||
|
#
|
||||||
|
# Copyright (c) 2024 ATCorp
|
||||||
|
# Nathan Bahr
|
||||||
|
#
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
# pylint: disable=C0413
|
||||||
|
# Import topogen and topotest helpers
|
||||||
|
from lib.topogen import Topogen, get_topogen
|
||||||
|
from lib.topolog import logger
|
||||||
|
from lib.pim import scapy_send_autorp_raw_packet, verify_pim_rp_info, verify_pim_rp_info_is_empty
|
||||||
|
from lib.common_config import step, write_test_header
|
||||||
|
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
"""
|
||||||
|
test_pim_autorp.py: Test general PIM AutoRP functionality
|
||||||
|
"""
|
||||||
|
|
||||||
|
TOPOLOGY = """
|
||||||
|
Basic AutoRP functionality
|
||||||
|
|
||||||
|
+---+---+ +---+---+
|
||||||
|
| | 10.10.76.0/24 | |
|
||||||
|
+ R1 + <------------------> + R2 |
|
||||||
|
| | .1 .2 | |
|
||||||
|
+---+---+ +---+---+
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Save the Current Working Directory to find configuration files.
|
||||||
|
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
sys.path.append(os.path.join(CWD, "../"))
|
||||||
|
|
||||||
|
# Required to instantiate the topology builder class.
|
||||||
|
pytestmark = [pytest.mark.pimd]
|
||||||
|
|
||||||
|
|
||||||
|
def build_topo(tgen):
|
||||||
|
"Build function"
|
||||||
|
|
||||||
|
# Create routers
|
||||||
|
tgen.add_router("r1")
|
||||||
|
tgen.add_router("r2")
|
||||||
|
|
||||||
|
# Create link between router 1 and 2
|
||||||
|
switch = tgen.add_switch("s1-2")
|
||||||
|
switch.add_link(tgen.gears["r1"])
|
||||||
|
switch.add_link(tgen.gears["r2"])
|
||||||
|
|
||||||
|
def setup_module(mod):
|
||||||
|
logger.info("PIM AutoRP basic functionality:\n {}".format(TOPOLOGY))
|
||||||
|
|
||||||
|
tgen = Topogen(build_topo, mod.__name__)
|
||||||
|
tgen.start_topology()
|
||||||
|
|
||||||
|
# Router 1 will be the router configured with "fake" autorp configuration, so give it a default route
|
||||||
|
# to router 2 so that routing to the RP address is not an issue
|
||||||
|
# r1_defrt_setup_cmds = [
|
||||||
|
# "ip route add default via 10.10.76.1 dev r1-eth0",
|
||||||
|
# ]
|
||||||
|
# for cmd in r1_defrt_setup_cmds:
|
||||||
|
# tgen.net["r1"].cmd(cmd)
|
||||||
|
|
||||||
|
logger.info("Testing PIM AutoRP support")
|
||||||
|
router_list = tgen.routers()
|
||||||
|
for rname, router in router_list.items():
|
||||||
|
logger.info("Loading router %s" % rname)
|
||||||
|
router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
|
||||||
|
|
||||||
|
# Initialize all routers.
|
||||||
|
tgen.start_router()
|
||||||
|
for router in router_list.values():
|
||||||
|
if router.has_version("<", "4.0"):
|
||||||
|
tgen.set_error("unsupported version")
|
||||||
|
|
||||||
|
|
||||||
|
def teardown_module(mod):
|
||||||
|
"Teardown the pytest environment"
|
||||||
|
tgen = get_topogen()
|
||||||
|
tgen.stop_topology()
|
||||||
|
|
||||||
|
def test_pim_autorp_discovery_single_rp(request):
|
||||||
|
"Test PIM AutoRP Discovery with single RP"
|
||||||
|
tgen = get_topogen()
|
||||||
|
tc_name = request.node.name
|
||||||
|
write_test_header(tc_name)
|
||||||
|
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
step("Start with no RP configuration")
|
||||||
|
result = verify_pim_rp_info_is_empty(tgen, "r1")
|
||||||
|
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||||
|
|
||||||
|
step("Send AutoRP packet from r1 to r2")
|
||||||
|
# 1 RP(s), hold time 5 secs, 10.10.76.1, group(s) 224.0.0.0/4
|
||||||
|
data = "01005e00012800127f55cfb1080045c00030700c000008110abe0a0a4c01e000012801f001f0001c798b12010005000000000a0a4c0103010004e0000000"
|
||||||
|
scapy_send_autorp_raw_packet(tgen, "r1", "r1-eth0", data)
|
||||||
|
|
||||||
|
step("Verify rp-info from AutoRP packet")
|
||||||
|
result = verify_pim_rp_info(tgen, None, "r2", "224.0.0.0/4", "r2-eth0", "10.10.76.1", "AutoRP", False, "ipv4", True)
|
||||||
|
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||||
|
|
||||||
|
step("Verify AutoRP configuration times out")
|
||||||
|
result = verify_pim_rp_info_is_empty(tgen, "r2")
|
||||||
|
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||||
|
|
||||||
|
def test_pim_autorp_discovery_multiple_rp(request):
|
||||||
|
"Test PIM AutoRP Discovery with multiple RP's"
|
||||||
|
tgen = get_topogen()
|
||||||
|
tc_name = request.node.name
|
||||||
|
write_test_header(tc_name)
|
||||||
|
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip("skipped because of router(s) failure")
|
||||||
|
|
||||||
|
step("Start with no RP configuration")
|
||||||
|
result = verify_pim_rp_info_is_empty(tgen, "r2")
|
||||||
|
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||||
|
|
||||||
|
step("Send AutoRP packet from r1 to r2")
|
||||||
|
# 2 RP(s), hold time 5 secs, 10.10.76.1, group(s) 224.0.0.0/8, 10.10.76.3, group(s) 225.0.0.0/8
|
||||||
|
data = "01005e00012800127f55cfb1080045c0003c700c000008110ab20a0a4c01e000012801f001f000283f5712020005000000000a0a4c0103010008e00000000a0a4c0303010008e1000000"
|
||||||
|
scapy_send_autorp_raw_packet(tgen, "r1", "r1-eth0", data)
|
||||||
|
|
||||||
|
step("Verify rp-info from AutoRP packet")
|
||||||
|
result = verify_pim_rp_info(tgen, None, "r2", "224.0.0.0/8", "r2-eth0", "10.10.76.1", "AutoRP", False, "ipv4", True)
|
||||||
|
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||||
|
result = verify_pim_rp_info(tgen, None, "r2", "225.0.0.0/8", "r2-eth0", "10.10.76.3", "AutoRP", False, "ipv4", True)
|
||||||
|
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||||
|
|
||||||
|
|
||||||
|
def test_pim_autorp_discovery_static(request):
|
||||||
|
"Test PIM AutoRP Discovery with Static RP"
|
||||||
|
tgen = get_topogen()
|
||||||
|
tc_name = request.node.name
|
||||||
|
write_test_header(tc_name)
|
||||||
|
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip("skipped because of router(s) failure")
|
||||||
|
|
||||||
|
step("Start with no RP configuration")
|
||||||
|
result = verify_pim_rp_info_is_empty(tgen, "r2")
|
||||||
|
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||||
|
|
||||||
|
step("Add static RP configuration to r2")
|
||||||
|
rnode = tgen.routers()["r2"]
|
||||||
|
rnode.cmd("vtysh -c 'conf t' -c 'router pim' -c 'rp 10.10.76.3 224.0.0.0/4'")
|
||||||
|
|
||||||
|
step("Verify static rp-info from r2")
|
||||||
|
result = verify_pim_rp_info(tgen, None, "r2", "224.0.0.0/4", "r2-eth0", "10.10.76.3", "Static", False, "ipv4", True)
|
||||||
|
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||||
|
|
||||||
|
step("Send AutoRP packet from r1 to r2")
|
||||||
|
# 1 RP(s), hold time 5 secs, 10.10.76.1, group(s) 224.0.0.0/4
|
||||||
|
data = "01005e00012800127f55cfb1080045c00030700c000008110abe0a0a4c01e000012801f001f0001c798b12010005000000000a0a4c0103010004e0000000"
|
||||||
|
scapy_send_autorp_raw_packet(tgen, "r1", "r1-eth0", data)
|
||||||
|
|
||||||
|
step("Verify rp-info from AutoRP packet")
|
||||||
|
result = verify_pim_rp_info(tgen, None, "r2", "224.0.0.0/4", "r2-eth0", "10.10.76.1", "AutoRP", False, "ipv4", True)
|
||||||
|
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||||
|
|
||||||
|
|
||||||
|
def test_pim_autorp_announce_group(request):
|
||||||
|
"Test PIM AutoRP Announcement with a single group"
|
||||||
|
tgen = get_topogen()
|
||||||
|
tc_name = request.node.name
|
||||||
|
write_test_header(tc_name)
|
||||||
|
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip("skipped because of router(s) failure")
|
||||||
|
|
||||||
|
step("Add candidate RP configuration to r1")
|
||||||
|
rnode = tgen.routers()["r1"]
|
||||||
|
rnode.cmd("vtysh -c 'conf t' -c 'router pim' -c 'send-rp-announce 10.10.76.1 224.0.0.0/4'")
|
||||||
|
step("Verify Announcement sent data")
|
||||||
|
# TODO: Verify AutoRP mapping agent receives candidate RP announcement
|
||||||
|
# Mapping agent is not yet implemented
|
||||||
|
#sleep(10)
|
||||||
|
step("Change AutoRP Announcement packet parameters")
|
||||||
|
rnode.cmd("vtysh -c 'conf t' -c 'router pim' -c 'send-rp-announce scope 8 interval 10 holdtime 60'")
|
||||||
|
step("Verify Announcement sent data")
|
||||||
|
# TODO: Verify AutoRP mapping agent receives updated candidate RP announcement
|
||||||
|
# Mapping agent is not yet implemented
|
||||||
|
#sleep(10)
|
||||||
|
|
||||||
|
|
||||||
|
def test_memory_leak():
|
||||||
|
"Run the memory leak test and report results."
|
||||||
|
tgen = get_topogen()
|
||||||
|
if not tgen.is_memleak_enabled():
|
||||||
|
pytest.skip("Memory leak test/report is disabled")
|
||||||
|
|
||||||
|
tgen.report_memory_leaks()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
args = ["-s"] + sys.argv[1:]
|
||||||
|
sys.exit(pytest.main(args))
|
@ -111,6 +111,70 @@ module frr-pim-rp {
|
|||||||
} // static-rp
|
} // static-rp
|
||||||
} // static-rp-container
|
} // static-rp-container
|
||||||
|
|
||||||
|
grouping auto-rp-container {
|
||||||
|
description
|
||||||
|
"Grouping of AutoRP container.";
|
||||||
|
|
||||||
|
container auto-rp {
|
||||||
|
description
|
||||||
|
"Containing AutoRP attributes.";
|
||||||
|
|
||||||
|
leaf discovery-enabled {
|
||||||
|
type boolean;
|
||||||
|
description
|
||||||
|
"Flag indicating if Auto RP discovery is enabled.";
|
||||||
|
}
|
||||||
|
|
||||||
|
leaf announce-scope {
|
||||||
|
type uint8;
|
||||||
|
description
|
||||||
|
"The TTL of the C-RP Announcement packet.";
|
||||||
|
}
|
||||||
|
|
||||||
|
leaf announce-interval {
|
||||||
|
type uint16;
|
||||||
|
description
|
||||||
|
"The time between sending C-RP announcement packets.";
|
||||||
|
}
|
||||||
|
|
||||||
|
leaf announce-holdtime {
|
||||||
|
type uint16;
|
||||||
|
description
|
||||||
|
"The hold time in seconds advertised in the announcement packet.";
|
||||||
|
}
|
||||||
|
|
||||||
|
list candidate-rp-list {
|
||||||
|
key "rp-address";
|
||||||
|
description
|
||||||
|
"A list of Candidate RP addresses.";
|
||||||
|
|
||||||
|
leaf rp-address {
|
||||||
|
type inet:ip-address;
|
||||||
|
description
|
||||||
|
"Specifies a candidate RP address.";
|
||||||
|
}
|
||||||
|
|
||||||
|
choice group-or-prefix-list {
|
||||||
|
description "Use group or prefix-list";
|
||||||
|
case group {
|
||||||
|
leaf group {
|
||||||
|
type frr-route-types:ip-multicast-group-prefix;
|
||||||
|
description
|
||||||
|
"Multicast group prefix.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case prefix-list {
|
||||||
|
leaf prefix-list {
|
||||||
|
type plist-ref;
|
||||||
|
description
|
||||||
|
"Group prefix-list filter";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // candidate-rp-list
|
||||||
|
} // auto-rp
|
||||||
|
} // auto-rp-container
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configuration data nodes
|
* Configuration data nodes
|
||||||
*/
|
*/
|
||||||
@ -123,6 +187,13 @@ module frr-pim-rp {
|
|||||||
description
|
description
|
||||||
"PIM RP configuration data.";
|
"PIM RP configuration data.";
|
||||||
uses static-rp-container;
|
uses static-rp-container;
|
||||||
|
|
||||||
|
uses auto-rp-container {
|
||||||
|
when "../frr-pim:address-family = 'frr-rt:ipv4'" {
|
||||||
|
description
|
||||||
|
"Only applicable to IPv4 address family.";
|
||||||
|
}
|
||||||
|
}
|
||||||
} // rp
|
} // rp
|
||||||
} // augment
|
} // augment
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user