]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_ssm.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / pimd / pim_ssm.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * IP SSM ranges for FRR
4 * Copyright (C) 2017 Cumulus Networks, Inc.
5 */
6
7 #include <zebra.h>
8
9 #include <lib/linklist.h>
10 #include <lib/prefix.h>
11 #include <lib/vty.h>
12 #include <lib/vrf.h>
13 #include <lib/plist.h>
14 #include <lib/lib_errors.h>
15
16 #include "pimd.h"
17 #include "pim_instance.h"
18 #include "pim_ssm.h"
19 #include "pim_igmp.h"
20
21 static void pim_ssm_range_reevaluate(struct pim_instance *pim)
22 {
23 #if PIM_IPV == 4
24 /* 1. Setup register state for (S,G) entries if G has changed from SSM
25 * to
26 * ASM.
27 * 2. check existing (*,G) IGMP registrations to see if they are
28 * still ASM. if they are now SSM delete them.
29 * 3. Allow channel setup for IGMP (*,G) members if G is now ASM
30 * 4. I could tear down all (*,G), (S,G,rpt) states. But that is an
31 * unnecessary sladge hammer and may not be particularly useful as it is
32 * likely the SPT switchover has already happened for flows along such
33 * RPTs.
34 * As for the RPT states it seems that the best thing to do is let them
35 * age
36 * out gracefully. As long as the FHR and LHR do the right thing RPTs
37 * will
38 * disappear in time for SSM groups.
39 */
40 pim_upstream_register_reevaluate(pim);
41 igmp_source_forward_reevaluate_all(pim);
42 #endif
43 }
44
45 void pim_ssm_prefix_list_update(struct pim_instance *pim,
46 struct prefix_list *plist)
47 {
48 struct pim_ssm *ssm = pim->ssm_info;
49
50 if (!ssm->plist_name
51 || strcmp(ssm->plist_name, prefix_list_name(plist))) {
52 /* not ours */
53 return;
54 }
55
56 pim_ssm_range_reevaluate(pim);
57 }
58
59 static int pim_is_grp_standard_ssm(struct prefix *group)
60 {
61 pim_addr addr = pim_addr_from_prefix(group);
62
63 return pim_addr_ssm(addr);
64 }
65
66 int pim_is_grp_ssm(struct pim_instance *pim, pim_addr group_addr)
67 {
68 struct pim_ssm *ssm;
69 struct prefix group;
70 struct prefix_list *plist;
71
72 pim_addr_to_prefix(&group, group_addr);
73
74 ssm = pim->ssm_info;
75 if (!ssm->plist_name) {
76 return pim_is_grp_standard_ssm(&group);
77 }
78
79 plist = prefix_list_lookup(PIM_AFI, ssm->plist_name);
80 if (!plist)
81 return 0;
82
83 return (prefix_list_apply_ext(plist, NULL, &group, true) ==
84 PREFIX_PERMIT);
85 }
86
87 int pim_ssm_range_set(struct pim_instance *pim, vrf_id_t vrf_id,
88 const char *plist_name)
89 {
90 struct pim_ssm *ssm;
91 int change = 0;
92
93 if (vrf_id != pim->vrf->vrf_id)
94 return PIM_SSM_ERR_NO_VRF;
95
96 ssm = pim->ssm_info;
97 if (plist_name) {
98 if (ssm->plist_name) {
99 if (!strcmp(ssm->plist_name, plist_name))
100 return PIM_SSM_ERR_DUP;
101 XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name);
102 }
103 ssm->plist_name = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist_name);
104 change = 1;
105 } else {
106 if (ssm->plist_name) {
107 change = 1;
108 XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name);
109 }
110 }
111
112 if (change)
113 pim_ssm_range_reevaluate(pim);
114
115 return PIM_SSM_ERR_NONE;
116 }
117
118 void *pim_ssm_init(void)
119 {
120 struct pim_ssm *ssm;
121
122 ssm = XCALLOC(MTYPE_PIM_SSM_INFO, sizeof(*ssm));
123
124 return ssm;
125 }
126
127 void pim_ssm_terminate(struct pim_ssm *ssm)
128 {
129 if (!ssm)
130 return;
131
132 XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name);
133
134 XFREE(MTYPE_PIM_SSM_INFO, ssm);
135 }