1/* 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 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, 18 MA 02110-1301 USA 19 20 $QuaggaId: $Format:%an, %ai, %h$ $ 21*/ 22 23#include <zebra.h> 24 25#include "log.h" 26#include "memory.h" 27#include "linklist.h" 28 29#include "pimd.h" 30#include "pim_oil.h" 31#include "pim_str.h" 32#include "pim_iface.h" 33 34void pim_channel_oil_free(struct channel_oil *c_oil) 35{ 36 XFREE(MTYPE_PIM_CHANNEL_OIL, c_oil); 37} 38 39static void pim_channel_oil_delete(struct channel_oil *c_oil) 40{ 41 /* 42 notice that listnode_delete() can't be moved 43 into pim_channel_oil_free() because the later is 44 called by list_delete_all_node() 45 */ 46 listnode_delete(qpim_channel_oil_list, c_oil); 47 48 pim_channel_oil_free(c_oil); 49} 50 51static struct channel_oil *channel_oil_new(struct in_addr group_addr, 52 struct in_addr source_addr, 53 int input_vif_index) 54{ 55 struct channel_oil *c_oil; 56 struct interface *ifp_in; 57 58 ifp_in = pim_if_find_by_vif_index(input_vif_index); 59 if (!ifp_in) { 60 /* warning only */ 61 char group_str[100]; 62 char source_str[100]; 63 pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str)); 64 pim_inet4_dump("<source?>", source_addr, source_str, sizeof(source_str)); 65 zlog_warn("%s: (S,G)=(%s,%s) could not find input interface for input_vif_index=%d", 66 __PRETTY_FUNCTION__, 67 source_str, group_str, input_vif_index); 68 } 69 70 c_oil = XCALLOC(MTYPE_PIM_CHANNEL_OIL, sizeof(*c_oil)); 71 if (!c_oil) { 72 zlog_err("PIM XCALLOC(%zu) failure", sizeof(*c_oil)); 73 return 0; 74 } 75 76 c_oil->oil.mfcc_mcastgrp = group_addr; 77 c_oil->oil.mfcc_origin = source_addr; 78 c_oil->oil.mfcc_parent = input_vif_index; 79 c_oil->oil_ref_count = 1; 80 81 zassert(c_oil->oil_size == 0); 82 83 return c_oil; 84} 85 86static struct channel_oil *pim_add_channel_oil(struct in_addr group_addr, 87 struct in_addr source_addr, 88 int input_vif_index) 89{ 90 struct channel_oil *c_oil; 91 92 c_oil = channel_oil_new(group_addr, source_addr, input_vif_index); 93 if (!c_oil) { 94 zlog_warn("PIM XCALLOC(%zu) failure", sizeof(*c_oil)); 95 return 0; 96 } 97 98 listnode_add(qpim_channel_oil_list, c_oil); 99 100 return c_oil; 101} 102 103static struct channel_oil *pim_find_channel_oil(struct in_addr group_addr, 104 struct in_addr source_addr) 105{ 106 struct listnode *node; 107 struct channel_oil *c_oil; 108 109 for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) { 110 if ((group_addr.s_addr == c_oil->oil.mfcc_mcastgrp.s_addr) && 111 (source_addr.s_addr == c_oil->oil.mfcc_origin.s_addr)) 112 return c_oil; 113 } 114 115 return 0; 116} 117 118struct channel_oil *pim_channel_oil_add(struct in_addr group_addr, 119 struct in_addr source_addr, 120 int input_vif_index) 121{ 122 struct channel_oil *c_oil; 123 124 c_oil = pim_find_channel_oil(group_addr, source_addr); 125 if (c_oil) { 126 ++c_oil->oil_ref_count; 127 return c_oil; 128 } 129 130 return pim_add_channel_oil(group_addr, source_addr, input_vif_index); 131} 132 133void pim_channel_oil_del(struct channel_oil *c_oil) 134{ 135 --c_oil->oil_ref_count; 136 137 if (c_oil->oil_ref_count < 1) { 138 pim_channel_oil_delete(c_oil); 139 } 140} 141