]>
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 #ifdef PIM_ENFORCE_LOOPFREE_MFC
168 Prevent creating MFC entry with OIF=IIF.
170 This is a protection against implementation mistakes.
172 PIM protocol implicitely ensures loopfree multicast topology.
174 IGMP must be protected against adding looped MFC entries created
175 by both source and receiver attached to the same interface. See
178 if (pim_ifp
->mroute_vif_index
== channel_oil
->oil
.mfcc_parent
) {
179 if (PIM_DEBUG_MROUTE
)
182 char source_str
[100];
183 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
184 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
185 zlog_debug("%s %s: refusing protocol mask %u request for IIF=OIF=%s (vif_index=%d) for channel (S,G)=(%s,%s)",
186 __FILE__
, __PRETTY_FUNCTION__
,
187 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
,
188 source_str
, group_str
);
194 /* Prevent single protocol from subscribing same interface to
195 channel (S,G) multiple times */
196 if (channel_oil
->oif_flags
[pim_ifp
->mroute_vif_index
] & proto_mask
) {
197 if (PIM_DEBUG_MROUTE
)
200 char source_str
[100];
201 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
202 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
203 zlog_debug("%s %s: existing protocol mask %u requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
204 __FILE__
, __PRETTY_FUNCTION__
,
205 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
,
206 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
],
207 source_str
, group_str
);
212 /* Allow other protocol to request subscription of same interface to
213 channel (S,G) multiple times, by silently ignoring further
215 if (channel_oil
->oif_flags
[pim_ifp
->mroute_vif_index
] & PIM_OIF_FLAG_PROTO_ANY
) {
217 /* Check the OIF really exists before returning, and only log
219 if (channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
] < 1) {
220 if (PIM_DEBUG_MROUTE
)
223 char source_str
[100];
224 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
225 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
226 zlog_debug("%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
227 __FILE__
, __PRETTY_FUNCTION__
,
228 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
,
229 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
],
230 source_str
, group_str
);
237 old_ttl
= channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
];
240 if (PIM_DEBUG_MROUTE
)
243 char source_str
[100];
244 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
245 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
246 zlog_debug("%s %s: interface %s (vif_index=%d) is existing output for channel (S,G)=(%s,%s)",
247 __FILE__
, __PRETTY_FUNCTION__
,
248 oif
->name
, pim_ifp
->mroute_vif_index
,
249 source_str
, group_str
);
254 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
] = PIM_MROUTE_MIN_TTL
;
256 if (pim_mroute_add(channel_oil
)) {
257 if (PIM_DEBUG_MROUTE
)
260 char source_str
[100];
261 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
262 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
263 zlog_debug("%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)",
264 __FILE__
, __PRETTY_FUNCTION__
,
265 oif
->name
, pim_ifp
->mroute_vif_index
,
266 source_str
, group_str
);
269 channel_oil
->oil
.mfcc_ttls
[pim_ifp
->mroute_vif_index
] = old_ttl
;
273 channel_oil
->oif_creation
[pim_ifp
->mroute_vif_index
] = pim_time_monotonic_sec();
274 ++channel_oil
->oil_size
;
275 channel_oil
->oif_flags
[pim_ifp
->mroute_vif_index
] |= proto_mask
;
277 if (PIM_DEBUG_MROUTE
) {
279 char source_str
[100];
280 pim_inet4_dump("<group?>", channel_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
281 pim_inet4_dump("<source?>", channel_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
282 zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE",
283 __FILE__
, __PRETTY_FUNCTION__
,
284 source_str
, group_str
,
285 proto_mask
, oif
->name
, pim_ifp
->mroute_vif_index
);