]>
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;
84 zassert(c_oil
->oil_size
== 0);
89 static struct channel_oil
*pim_add_channel_oil(struct in_addr group_addr
,
90 struct in_addr source_addr
,
93 struct channel_oil
*c_oil
;
95 c_oil
= channel_oil_new(group_addr
, source_addr
, input_vif_index
);
97 zlog_warn("PIM XCALLOC(%zu) failure", sizeof(*c_oil
));
101 listnode_add(qpim_channel_oil_list
, c_oil
);
106 static struct channel_oil
*pim_find_channel_oil(struct in_addr group_addr
,
107 struct in_addr source_addr
)
109 struct listnode
*node
;
110 struct channel_oil
*c_oil
;
112 for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list
, node
, c_oil
)) {
113 if ((group_addr
.s_addr
== c_oil
->oil
.mfcc_mcastgrp
.s_addr
) &&
114 (source_addr
.s_addr
== c_oil
->oil
.mfcc_origin
.s_addr
))
121 struct channel_oil
*pim_channel_oil_add(struct in_addr group_addr
,
122 struct in_addr source_addr
,
125 struct channel_oil
*c_oil
;
127 c_oil
= pim_find_channel_oil(group_addr
, source_addr
);
129 ++c_oil
->oil_ref_count
;
133 return pim_add_channel_oil(group_addr
, source_addr
, input_vif_index
);
136 void pim_channel_oil_del(struct channel_oil
*c_oil
)
138 --c_oil
->oil_ref_count
;
140 if (c_oil
->oil_ref_count
< 1) {
141 pim_channel_oil_delete(c_oil
);
145 int pim_channel_add_oif(struct channel_oil
*channel_oil
,
146 struct interface
*oif
,
149 struct pim_interface
*pim_ifp
;
152 zassert(channel_oil
);
156 if (PIM_DEBUG_MROUTE
) {
158 char source_str
[100];
159 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
160 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
161 zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d",
162 __FILE__
, __PRETTY_FUNCTION__
,
163 source_str
, group_str
,
164 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
);
167 #ifdef PIM_ENFORCE_LOOPFREE_MFC
169 Prevent creating MFC entry with OIF=IIF.
171 This is a protection against implementation mistakes.
173 PIM protocol implicitely ensures loopfree multicast topology.
175 IGMP must be protected against adding looped MFC entries created
176 by both source and receiver attached to the same interface. See
179 if (pim_ifp
->mroute_vif_index
== channel_oil
->oil
.mfcc_parent
) {
180 if (PIM_DEBUG_MROUTE
)
183 char source_str
[100];
184 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
185 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
186 zlog_debug("%s %s: refusing protocol mask %u request for IIF=OIF=%s (vif_index=%d) for channel (S,G)=(%s,%s)",
187 __FILE__
, __PRETTY_FUNCTION__
,
188 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
,
189 source_str
, group_str
);
195 /* Prevent single protocol from subscribing same interface to
196 channel (S,G) multiple times */
197 if (channel_oil
->oif_flags
[pim_ifp
->mroute_vif_index
] & proto_mask
) {
198 if (PIM_DEBUG_MROUTE
)
201 char source_str
[100];
202 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
203 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
204 zlog_debug("%s %s: existing protocol mask %u requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
205 __FILE__
, __PRETTY_FUNCTION__
,
206 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
,
207 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
],
208 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) {
221 if (PIM_DEBUG_MROUTE
)
224 char source_str
[100];
225 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
226 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
227 zlog_debug("%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
228 __FILE__
, __PRETTY_FUNCTION__
,
229 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
,
230 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
],
231 source_str
, group_str
);
238 old_ttl
= channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
];
241 if (PIM_DEBUG_MROUTE
)
244 char source_str
[100];
245 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
246 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
247 zlog_debug("%s %s: interface %s (vif_index=%d) is existing output for channel (S,G)=(%s,%s)",
248 __FILE__
, __PRETTY_FUNCTION__
,
249 oif
->name
, pim_ifp
->mroute_vif_index
,
250 source_str
, group_str
);
255 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
] = PIM_MROUTE_MIN_TTL
;
257 if (pim_mroute_add(channel_oil
)) {
258 if (PIM_DEBUG_MROUTE
)
261 char source_str
[100];
262 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
263 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
264 zlog_debug("%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)",
265 __FILE__
, __PRETTY_FUNCTION__
,
266 oif
->name
, pim_ifp
->mroute_vif_index
,
267 source_str
, group_str
);
270 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
] = old_ttl
;
274 channel_oil
->oif_creation
[pim_ifp
->mroute_vif_index
] = pim_time_monotonic_sec();
275 ++channel_oil
->oil_size
;
276 channel_oil
->oif_flags
[pim_ifp
->mroute_vif_index
] |= proto_mask
;
278 if (PIM_DEBUG_MROUTE
) {
280 char source_str
[100];
281 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
282 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
283 zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE",
284 __FILE__
, __PRETTY_FUNCTION__
,
285 source_str
, group_str
,
286 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
);