]>
git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_oil.c
3 Copyright (C) 2008 Everton da Silva Marques
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.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING; if not, write to the
17 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
32 #include "pim_iface.h"
35 void pim_channel_oil_free(struct channel_oil
*c_oil
)
37 XFREE(MTYPE_PIM_CHANNEL_OIL
, c_oil
);
41 pim_del_channel_oil (struct channel_oil
*c_oil
)
44 notice that listnode_delete() can't be moved
45 into pim_channel_oil_free() because the later is
46 called by list_delete_all_node()
48 listnode_delete(qpim_channel_oil_list
, c_oil
);
50 pim_channel_oil_free(c_oil
);
53 static struct channel_oil
*
54 pim_add_channel_oil (struct prefix_sg
*sg
,
57 struct channel_oil
*c_oil
;
58 struct interface
*ifp
;
60 ifp
= pim_if_find_by_vif_index(input_vif_index
);
63 zlog_warn("%s: (S,G)=%s could not find input interface for input_vif_index=%d",
65 pim_str_sg_dump (sg
), input_vif_index
);
68 c_oil
= XCALLOC(MTYPE_PIM_CHANNEL_OIL
, sizeof(*c_oil
));
70 zlog_err("PIM XCALLOC(%zu) failure", sizeof(*c_oil
));
74 c_oil
->oil
.mfcc_mcastgrp
= sg
->grp
;
75 c_oil
->oil
.mfcc_origin
= sg
->src
;
76 c_oil
->oil
.mfcc_parent
= input_vif_index
;
77 c_oil
->oil_ref_count
= 1;
80 listnode_add_sort(qpim_channel_oil_list
, c_oil
);
85 static struct channel_oil
*pim_find_channel_oil(struct prefix_sg
*sg
)
87 struct listnode
*node
;
88 struct channel_oil
*c_oil
;
90 for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list
, node
, c_oil
)) {
91 if ((sg
->grp
.s_addr
== c_oil
->oil
.mfcc_mcastgrp
.s_addr
) &&
92 (sg
->src
.s_addr
== c_oil
->oil
.mfcc_origin
.s_addr
))
99 struct channel_oil
*pim_channel_oil_add(struct prefix_sg
*sg
,
102 struct channel_oil
*c_oil
;
104 c_oil
= pim_find_channel_oil(sg
);
106 ++c_oil
->oil_ref_count
;
110 return pim_add_channel_oil(sg
, input_vif_index
);
113 void pim_channel_oil_del(struct channel_oil
*c_oil
)
115 --c_oil
->oil_ref_count
;
117 if (c_oil
->oil_ref_count
< 1) {
118 pim_del_channel_oil(c_oil
);
123 pim_channel_del_oif (struct channel_oil
*channel_oil
,
124 struct interface
*oif
,
127 struct pim_interface
*pim_ifp
;
129 zassert (channel_oil
);
134 if (PIM_DEBUG_MROUTE
)
137 char source_str
[100];
138 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
139 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
140 zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d",
141 __FILE__
, __PRETTY_FUNCTION__
,
142 source_str
, group_str
,
143 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
);
147 * Don't do anything if we've been asked to remove a source
148 * that is not actually on it.
150 if (!(channel_oil
->oif_flags
[pim_ifp
->mroute_vif_index
] & proto_mask
))
152 if (PIM_DEBUG_MROUTE
)
155 char source_str
[100];
156 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
157 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
158 zlog_debug("%s %s: no existing protocol mask %u(%u) for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
159 __FILE__
, __PRETTY_FUNCTION__
,
160 proto_mask
, channel_oil
->oif_flags
[pim_ifp
->mroute_vif_index
],
161 oif
->name
, pim_ifp
->mroute_vif_index
,
162 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
],
163 source_str
, group_str
);
168 channel_oil
->oif_flags
[pim_ifp
->mroute_vif_index
] &= ~proto_mask
;
170 if (channel_oil
->oif_flags
[pim_ifp
->mroute_vif_index
])
172 if (PIM_DEBUG_MROUTE
)
175 char source_str
[100];
176 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
177 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
178 zlog_debug("%s %s: other protocol masks remain for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
179 __FILE__
, __PRETTY_FUNCTION__
,
180 oif
->name
, pim_ifp
->mroute_vif_index
,
181 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
],
182 source_str
, group_str
);
187 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
] = 0;
189 if (pim_mroute_add (channel_oil
)) {
190 if (PIM_DEBUG_MROUTE
)
193 char source_str
[100];
194 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
195 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
196 zlog_debug("%s %s: could not remove output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)",
197 __FILE__
, __PRETTY_FUNCTION__
,
198 oif
->name
, pim_ifp
->mroute_vif_index
,
199 source_str
, group_str
);
208 int pim_channel_add_oif(struct channel_oil
*channel_oil
,
209 struct interface
*oif
,
212 struct pim_interface
*pim_ifp
;
216 * If we've gotten here we've gone bad, but let's
221 zlog_warn ("Attempt to Add OIF for non-existent channel oil");
227 if (PIM_DEBUG_MROUTE
) {
229 char source_str
[100];
230 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
231 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
232 zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d",
233 __FILE__
, __PRETTY_FUNCTION__
,
234 source_str
, group_str
,
235 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
);
238 #ifdef PIM_ENFORCE_LOOPFREE_MFC
240 Prevent creating MFC entry with OIF=IIF.
242 This is a protection against implementation mistakes.
244 PIM protocol implicitely ensures loopfree multicast topology.
246 IGMP must be protected against adding looped MFC entries created
247 by both source and receiver attached to the same interface. See
250 if (pim_ifp
->mroute_vif_index
== channel_oil
->oil
.mfcc_parent
) {
251 if (PIM_DEBUG_MROUTE
)
254 char source_str
[100];
255 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
256 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
257 zlog_debug("%s %s: refusing protocol mask %u request for IIF=OIF=%s (vif_index=%d) for channel (S,G)=(%s,%s)",
258 __FILE__
, __PRETTY_FUNCTION__
,
259 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
,
260 source_str
, group_str
);
266 /* Prevent single protocol from subscribing same interface to
267 channel (S,G) multiple times */
268 if (channel_oil
->oif_flags
[pim_ifp
->mroute_vif_index
] & proto_mask
) {
269 if (PIM_DEBUG_MROUTE
)
272 char source_str
[100];
273 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
274 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
275 zlog_debug("%s %s: existing protocol mask %u requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
276 __FILE__
, __PRETTY_FUNCTION__
,
277 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
,
278 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
],
279 source_str
, group_str
);
284 /* Allow other protocol to request subscription of same interface to
285 channel (S,G) multiple times, by silently ignoring further
287 if (channel_oil
->oif_flags
[pim_ifp
->mroute_vif_index
] & PIM_OIF_FLAG_PROTO_ANY
) {
289 /* Check the OIF really exists before returning, and only log
291 if (channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
] < 1) {
292 if (PIM_DEBUG_MROUTE
)
295 char source_str
[100];
296 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
297 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
298 zlog_debug("%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
299 __FILE__
, __PRETTY_FUNCTION__
,
300 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
,
301 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
],
302 source_str
, group_str
);
309 old_ttl
= channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
];
312 if (PIM_DEBUG_MROUTE
)
315 char source_str
[100];
316 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
317 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
318 zlog_debug("%s %s: interface %s (vif_index=%d) is existing output for channel (S,G)=(%s,%s)",
319 __FILE__
, __PRETTY_FUNCTION__
,
320 oif
->name
, pim_ifp
->mroute_vif_index
,
321 source_str
, group_str
);
326 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
] = PIM_MROUTE_MIN_TTL
;
328 if (pim_mroute_add(channel_oil
)) {
329 if (PIM_DEBUG_MROUTE
)
332 char source_str
[100];
333 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
334 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
335 zlog_debug("%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)",
336 __FILE__
, __PRETTY_FUNCTION__
,
337 oif
->name
, pim_ifp
->mroute_vif_index
,
338 source_str
, group_str
);
341 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
] = old_ttl
;
345 channel_oil
->oif_creation
[pim_ifp
->mroute_vif_index
] = pim_time_monotonic_sec();
346 ++channel_oil
->oil_size
;
347 channel_oil
->oif_flags
[pim_ifp
->mroute_vif_index
] |= proto_mask
;
349 if (PIM_DEBUG_MROUTE
) {
351 char source_str
[100];
352 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
353 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
354 zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE",
355 __FILE__
, __PRETTY_FUNCTION__
,
356 source_str
, group_str
,
357 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
);