]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_oil.c
pimd: There is nothing to do with a WRVIFWHOLE for iifp of pimreg
[mirror_frr.git] / pimd / pim_oil.c
CommitLineData
12e41d03 1/*
896014f4
DL
2 * PIM for Quagga
3 * Copyright (C) 2008 Everton da Silva Marques
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 *
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
18 */
12e41d03
DL
19
20#include <zebra.h>
21
22#include "log.h"
23#include "memory.h"
24#include "linklist.h"
744d91b3 25#include "if.h"
040d86ad
DS
26#include "hash.h"
27#include "jhash.h"
12e41d03
DL
28
29#include "pimd.h"
30#include "pim_oil.h"
31#include "pim_str.h"
32#include "pim_iface.h"
37653d4f 33#include "pim_time.h"
5923b739 34#include "pim_vxlan.h"
12e41d03 35
611925dc
DS
36// struct list *pim_channel_oil_list = NULL;
37// struct hash *pim_channel_oil_hash = NULL;
040d86ad 38
a155fed5
AK
39static void pim_channel_update_mute(struct channel_oil *c_oil);
40
d62a17ae 41char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)
781a1745 42{
a2dc7057 43 char *out;
9bf5f19c 44 struct interface *ifp;
d62a17ae 45 struct prefix_sg sg;
46 int i;
47
d62a17ae 48 sg.src = c_oil->oil.mfcc_origin;
49 sg.grp = c_oil->oil.mfcc_mcastgrp;
9bf5f19c
DS
50 ifp = pim_if_find_by_vif_index(c_oil->pim, c_oil->oil.mfcc_parent);
51 snprintf(buf, size, "%s IIF: %s, OIFS: ", pim_str_sg_dump(&sg),
52 ifp ? ifp->name : "(?)");
d62a17ae 53
a2dc7057 54 out = buf + strlen(buf);
d62a17ae 55 for (i = 0; i < MAXVIFS; i++) {
56 if (c_oil->oil.mfcc_ttls[i] != 0) {
9bf5f19c
DS
57 ifp = pim_if_find_by_vif_index(c_oil->pim, i);
58 snprintf(out, buf + size - out, "%s ",
59 ifp ? ifp->name : "(?)");
a2dc7057 60 out += strlen(out);
d62a17ae 61 }
62 }
63
64 return buf;
781a1745
DS
65}
66
7315ecda
DS
67int pim_channel_oil_compare(const struct channel_oil *c1,
68 const struct channel_oil *c2)
040d86ad 69{
d62a17ae 70 if (ntohl(c1->oil.mfcc_mcastgrp.s_addr)
71 < ntohl(c2->oil.mfcc_mcastgrp.s_addr))
72 return -1;
040d86ad 73
d62a17ae 74 if (ntohl(c1->oil.mfcc_mcastgrp.s_addr)
75 > ntohl(c2->oil.mfcc_mcastgrp.s_addr))
76 return 1;
040d86ad 77
d62a17ae 78 if (ntohl(c1->oil.mfcc_origin.s_addr)
79 < ntohl(c2->oil.mfcc_origin.s_addr))
80 return -1;
040d86ad 81
d62a17ae 82 if (ntohl(c1->oil.mfcc_origin.s_addr)
83 > ntohl(c2->oil.mfcc_origin.s_addr))
84 return 1;
040d86ad 85
d62a17ae 86 return 0;
040d86ad
DS
87}
88
611925dc 89void pim_oil_init(struct pim_instance *pim)
040d86ad 90{
7315ecda 91 rb_pim_oil_init(&pim->channel_oil_head);
040d86ad
DS
92}
93
611925dc 94void pim_oil_terminate(struct pim_instance *pim)
040d86ad 95{
7315ecda
DS
96 struct channel_oil *c_oil;
97
98 while ((c_oil = rb_pim_oil_pop(&pim->channel_oil_head)))
99 pim_channel_oil_free(c_oil);
040d86ad 100
7315ecda 101 rb_pim_oil_fini(&pim->channel_oil_head);
040d86ad
DS
102}
103
12e41d03
DL
104void pim_channel_oil_free(struct channel_oil *c_oil)
105{
d62a17ae 106 XFREE(MTYPE_PIM_CHANNEL_OIL, c_oil);
12e41d03
DL
107}
108
4d9ad5dc
MS
109struct channel_oil *pim_find_channel_oil(struct pim_instance *pim,
110 struct prefix_sg *sg)
12e41d03 111{
d62a17ae 112 struct channel_oil *c_oil = NULL;
113 struct channel_oil lookup;
d270b216 114
d62a17ae 115 lookup.oil.mfcc_mcastgrp = sg->grp;
116 lookup.oil.mfcc_origin = sg->src;
d270b216 117
7315ecda 118 c_oil = rb_pim_oil_find(&pim->channel_oil_head, &lookup);
d270b216 119
d62a17ae 120 return c_oil;
12e41d03
DL
121}
122
611925dc
DS
123struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
124 struct prefix_sg *sg,
7984af18 125 const char *name)
12e41d03 126{
d62a17ae 127 struct channel_oil *c_oil;
d62a17ae 128
611925dc 129 c_oil = pim_find_channel_oil(pim, sg);
d62a17ae 130 if (c_oil) {
d62a17ae 131 ++c_oil->oil_ref_count;
a155fed5
AK
132
133 if (!c_oil->up) {
134 /* channel might be present prior to upstream */
135 c_oil->up = pim_upstream_find(
136 pim, sg);
137 /* if the upstream entry is being anchored to an
138 * already existing channel OIL we need to re-evaluate
139 * the "Mute" state on AA OIFs
140 */
141 pim_channel_update_mute(c_oil);
142 }
8a3e7e9e 143
7984af18
AK
144 /* check if the IIF has changed
145 * XXX - is this really needed
146 */
147 pim_upstream_mroute_iif_update(c_oil, __func__);
148
8a3e7e9e
DS
149 if (PIM_DEBUG_MROUTE)
150 zlog_debug(
151 "%s(%s): Existing oil for %pSG4 Ref Count: %d (Post Increment)",
15569c58 152 __func__, name, sg, c_oil->oil_ref_count);
d62a17ae 153 return c_oil;
154 }
155
d62a17ae 156 c_oil = XCALLOC(MTYPE_PIM_CHANNEL_OIL, sizeof(*c_oil));
d62a17ae 157
158 c_oil->oil.mfcc_mcastgrp = sg->grp;
159 c_oil->oil.mfcc_origin = sg->src;
d62a17ae 160
7984af18 161 c_oil->oil.mfcc_parent = MAXVIFS;
d62a17ae 162 c_oil->oil_ref_count = 1;
163 c_oil->installed = 0;
611925dc
DS
164 c_oil->up = pim_upstream_find(pim, sg);
165 c_oil->pim = pim;
d62a17ae 166
7315ecda 167 rb_pim_oil_add(&pim->channel_oil_head, c_oil);
d62a17ae 168
8a3e7e9e 169 if (PIM_DEBUG_MROUTE)
7984af18
AK
170 zlog_debug("%s(%s): c_oil %s add",
171 __func__, name, pim_str_sg_dump(sg));
172
d62a17ae 173 return c_oil;
12e41d03
DL
174}
175
a155fed5
AK
176struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
177 const char *name)
12e41d03 178{
8a3e7e9e
DS
179 if (PIM_DEBUG_MROUTE) {
180 struct prefix_sg sg = {.src = c_oil->oil.mfcc_mcastgrp,
181 .grp = c_oil->oil.mfcc_origin};
182
183 zlog_debug(
184 "%s(%s): Del oil for %pSG4, Ref Count: %d (Predecrement)",
15569c58 185 __func__, name, &sg, c_oil->oil_ref_count);
8a3e7e9e 186 }
d62a17ae 187 --c_oil->oil_ref_count;
188
189 if (c_oil->oil_ref_count < 1) {
190 /*
191 * notice that listnode_delete() can't be moved
192 * into pim_channel_oil_free() because the later is
193 * called by list_delete_all_node()
194 */
195 c_oil->up = NULL;
7315ecda 196 rb_pim_oil_del(&c_oil->pim->channel_oil_head, c_oil);
d62a17ae 197
198 pim_channel_oil_free(c_oil);
a155fed5
AK
199 return NULL;
200 }
201
202 return c_oil;
203}
204
205void pim_channel_oil_upstream_deref(struct channel_oil *c_oil)
206{
207 /* The upstream entry associated with a channel_oil is abt to be
208 * deleted. If the channel_oil is kept around because of other
209 * references we need to remove upstream based states out of it.
210 */
211 c_oil = pim_channel_oil_del(c_oil, __func__);
212 if (c_oil) {
213 /* note: here we assume that c_oil->up has already been
214 * cleared
215 */
216 pim_channel_update_mute(c_oil);
d62a17ae 217 }
12e41d03 218}
1865a44a 219
d62a17ae 220int pim_channel_del_oif(struct channel_oil *channel_oil, struct interface *oif,
1b249e70 221 uint32_t proto_mask, const char *caller)
887fa014 222{
d62a17ae 223 struct pim_interface *pim_ifp;
224
225 zassert(channel_oil);
226 zassert(oif);
227
228 pim_ifp = oif->info;
229
230 /*
231 * Don't do anything if we've been asked to remove a source
232 * that is not actually on it.
233 */
234 if (!(channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask)) {
235 if (PIM_DEBUG_MROUTE) {
236 char group_str[INET_ADDRSTRLEN];
237 char source_str[INET_ADDRSTRLEN];
238 pim_inet4_dump("<group?>",
239 channel_oil->oil.mfcc_mcastgrp,
240 group_str, sizeof(group_str));
241 pim_inet4_dump("<source?>",
242 channel_oil->oil.mfcc_origin, source_str,
243 sizeof(source_str));
244 zlog_debug(
245 "%s %s: no existing protocol mask %u(%u) for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
15569c58 246 __FILE__, __func__, proto_mask,
d62a17ae 247 channel_oil
248 ->oif_flags[pim_ifp->mroute_vif_index],
249 oif->name, pim_ifp->mroute_vif_index,
250 channel_oil->oil
251 .mfcc_ttls[pim_ifp->mroute_vif_index],
252 source_str, group_str);
253 }
254 return 0;
255 }
256
257 channel_oil->oif_flags[pim_ifp->mroute_vif_index] &= ~proto_mask;
258
5923b739
AK
259 if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] &
260 PIM_OIF_FLAG_PROTO_ANY) {
d62a17ae 261 if (PIM_DEBUG_MROUTE) {
262 char group_str[INET_ADDRSTRLEN];
263 char source_str[INET_ADDRSTRLEN];
264 pim_inet4_dump("<group?>",
265 channel_oil->oil.mfcc_mcastgrp,
266 group_str, sizeof(group_str));
267 pim_inet4_dump("<source?>",
268 channel_oil->oil.mfcc_origin, source_str,
269 sizeof(source_str));
270 zlog_debug(
271 "%s %s: other protocol masks remain for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
15569c58 272 __FILE__, __func__, oif->name,
d62a17ae 273 pim_ifp->mroute_vif_index,
274 channel_oil->oil
275 .mfcc_ttls[pim_ifp->mroute_vif_index],
276 source_str, group_str);
277 }
278 return 0;
279 }
280
281 channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0;
5923b739
AK
282 /* clear mute; will be re-evaluated when the OIF becomes valid again */
283 channel_oil->oif_flags[pim_ifp->mroute_vif_index] &= ~PIM_OIF_FLAG_MUTE;
d62a17ae 284
15569c58 285 if (pim_upstream_mroute_add(channel_oil, __func__)) {
d62a17ae 286 if (PIM_DEBUG_MROUTE) {
287 char group_str[INET_ADDRSTRLEN];
288 char source_str[INET_ADDRSTRLEN];
289 pim_inet4_dump("<group?>",
290 channel_oil->oil.mfcc_mcastgrp,
291 group_str, sizeof(group_str));
292 pim_inet4_dump("<source?>",
293 channel_oil->oil.mfcc_origin, source_str,
294 sizeof(source_str));
295 zlog_debug(
296 "%s %s: could not remove output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)",
15569c58 297 __FILE__, __func__, oif->name,
d62a17ae 298 pim_ifp->mroute_vif_index, source_str,
299 group_str);
300 }
301 return -1;
887fa014 302 }
d62a17ae 303
304 --channel_oil->oil_size;
305
306 if (PIM_DEBUG_MROUTE) {
307 char group_str[INET_ADDRSTRLEN];
308 char source_str[INET_ADDRSTRLEN];
309 pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp,
310 group_str, sizeof(group_str));
311 pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin,
312 source_str, sizeof(source_str));
313 zlog_debug(
1b249e70 314 "%s(%s): (S,G)=(%s,%s): proto_mask=%u IIF:%d OIF=%s vif_index=%d",
15569c58
DA
315 __func__, caller, source_str, group_str, proto_mask,
316 channel_oil->oil.mfcc_parent, oif->name,
d62a17ae 317 pim_ifp->mroute_vif_index);
887fa014 318 }
d62a17ae 319
320 return 0;
887fa014
DS
321}
322
1537a668
AK
323void pim_channel_del_inherited_oif(struct channel_oil *c_oil,
324 struct interface *oif, const char *caller)
325{
326 struct pim_upstream *up = c_oil->up;
327
328 pim_channel_del_oif(c_oil, oif, PIM_OIF_FLAG_PROTO_STAR,
329 caller);
330
331 /* if an inherited OIF is being removed join-desired can change
332 * if the inherited OIL is now empty and KAT is running
333 */
334 if (up && up->sg.src.s_addr != INADDR_ANY &&
335 pim_upstream_empty_inherited_olist(up))
336 pim_upstream_update_join_desired(up->pim, up);
337}
887fa014 338
5923b739
AK
339static bool pim_channel_eval_oif_mute(struct channel_oil *c_oil,
340 struct pim_interface *pim_ifp)
341{
342 struct pim_interface *pim_reg_ifp;
343 struct pim_interface *vxlan_ifp;
344 bool do_mute = false;
345 struct pim_instance *pim = c_oil->pim;
346
347 if (!c_oil->up)
348 return do_mute;
349
350 pim_reg_ifp = pim->regiface->info;
351 if (pim_ifp == pim_reg_ifp) {
352 /* suppress pimreg in the OIL if the mroute is not supposed to
353 * trigger register encapsulated data
354 */
355 if (PIM_UPSTREAM_FLAG_TEST_NO_PIMREG_DATA(c_oil->up->flags))
356 do_mute = true;
357
358 return do_mute;
359 }
360
361 vxlan_ifp = pim_vxlan_get_term_ifp(pim);
362 if (pim_ifp == vxlan_ifp) {
363 /* 1. vxlan termination device must never be added to the
364 * origination mroute (and that can actually happen because
365 * of XG inheritance from the termination mroute) otherwise
366 * traffic will end up looping.
367 * PS: This check has also been extended to non-orig mroutes
368 * that have a local SIP as such mroutes can move back and
369 * forth between orig<=>non-orig type.
370 * 2. vxlan termination device should be removed from the non-DF
371 * to prevent duplicates to the overlay rxer
372 */
373 if (PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN_ORIG(c_oil->up->flags) ||
374 PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(c_oil->up->flags) ||
375 pim_vxlan_is_local_sip(c_oil->up))
376 do_mute = true;
377
378 return do_mute;
379 }
380
381 return do_mute;
382}
383
384void pim_channel_update_oif_mute(struct channel_oil *c_oil,
385 struct pim_interface *pim_ifp)
386{
387 bool old_mute;
388 bool new_mute;
389
390 /* If pim_ifp is not a part of the OIL there is nothing to do */
391 if (!c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index])
392 return;
393
394 old_mute = !!(c_oil->oif_flags[pim_ifp->mroute_vif_index] &
395 PIM_OIF_FLAG_MUTE);
396 new_mute = pim_channel_eval_oif_mute(c_oil, pim_ifp);
397 if (old_mute == new_mute)
398 return;
399
400 if (new_mute)
401 c_oil->oif_flags[pim_ifp->mroute_vif_index] |=
402 PIM_OIF_FLAG_MUTE;
403 else
404 c_oil->oif_flags[pim_ifp->mroute_vif_index] &=
405 ~PIM_OIF_FLAG_MUTE;
406
15569c58 407 pim_upstream_mroute_add(c_oil, __func__);
5923b739
AK
408}
409
a155fed5
AK
410/* pim_upstream has been set or cleared on the c_oil. re-eval mute state
411 * on all existing OIFs
412 */
413static void pim_channel_update_mute(struct channel_oil *c_oil)
414{
415 struct pim_interface *pim_reg_ifp;
416 struct pim_interface *vxlan_ifp;
417
418 pim_reg_ifp = c_oil->pim->regiface->info;
419 if (pim_reg_ifp)
420 pim_channel_update_oif_mute(c_oil, pim_reg_ifp);
421 vxlan_ifp = pim_vxlan_get_term_ifp(c_oil->pim);
422 if (vxlan_ifp)
423 pim_channel_update_oif_mute(c_oil, vxlan_ifp);
424}
425
d62a17ae 426int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif,
1b249e70 427 uint32_t proto_mask, const char *caller)
1865a44a 428{
d62a17ae 429 struct pim_interface *pim_ifp;
430 int old_ttl;
431
432 /*
433 * If we've gotten here we've gone bad, but let's
434 * not take down pim
435 */
436 if (!channel_oil) {
437 zlog_warn("Attempt to Add OIF for non-existent channel oil");
438 return -1;
439 }
1865a44a 440
d62a17ae 441 pim_ifp = oif->info;
1865a44a 442
d62a17ae 443 /* Prevent single protocol from subscribing same interface to
444 channel (S,G) multiple times */
445 if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask) {
446 if (PIM_DEBUG_MROUTE) {
447 char group_str[INET_ADDRSTRLEN];
448 char source_str[INET_ADDRSTRLEN];
449 pim_inet4_dump("<group?>",
450 channel_oil->oil.mfcc_mcastgrp,
451 group_str, sizeof(group_str));
452 pim_inet4_dump("<source?>",
453 channel_oil->oil.mfcc_origin, source_str,
454 sizeof(source_str));
455 zlog_debug(
456 "%s %s: existing protocol mask %u requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
15569c58
DA
457 __FILE__, __func__, proto_mask, oif->name,
458 pim_ifp->mroute_vif_index,
d62a17ae 459 channel_oil->oil
460 .mfcc_ttls[pim_ifp->mroute_vif_index],
461 source_str, group_str);
462 }
463 return -3;
464 }
465
466 /* Allow other protocol to request subscription of same interface to
467 * channel (S,G), we need to note this information
468 */
469 if (channel_oil->oif_flags[pim_ifp->mroute_vif_index]
470 & PIM_OIF_FLAG_PROTO_ANY) {
471
d23756e9
SP
472 /* Updating time here is not required as this time has to
473 * indicate when the interface is added
474 */
475
d62a17ae 476 channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask;
477 /* Check the OIF really exists before returning, and only log
478 warning otherwise */
479 if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) {
480 {
481 char group_str[INET_ADDRSTRLEN];
482 char source_str[INET_ADDRSTRLEN];
483 pim_inet4_dump("<group?>",
484 channel_oil->oil.mfcc_mcastgrp,
485 group_str, sizeof(group_str));
486 pim_inet4_dump("<source?>",
487 channel_oil->oil.mfcc_origin,
488 source_str, sizeof(source_str));
489 zlog_warn(
490 "%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
15569c58
DA
491 __FILE__, __func__, proto_mask,
492 oif->name, pim_ifp->mroute_vif_index,
d62a17ae 493 channel_oil->oil.mfcc_ttls
494 [pim_ifp->mroute_vif_index],
495 source_str, group_str);
496 }
497 }
498
499 return 0;
500 }
501
502 old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index];
503
504 if (old_ttl > 0) {
505 if (PIM_DEBUG_MROUTE) {
506 char group_str[INET_ADDRSTRLEN];
507 char source_str[INET_ADDRSTRLEN];
508 pim_inet4_dump("<group?>",
509 channel_oil->oil.mfcc_mcastgrp,
510 group_str, sizeof(group_str));
511 pim_inet4_dump("<source?>",
512 channel_oil->oil.mfcc_origin, source_str,
513 sizeof(source_str));
514 zlog_debug(
515 "%s %s: interface %s (vif_index=%d) is existing output for channel (S,G)=(%s,%s)",
15569c58 516 __FILE__, __func__, oif->name,
d62a17ae 517 pim_ifp->mroute_vif_index, source_str,
518 group_str);
519 }
520 return -4;
521 }
522
523 channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] =
524 PIM_MROUTE_MIN_TTL;
525
5923b739
AK
526 /* Some OIFs are held in a muted state i.e. the PIM state machine
527 * decided to include the OIF but additional status check such as
528 * MLAG DF role prevent it from being activated for traffic
529 * forwarding.
530 */
531 if (pim_channel_eval_oif_mute(channel_oil, pim_ifp))
532 channel_oil->oif_flags[pim_ifp->mroute_vif_index] |=
533 PIM_OIF_FLAG_MUTE;
534 else
535 channel_oil->oif_flags[pim_ifp->mroute_vif_index] &=
536 ~PIM_OIF_FLAG_MUTE;
537
47e3ce59
SP
538 /* channel_oil->oil.mfcc_parent != MAXVIFS indicate this entry is not
539 * valid to get installed in kernel.
c3156184 540 */
47e3ce59 541 if (channel_oil->oil.mfcc_parent != MAXVIFS) {
15569c58 542 if (pim_upstream_mroute_add(channel_oil, __func__)) {
c3156184
SP
543 if (PIM_DEBUG_MROUTE) {
544 char group_str[INET_ADDRSTRLEN];
545 char source_str[INET_ADDRSTRLEN];
546 pim_inet4_dump("<group?>",
547 channel_oil->oil.mfcc_mcastgrp,
548 group_str, sizeof(group_str));
549 pim_inet4_dump("<source?>",
550 channel_oil->oil.mfcc_origin, source_str,
551 sizeof(source_str));
552 zlog_debug(
15569c58
DA
553 "%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)",
554 __FILE__, __func__, oif->name,
555 pim_ifp->mroute_vif_index, source_str,
556 group_str);
c3156184 557 }
d62a17ae 558
c3156184
SP
559 channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]
560 = old_ttl;
561 return -5;
562 }
d62a17ae 563 }
564
565 channel_oil->oif_creation[pim_ifp->mroute_vif_index] =
566 pim_time_monotonic_sec();
567 ++channel_oil->oil_size;
568 channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask;
569
570 if (PIM_DEBUG_MROUTE) {
571 char group_str[INET_ADDRSTRLEN];
572 char source_str[INET_ADDRSTRLEN];
573 pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp,
574 group_str, sizeof(group_str));
575 pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin,
576 source_str, sizeof(source_str));
577 zlog_debug(
1b249e70 578 "%s(%s): (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE",
15569c58
DA
579 __func__, caller, source_str, group_str, proto_mask,
580 oif->name, pim_ifp->mroute_vif_index);
d62a17ae 581 }
582
583 return 0;
1865a44a 584}
ce0ddb4e 585
d62a17ae 586int pim_channel_oil_empty(struct channel_oil *c_oil)
ce0ddb4e 587{
d86632fb 588 static struct mfcctl null_oil;
d62a17ae 589
590 if (!c_oil)
591 return 1;
d62a17ae 592
9e558d9a
AK
593 /* exclude pimreg from the OIL when checking if the inherited_oil is
594 * non-NULL.
595 * pimreg device (in all vrfs) uses a vifi of
596 * 0 (PIM_OIF_PIM_REGISTER_VIF) so we simply mfcc_ttls[0] */
597 return !memcmp(&c_oil->oil.mfcc_ttls[1], &null_oil.mfcc_ttls[1],
598 sizeof(null_oil.mfcc_ttls) - sizeof(null_oil.mfcc_ttls[0]));
ce0ddb4e 599}