]>
Commit | Line | Data |
---|---|---|
15a5dafe | 1 | /* |
2 | * IP SSM ranges for FRR | |
3 | * Copyright (C) 2017 Cumulus Networks, Inc. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation; either version 2 of the License, or | |
8 | * (at your option) any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * General Public License for more details. | |
14 | * | |
896014f4 DL |
15 | * You should have received a copy of the GNU General Public License along |
16 | * with this program; see the file COPYING; if not, write to the Free Software | |
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
15a5dafe | 18 | */ |
19 | ||
9e6fca3a | 20 | #include <zebra.h> |
21 | ||
15a5dafe | 22 | #include <lib/linklist.h> |
23 | #include <lib/prefix.h> | |
24 | #include <lib/vty.h> | |
25 | #include <lib/vrf.h> | |
26 | #include <lib/plist.h> | |
d9ff4302 | 27 | #include <lib/lib_errors.h> |
15a5dafe | 28 | |
29 | #include "pimd.h" | |
993e3d8e | 30 | #include "pim_instance.h" |
15a5dafe | 31 | #include "pim_ssm.h" |
cd6d2858 | 32 | #include "pim_igmp.h" |
15a5dafe | 33 | |
6f439a70 | 34 | static void pim_ssm_range_reevaluate(struct pim_instance *pim) |
15a5dafe | 35 | { |
94120cb2 | 36 | #if PIM_IPV == 4 |
d62a17ae | 37 | /* 1. Setup register state for (S,G) entries if G has changed from SSM |
38 | * to | |
39 | * ASM. | |
40 | * 2. check existing (*,G) IGMP registrations to see if they are | |
41 | * still ASM. if they are now SSM delete them. | |
42 | * 3. Allow channel setup for IGMP (*,G) members if G is now ASM | |
43 | * 4. I could tear down all (*,G), (S,G,rpt) states. But that is an | |
44 | * unnecessary sladge hammer and may not be particularly useful as it is | |
45 | * likely the SPT switchover has already happened for flows along such | |
46 | * RPTs. | |
47 | * As for the RPT states it seems that the best thing to do is let them | |
48 | * age | |
49 | * out gracefully. As long as the FHR and LHR do the right thing RPTs | |
50 | * will | |
51 | * disappear in time for SSM groups. | |
52 | */ | |
6f439a70 | 53 | pim_upstream_register_reevaluate(pim); |
5d59e408 | 54 | igmp_source_forward_reevaluate_all(pim); |
94120cb2 | 55 | #endif |
15a5dafe | 56 | } |
57 | ||
6f439a70 DS |
58 | void pim_ssm_prefix_list_update(struct pim_instance *pim, |
59 | struct prefix_list *plist) | |
15a5dafe | 60 | { |
6f439a70 | 61 | struct pim_ssm *ssm = pim->ssm_info; |
15a5dafe | 62 | |
d62a17ae | 63 | if (!ssm->plist_name |
64 | || strcmp(ssm->plist_name, prefix_list_name(plist))) { | |
65 | /* not ours */ | |
66 | return; | |
67 | } | |
15a5dafe | 68 | |
6f439a70 | 69 | pim_ssm_range_reevaluate(pim); |
15a5dafe | 70 | } |
71 | ||
d62a17ae | 72 | static int pim_is_grp_standard_ssm(struct prefix *group) |
15a5dafe | 73 | { |
95793341 | 74 | pim_addr addr = pim_addr_from_prefix(group); |
15a5dafe | 75 | |
95793341 | 76 | return pim_addr_ssm(addr); |
15a5dafe | 77 | } |
78 | ||
80d9fa1e | 79 | int pim_is_grp_ssm(struct pim_instance *pim, pim_addr group_addr) |
15a5dafe | 80 | { |
d62a17ae | 81 | struct pim_ssm *ssm; |
82 | struct prefix group; | |
83 | struct prefix_list *plist; | |
84 | ||
80d9fa1e | 85 | pim_addr_to_prefix(&group, group_addr); |
d62a17ae | 86 | |
6f439a70 | 87 | ssm = pim->ssm_info; |
d62a17ae | 88 | if (!ssm->plist_name) { |
89 | return pim_is_grp_standard_ssm(&group); | |
90 | } | |
91 | ||
80d9fa1e | 92 | plist = prefix_list_lookup(PIM_AFI, ssm->plist_name); |
d62a17ae | 93 | if (!plist) |
94 | return 0; | |
95 | ||
96 | return (prefix_list_apply(plist, &group) == PREFIX_PERMIT); | |
15a5dafe | 97 | } |
98 | ||
6f439a70 DS |
99 | int pim_ssm_range_set(struct pim_instance *pim, vrf_id_t vrf_id, |
100 | const char *plist_name) | |
15a5dafe | 101 | { |
d62a17ae | 102 | struct pim_ssm *ssm; |
103 | int change = 0; | |
104 | ||
d3cc1e45 | 105 | if (vrf_id != pim->vrf->vrf_id) |
d62a17ae | 106 | return PIM_SSM_ERR_NO_VRF; |
107 | ||
6f439a70 | 108 | ssm = pim->ssm_info; |
d62a17ae | 109 | if (plist_name) { |
110 | if (ssm->plist_name) { | |
111 | if (!strcmp(ssm->plist_name, plist_name)) | |
112 | return PIM_SSM_ERR_DUP; | |
113 | XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name); | |
114 | } | |
115 | ssm->plist_name = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist_name); | |
116 | change = 1; | |
117 | } else { | |
118 | if (ssm->plist_name) { | |
119 | change = 1; | |
120 | XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name); | |
121 | } | |
122 | } | |
123 | ||
124 | if (change) | |
6f439a70 | 125 | pim_ssm_range_reevaluate(pim); |
d62a17ae | 126 | |
127 | return PIM_SSM_ERR_NONE; | |
15a5dafe | 128 | } |
129 | ||
e07fe9e6 | 130 | void *pim_ssm_init(void) |
15a5dafe | 131 | { |
d62a17ae | 132 | struct pim_ssm *ssm; |
15a5dafe | 133 | |
d62a17ae | 134 | ssm = XCALLOC(MTYPE_PIM_SSM_INFO, sizeof(*ssm)); |
15a5dafe | 135 | |
d62a17ae | 136 | return ssm; |
15a5dafe | 137 | } |
138 | ||
d62a17ae | 139 | void pim_ssm_terminate(struct pim_ssm *ssm) |
15a5dafe | 140 | { |
27cfe222 DS |
141 | if (!ssm) |
142 | return; | |
143 | ||
0a22ddfb | 144 | XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name); |
27cfe222 DS |
145 | |
146 | XFREE(MTYPE_PIM_SSM_INFO, ssm); | |
15a5dafe | 147 | } |