Line | Count | Source |
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 | 0 | { |
23 | 0 | #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 | 0 | pim_upstream_register_reevaluate(pim); |
41 | 0 | igmp_source_forward_reevaluate_all(pim); |
42 | 0 | #endif |
43 | 0 | } |
44 | | |
45 | | void pim_ssm_prefix_list_update(struct pim_instance *pim, |
46 | | struct prefix_list *plist) |
47 | 0 | { |
48 | 0 | struct pim_ssm *ssm = pim->ssm_info; |
49 | |
|
50 | 0 | if (!ssm->plist_name |
51 | 0 | || strcmp(ssm->plist_name, prefix_list_name(plist))) { |
52 | | /* not ours */ |
53 | 0 | return; |
54 | 0 | } |
55 | | |
56 | 0 | pim_ssm_range_reevaluate(pim); |
57 | 0 | } |
58 | | |
59 | | static int pim_is_grp_standard_ssm(struct prefix *group) |
60 | 28 | { |
61 | 28 | pim_addr addr = pim_addr_from_prefix(group); |
62 | | |
63 | 28 | return pim_addr_ssm(addr); |
64 | 28 | } |
65 | | |
66 | | int pim_is_grp_ssm(struct pim_instance *pim, pim_addr group_addr) |
67 | 28 | { |
68 | 28 | struct pim_ssm *ssm; |
69 | 28 | struct prefix group; |
70 | 28 | struct prefix_list *plist; |
71 | | |
72 | 28 | pim_addr_to_prefix(&group, group_addr); |
73 | | |
74 | 28 | ssm = pim->ssm_info; |
75 | 28 | if (!ssm->plist_name) { |
76 | 28 | return pim_is_grp_standard_ssm(&group); |
77 | 28 | } |
78 | | |
79 | 0 | plist = prefix_list_lookup(PIM_AFI, ssm->plist_name); |
80 | 0 | if (!plist) |
81 | 0 | return 0; |
82 | | |
83 | 0 | return (prefix_list_apply_ext(plist, NULL, &group, true) == |
84 | 0 | PREFIX_PERMIT); |
85 | 0 | } |
86 | | |
87 | | int pim_ssm_range_set(struct pim_instance *pim, vrf_id_t vrf_id, |
88 | | const char *plist_name) |
89 | 0 | { |
90 | 0 | struct pim_ssm *ssm; |
91 | 0 | int change = 0; |
92 | |
|
93 | 0 | if (vrf_id != pim->vrf->vrf_id) |
94 | 0 | return PIM_SSM_ERR_NO_VRF; |
95 | | |
96 | 0 | ssm = pim->ssm_info; |
97 | 0 | if (plist_name) { |
98 | 0 | if (ssm->plist_name) { |
99 | 0 | if (!strcmp(ssm->plist_name, plist_name)) |
100 | 0 | return PIM_SSM_ERR_DUP; |
101 | 0 | XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name); |
102 | 0 | } |
103 | 0 | ssm->plist_name = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist_name); |
104 | 0 | change = 1; |
105 | 0 | } else { |
106 | 0 | if (ssm->plist_name) { |
107 | 0 | change = 1; |
108 | 0 | XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name); |
109 | 0 | } |
110 | 0 | } |
111 | | |
112 | 0 | if (change) |
113 | 0 | pim_ssm_range_reevaluate(pim); |
114 | |
|
115 | 0 | return PIM_SSM_ERR_NONE; |
116 | 0 | } |
117 | | |
118 | | void *pim_ssm_init(void) |
119 | 1 | { |
120 | 1 | struct pim_ssm *ssm; |
121 | | |
122 | 1 | ssm = XCALLOC(MTYPE_PIM_SSM_INFO, sizeof(*ssm)); |
123 | | |
124 | 1 | return ssm; |
125 | 1 | } |
126 | | |
127 | | void pim_ssm_terminate(struct pim_ssm *ssm) |
128 | 0 | { |
129 | 0 | if (!ssm) |
130 | 0 | return; |
131 | | |
132 | 0 | XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name); |
133 | |
|
134 | | XFREE(MTYPE_PIM_SSM_INFO, ssm); |
135 | 0 | } |