]>
git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_static.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * PIM for Quagga: add the ability to configure multicast static routes
4 * Copyright (C) 2014 Nathan Bahr, ATCorp
16 #include "pim_instance.h"
18 #include "pim_static.h"
21 #include "pim_iface.h"
23 void pim_static_route_free(struct static_route
*s_route
)
25 XFREE(MTYPE_PIM_STATIC_ROUTE
, s_route
);
28 static struct static_route
*static_route_alloc(void)
30 return XCALLOC(MTYPE_PIM_STATIC_ROUTE
, sizeof(struct static_route
));
33 static struct static_route
*static_route_new(ifindex_t iif
, ifindex_t oif
,
37 struct static_route
*s_route
;
38 s_route
= static_route_alloc();
40 s_route
->group
= group
;
41 s_route
->source
= source
;
43 s_route
->oif_ttls
[oif
] = 1;
44 s_route
->c_oil
.oil_ref_count
= 1;
45 *oil_origin(&s_route
->c_oil
) = source
;
46 *oil_mcastgrp(&s_route
->c_oil
) = group
;
47 *oil_parent(&s_route
->c_oil
) = iif
;
48 oil_if_set(&s_route
->c_oil
, oif
, 1);
49 s_route
->c_oil
.oif_creation
[oif
] = pim_time_monotonic_sec();
55 int pim_static_add(struct pim_instance
*pim
, struct interface
*iif
,
56 struct interface
*oif
, pim_addr group
, pim_addr source
)
58 struct listnode
*node
= NULL
;
59 struct static_route
*s_route
= NULL
;
60 struct static_route
*original_s_route
= NULL
;
61 struct pim_interface
*pim_iif
= iif
? iif
->info
: NULL
;
62 struct pim_interface
*pim_oif
= oif
? oif
->info
: NULL
;
63 ifindex_t iif_index
= pim_iif
? pim_iif
->mroute_vif_index
: 0;
64 ifindex_t oif_index
= pim_oif
? pim_oif
->mroute_vif_index
: 0;
66 if (!iif_index
|| !oif_index
|| iif_index
== -1 || oif_index
== -1) {
68 "%s %s: Unable to add static route: Invalid interface index(iif=%d,oif=%d)",
69 __FILE__
, __func__
, iif_index
, oif_index
);
73 #ifdef PIM_ENFORCE_LOOPFREE_MFC
74 if (iif_index
== oif_index
) {
75 /* looped MFC entry */
77 "%s %s: Unable to add static route: Looped MFC entry(iif=%d,oif=%d)",
78 __FILE__
, __func__
, iif_index
, oif_index
);
82 if (iif
->vrf
->vrf_id
!= oif
->vrf
->vrf_id
) {
86 for (ALL_LIST_ELEMENTS_RO(pim
->static_routes
, node
, s_route
)) {
87 if (!pim_addr_cmp(s_route
->group
, group
) &&
88 !pim_addr_cmp(s_route
->source
, source
) &&
89 (s_route
->iif
== iif_index
)) {
91 if (s_route
->oif_ttls
[oif_index
]) {
93 "%s %s: Unable to add static route: Route already exists (iif=%d,oif=%d,group=%pPAs,source=%pPAs)",
94 __FILE__
, __func__
, iif_index
,
95 oif_index
, &group
, &source
);
99 /* Ok, from here on out we will be making changes to the
100 * s_route structure, but if
101 * for some reason we fail to commit these changes to
102 * the kernel, we want to be able
103 * restore the state of the list. So copy the node data
104 * and if need be, we can copy
107 original_s_route
= static_route_alloc();
108 memcpy(original_s_route
, s_route
,
109 sizeof(struct static_route
));
111 /* Route exists and has the same input interface, but
112 * adding a new output interface */
113 s_route
->oif_ttls
[oif_index
] = 1;
114 oil_if_set(&s_route
->c_oil
, oif_index
, 1);
115 s_route
->c_oil
.oif_creation
[oif_index
] =
116 pim_time_monotonic_sec();
117 ++s_route
->c_oil
.oil_ref_count
;
122 /* If node is null then we reached the end of the list without finding a
125 s_route
= static_route_new(iif_index
, oif_index
, group
, source
);
126 listnode_add(pim
->static_routes
, s_route
);
129 s_route
->c_oil
.pim
= pim
;
131 if (pim_static_mroute_add(&s_route
->c_oil
, __func__
)) {
133 "%s %s: Unable to add static route(iif=%d,oif=%d,group=%pPAs,source=%pPAs)",
134 __FILE__
, __func__
, iif_index
, oif_index
, &group
,
137 /* Need to put s_route back to the way it was */
138 if (original_s_route
) {
139 memcpy(s_route
, original_s_route
,
140 sizeof(struct static_route
));
142 /* we never stored off a copy, so it must have been a
144 listnode_delete(pim
->static_routes
, s_route
);
145 pim_static_route_free(s_route
);
148 if (original_s_route
) {
149 pim_static_route_free(original_s_route
);
155 /* Make sure we free the memory for the route copy if used */
156 if (original_s_route
) {
157 pim_static_route_free(original_s_route
);
160 if (PIM_DEBUG_STATIC
) {
162 "%s: Static route added(iif=%d,oif=%d,group=%pPAs,source=%pPAs)",
163 __func__
, iif_index
, oif_index
, &group
,
170 int pim_static_del(struct pim_instance
*pim
, struct interface
*iif
,
171 struct interface
*oif
, pim_addr group
, pim_addr source
)
173 struct listnode
*node
= NULL
;
174 struct listnode
*nextnode
= NULL
;
175 struct static_route
*s_route
= NULL
;
176 struct pim_interface
*pim_iif
= iif
? iif
->info
: 0;
177 struct pim_interface
*pim_oif
= oif
? oif
->info
: 0;
178 ifindex_t iif_index
= pim_iif
? pim_iif
->mroute_vif_index
: 0;
179 ifindex_t oif_index
= pim_oif
? pim_oif
->mroute_vif_index
: 0;
181 if (!iif_index
|| !oif_index
) {
183 "%s %s: Unable to remove static route: Invalid interface index(iif=%d,oif=%d)",
184 __FILE__
, __func__
, iif_index
, oif_index
);
188 for (ALL_LIST_ELEMENTS(pim
->static_routes
, node
, nextnode
, s_route
)) {
189 if (s_route
->iif
== iif_index
190 && !pim_addr_cmp(s_route
->group
, group
)
191 && !pim_addr_cmp(s_route
->source
, source
)
192 && s_route
->oif_ttls
[oif_index
]) {
193 s_route
->oif_ttls
[oif_index
] = 0;
194 oil_if_set(&s_route
->c_oil
, oif_index
, 0);
195 --s_route
->c_oil
.oil_ref_count
;
197 /* If there are no more outputs then delete the whole
198 * route, otherwise set the route with the new outputs
200 if (s_route
->c_oil
.oil_ref_count
<= 0
201 ? pim_mroute_del(&s_route
->c_oil
, __func__
)
202 : pim_static_mroute_add(&s_route
->c_oil
,
205 "%s %s: Unable to remove static route(iif=%d,oif=%d,group=%pPAs,source=%pPAs)",
206 __FILE__
, __func__
, iif_index
,
207 oif_index
, &group
, &source
);
209 s_route
->oif_ttls
[oif_index
] = 1;
210 oil_if_set(&s_route
->c_oil
, oif_index
, 1);
211 ++s_route
->c_oil
.oil_ref_count
;
216 s_route
->c_oil
.oif_creation
[oif_index
] = 0;
218 if (s_route
->c_oil
.oil_ref_count
<= 0) {
219 listnode_delete(pim
->static_routes
, s_route
);
220 pim_static_route_free(s_route
);
223 if (PIM_DEBUG_STATIC
) {
225 "%s: Static route removed(iif=%d,oif=%d,group=%pPAs,source=%pPAs)",
226 __func__
, iif_index
, oif_index
,
236 "%s %s: Unable to remove static route: Route does not exist(iif=%d,oif=%d,group=%pPAs,source=%pPAs)",
237 __FILE__
, __func__
, iif_index
, oif_index
, &group
,
245 int pim_static_write_mroute(struct pim_instance
*pim
, struct vty
*vty
,
246 struct interface
*ifp
)
248 struct pim_interface
*pim_ifp
= ifp
->info
;
249 struct listnode
*node
;
250 struct static_route
*sroute
;
256 for (ALL_LIST_ELEMENTS_RO(pim
->static_routes
, node
, sroute
)) {
257 if (sroute
->iif
== pim_ifp
->mroute_vif_index
) {
259 for (i
= 0; i
< MAXVIFS
; i
++)
260 if (sroute
->oif_ttls
[i
]) {
261 struct interface
*oifp
=
262 pim_if_find_by_vif_index(pim
,
264 if (pim_addr_is_any(sroute
->source
))
266 " " PIM_AF_NAME
" mroute %s %pPA\n",
267 oifp
->name
, &sroute
->group
);
270 " " PIM_AF_NAME
" mroute %s %pPA %pPA\n",
271 oifp
->name
, &sroute
->group
,