]>
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,
20 $QuaggaId: $Format:%an, %ai, %h$ $
33 #include "pim_iface.h"
36 void pim_channel_oil_free(struct channel_oil
*c_oil
)
38 XFREE(MTYPE_PIM_CHANNEL_OIL
, c_oil
);
41 static void pim_channel_oil_delete(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
*channel_oil_new(struct in_addr group_addr
,
54 struct in_addr source_addr
,
57 struct channel_oil
*c_oil
;
58 struct interface
*ifp_in
;
60 ifp_in
= pim_if_find_by_vif_index(input_vif_index
);
65 pim_inet4_dump("<group?>", group_addr
, group_str
, sizeof(group_str
));
66 pim_inet4_dump("<source?>", source_addr
, source_str
, sizeof(source_str
));
67 zlog_warn("%s: (S,G)=(%s,%s) could not find input interface for input_vif_index=%d",
69 source_str
, group_str
, input_vif_index
);
72 c_oil
= XCALLOC(MTYPE_PIM_CHANNEL_OIL
, sizeof(*c_oil
));
74 zlog_err("PIM XCALLOC(%zu) failure", sizeof(*c_oil
));
78 c_oil
->oil
.mfcc_mcastgrp
= group_addr
;
79 c_oil
->oil
.mfcc_origin
= source_addr
;
80 c_oil
->oil
.mfcc_parent
= input_vif_index
;
81 c_oil
->oil_ref_count
= 1;
83 zassert(c_oil
->oil_size
== 0);
88 static struct channel_oil
*pim_add_channel_oil(struct in_addr group_addr
,
89 struct in_addr source_addr
,
92 struct channel_oil
*c_oil
;
94 c_oil
= channel_oil_new(group_addr
, source_addr
, input_vif_index
);
96 zlog_warn("PIM XCALLOC(%zu) failure", sizeof(*c_oil
));
100 listnode_add(qpim_channel_oil_list
, c_oil
);
105 static struct channel_oil
*pim_find_channel_oil(struct in_addr group_addr
,
106 struct in_addr source_addr
)
108 struct listnode
*node
;
109 struct channel_oil
*c_oil
;
111 for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list
, node
, c_oil
)) {
112 if ((group_addr
.s_addr
== c_oil
->oil
.mfcc_mcastgrp
.s_addr
) &&
113 (source_addr
.s_addr
== c_oil
->oil
.mfcc_origin
.s_addr
))
120 struct channel_oil
*pim_channel_oil_add(struct in_addr group_addr
,
121 struct in_addr source_addr
,
124 struct channel_oil
*c_oil
;
126 c_oil
= pim_find_channel_oil(group_addr
, source_addr
);
128 ++c_oil
->oil_ref_count
;
132 return pim_add_channel_oil(group_addr
, source_addr
, input_vif_index
);
135 void pim_channel_oil_del(struct channel_oil
*c_oil
)
137 --c_oil
->oil_ref_count
;
139 if (c_oil
->oil_ref_count
< 1) {
140 pim_channel_oil_delete(c_oil
);
144 int pim_channel_add_oif(struct channel_oil
*channel_oil
,
145 struct interface
*oif
,
148 struct pim_interface
*pim_ifp
;
151 zassert(channel_oil
);
155 if (PIM_DEBUG_MROUTE
) {
157 char source_str
[100];
158 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
159 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
160 zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d",
161 __FILE__
, __PRETTY_FUNCTION__
,
162 source_str
, group_str
,
163 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
);
166 if (pim_ifp
->mroute_vif_index
< 1) {
167 zlog_warn("%s %s: interface %s vif_index=%d < 1",
168 __FILE__
, __PRETTY_FUNCTION__
,
169 oif
->name
, pim_ifp
->mroute_vif_index
);
173 #ifdef PIM_ENFORCE_LOOPFREE_MFC
175 Prevent creating MFC entry with OIF=IIF.
177 This is a protection against implementation mistakes.
179 PIM protocol implicitely ensures loopfree multicast topology.
181 IGMP must be protected against adding looped MFC entries created
182 by both source and receiver attached to the same interface. See
185 if (pim_ifp
->mroute_vif_index
== channel_oil
->oil
.mfcc_parent
) {
187 char source_str
[100];
188 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
189 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
190 zlog_warn("%s %s: refusing protocol mask %u request for IIF=OIF=%s (vif_index=%d) for channel (S,G)=(%s,%s)",
191 __FILE__
, __PRETTY_FUNCTION__
,
192 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
,
193 source_str
, group_str
);
198 /* Prevent single protocol from subscribing same interface to
199 channel (S,G) multiple times */
200 if (channel_oil
->oif_flags
[pim_ifp
->mroute_vif_index
] & proto_mask
) {
202 char source_str
[100];
203 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
204 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
205 zlog_warn("%s %s: existing protocol mask %u requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
206 __FILE__
, __PRETTY_FUNCTION__
,
207 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
,
208 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
],
209 source_str
, group_str
);
213 /* Allow other protocol to request subscription of same interface to
214 channel (S,G) multiple times, by silently ignoring further
216 if (channel_oil
->oif_flags
[pim_ifp
->mroute_vif_index
] & PIM_OIF_FLAG_PROTO_ANY
) {
218 /* Check the OIF really exists before returning, and only log
220 if (channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
] < 1) {
222 char source_str
[100];
223 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
224 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
225 zlog_warn("%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
226 __FILE__
, __PRETTY_FUNCTION__
,
227 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
,
228 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
],
229 source_str
, group_str
);
235 old_ttl
= channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
];
239 char source_str
[100];
240 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
241 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
242 zlog_warn("%s %s: interface %s (vif_index=%d) is existing output for channel (S,G)=(%s,%s)",
243 __FILE__
, __PRETTY_FUNCTION__
,
244 oif
->name
, pim_ifp
->mroute_vif_index
,
245 source_str
, group_str
);
249 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
] = PIM_MROUTE_MIN_TTL
;
251 if (pim_mroute_add(&channel_oil
->oil
)) {
253 char source_str
[100];
254 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
255 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
256 zlog_warn("%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)",
257 __FILE__
, __PRETTY_FUNCTION__
,
258 oif
->name
, pim_ifp
->mroute_vif_index
,
259 source_str
, group_str
);
261 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
] = old_ttl
;
265 channel_oil
->oif_creation
[pim_ifp
->mroute_vif_index
] = pim_time_monotonic_sec();
266 ++channel_oil
->oil_size
;
267 channel_oil
->oif_flags
[pim_ifp
->mroute_vif_index
] |= proto_mask
;
269 if (PIM_DEBUG_MROUTE
) {
271 char source_str
[100];
272 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
273 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
274 zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE",
275 __FILE__
, __PRETTY_FUNCTION__
,
276 source_str
, group_str
,
277 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
);