qpim_mroute_oif_highest_vif_index,
VTY_NEWLINE);
vty_out(vty, "Maximum highest VifIndex: %d%s",
- MAXVIFS - 2,
+ PIM_MAX_USABLE_VIFS,
VTY_NEWLINE);
vty_out(vty, "%s", VTY_NEWLINE);
mc.mfcc_origin = msg->im_src;
mc.mfcc_mcastgrp = msg->im_dst;
mc.mfcc_parent = ifp->ifindex;
- mc.mfcc_ttls[MAXVIFS-1] = 1;
+ mc.mfcc_ttls[PIM_OIF_PIM_REGISTER_VIF] = 1;
pim_mroute_add(&mc);
return 0;
}
}
qpim_mroute_socket_fd = fd;
- pim_mroute_add_vif(MAXVIFS-1, pimreg, VIFF_REGISTER);
+ pim_mroute_add_vif(PIM_OIF_PIM_REGISTER_VIF, pimreg, VIFF_REGISTER);
qpim_mroute_socket_creation = pim_time_monotonic_sec();
mroute_read_on();
*/
#ifndef MAXVIFS
-#define MAXVIFS (32)
+#define MAXVIFS (256)
#endif
#ifndef SIOCGETVIFCNT
pim_channel_oil_delete(c_oil);
}
}
+
+int pim_channel_add_oif(struct channel_oil *channel_oil,
+ struct interface *oif,
+ uint32_t proto_mask)
+{
+ struct pim_interface *pim_ifp;
+ int old_ttl;
+
+ zassert(channel_oil);
+
+ pim_ifp = oif->info;
+
+ if (PIM_DEBUG_MROUTE) {
+ char group_str[100];
+ char source_str[100];
+ pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
+ pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
+ zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d",
+ __FILE__, __PRETTY_FUNCTION__,
+ source_str, group_str,
+ proto_mask, oif->name, pim_ifp->mroute_vif_index);
+ }
+
+ if (pim_ifp->mroute_vif_index < 1) {
+ zlog_warn("%s %s: interface %s vif_index=%d < 1",
+ __FILE__, __PRETTY_FUNCTION__,
+ oif->name, pim_ifp->mroute_vif_index);
+ return -1;
+ }
+
+#ifdef PIM_ENFORCE_LOOPFREE_MFC
+ /*
+ Prevent creating MFC entry with OIF=IIF.
+
+ This is a protection against implementation mistakes.
+
+ PIM protocol implicitely ensures loopfree multicast topology.
+
+ IGMP must be protected against adding looped MFC entries created
+ by both source and receiver attached to the same interface. See
+ TODO T22.
+ */
+ if (pim_ifp->mroute_vif_index == channel_oil->oil.mfcc_parent) {
+ char group_str[100];
+ char source_str[100];
+ pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
+ pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
+ zlog_warn("%s %s: refusing protocol mask %u request for IIF=OIF=%s (vif_index=%d) for channel (S,G)=(%s,%s)",
+ __FILE__, __PRETTY_FUNCTION__,
+ proto_mask, oif->name, pim_ifp->mroute_vif_index,
+ source_str, group_str);
+ return -2;
+ }
+#endif
+
+ zassert(qpim_mroute_oif_highest_vif_index < MAXVIFS);
+ zassert(pim_ifp->mroute_vif_index <= qpim_mroute_oif_highest_vif_index);
+
+ /* Prevent single protocol from subscribing same interface to
+ channel (S,G) multiple times */
+ if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask) {
+ char group_str[100];
+ char source_str[100];
+ pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
+ pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
+ zlog_warn("%s %s: existing protocol mask %u requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
+ __FILE__, __PRETTY_FUNCTION__,
+ proto_mask, oif->name, pim_ifp->mroute_vif_index,
+ channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index],
+ source_str, group_str);
+ return -3;
+ }
+
+ /* Allow other protocol to request subscription of same interface to
+ channel (S,G) multiple times, by silently ignoring further
+ requests */
+ if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & PIM_OIF_FLAG_PROTO_ANY) {
+
+ /* Check the OIF really exists before returning, and only log
+ warning otherwise */
+ if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) {
+ char group_str[100];
+ char source_str[100];
+ pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
+ pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
+ zlog_warn("%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
+ __FILE__, __PRETTY_FUNCTION__,
+ proto_mask, oif->name, pim_ifp->mroute_vif_index,
+ channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index],
+ source_str, group_str);
+ }
+
+ return 0;
+ }
+
+ old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index];
+
+ if (old_ttl > 0) {
+ char group_str[100];
+ char source_str[100];
+ pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
+ pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
+ zlog_warn("%s %s: interface %s (vif_index=%d) is existing output for channel (S,G)=(%s,%s)",
+ __FILE__, __PRETTY_FUNCTION__,
+ oif->name, pim_ifp->mroute_vif_index,
+ source_str, group_str);
+ return -4;
+ }
+
+ channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = PIM_MROUTE_MIN_TTL;
+
+ if (pim_mroute_add(&channel_oil->oil)) {
+ char group_str[100];
+ char source_str[100];
+ pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
+ pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
+ zlog_warn("%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)",
+ __FILE__, __PRETTY_FUNCTION__,
+ oif->name, pim_ifp->mroute_vif_index,
+ source_str, group_str);
+
+ channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = old_ttl;
+ return -5;
+ }
+
+ channel_oil->oif_creation[pim_ifp->mroute_vif_index] = pim_time_monotonic_sec();
+ ++channel_oil->oil_size;
+ channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask;
+
+ if (PIM_DEBUG_MROUTE) {
+ char group_str[100];
+ char source_str[100];
+ pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
+ pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
+ zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE",
+ __FILE__, __PRETTY_FUNCTION__,
+ source_str, group_str,
+ proto_mask, oif->name, pim_ifp->mroute_vif_index);
+ }
+
+ return 0;
+}
PIM_OIF_FLAG_PROTO_PIM | \
PIM_OIF_FLAG_PROTO_SOURCE)
+/*
+ * We need a pimreg vif id from the kernel.
+ * Since ifindex == vif id for most cases and the number
+ * of expected interfaces is at most 100, using MAXVIFS -1
+ * is probably ok.
+ * Don't come running to me if this assumption is bad,
+ * fix it.
+ */
+#define PIM_OIF_PIM_REGISTER_VIF (MAXVIFS - 1)
+#define PIM_MAX_USABLE_VIFS (MAXVIFS - 2)
+
/*
qpim_channel_oil_list holds a list of struct channel_oil.
int input_vif_index);
void pim_channel_oil_del(struct channel_oil *c_oil);
+int pim_channel_add_oif(struct channel_oil *c_oil,
+ struct interface *oif,
+ uint32_t proto_mask);
+
#endif /* PIM_OIL_H */
return vif_index;
}
-static int add_oif(struct channel_oil *channel_oil,
- struct interface *oif,
- uint32_t proto_mask)
-{
- struct pim_interface *pim_ifp;
- int old_ttl;
-
- zassert(channel_oil);
-
- pim_ifp = oif->info;
-
- if (PIM_DEBUG_MROUTE) {
- char group_str[100];
- char source_str[100];
- pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
- zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d",
- __FILE__, __PRETTY_FUNCTION__,
- source_str, group_str,
- proto_mask, oif->name, pim_ifp->mroute_vif_index);
- }
-
- if (pim_ifp->mroute_vif_index < 1) {
- zlog_warn("%s %s: interface %s vif_index=%d < 1",
- __FILE__, __PRETTY_FUNCTION__,
- oif->name, pim_ifp->mroute_vif_index);
- return -1;
- }
-
-#ifdef PIM_ENFORCE_LOOPFREE_MFC
- /*
- Prevent creating MFC entry with OIF=IIF.
-
- This is a protection against implementation mistakes.
-
- PIM protocol implicitely ensures loopfree multicast topology.
-
- IGMP must be protected against adding looped MFC entries created
- by both source and receiver attached to the same interface. See
- TODO T22.
- */
- if (pim_ifp->mroute_vif_index == channel_oil->oil.mfcc_parent) {
- char group_str[100];
- char source_str[100];
- pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
- zlog_warn("%s %s: refusing protocol mask %u request for IIF=OIF=%s (vif_index=%d) for channel (S,G)=(%s,%s)",
- __FILE__, __PRETTY_FUNCTION__,
- proto_mask, oif->name, pim_ifp->mroute_vif_index,
- source_str, group_str);
- return -2;
- }
-#endif
-
- zassert(qpim_mroute_oif_highest_vif_index < MAXVIFS);
- zassert(pim_ifp->mroute_vif_index <= qpim_mroute_oif_highest_vif_index);
-
- /* Prevent single protocol from subscribing same interface to
- channel (S,G) multiple times */
- if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask) {
- char group_str[100];
- char source_str[100];
- pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
- zlog_warn("%s %s: existing protocol mask %u requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
- __FILE__, __PRETTY_FUNCTION__,
- proto_mask, oif->name, pim_ifp->mroute_vif_index,
- channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index],
- source_str, group_str);
- return -3;
- }
-
- /* Allow other protocol to request subscription of same interface to
- channel (S,G) multiple times, by silently ignoring further
- requests */
- if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & PIM_OIF_FLAG_PROTO_ANY) {
-
- /* Check the OIF really exists before returning, and only log
- warning otherwise */
- if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) {
- char group_str[100];
- char source_str[100];
- pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
- zlog_warn("%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
- __FILE__, __PRETTY_FUNCTION__,
- proto_mask, oif->name, pim_ifp->mroute_vif_index,
- channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index],
- source_str, group_str);
- }
-
- return 0;
- }
-
- old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index];
-
- if (old_ttl > 0) {
- char group_str[100];
- char source_str[100];
- pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
- zlog_warn("%s %s: interface %s (vif_index=%d) is existing output for channel (S,G)=(%s,%s)",
- __FILE__, __PRETTY_FUNCTION__,
- oif->name, pim_ifp->mroute_vif_index,
- source_str, group_str);
- return -4;
- }
-
- channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = PIM_MROUTE_MIN_TTL;
-
- if (pim_mroute_add(&channel_oil->oil)) {
- char group_str[100];
- char source_str[100];
- pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
- zlog_warn("%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)",
- __FILE__, __PRETTY_FUNCTION__,
- oif->name, pim_ifp->mroute_vif_index,
- source_str, group_str);
-
- channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = old_ttl;
- return -5;
- }
-
- channel_oil->oif_creation[pim_ifp->mroute_vif_index] = pim_time_monotonic_sec();
- ++channel_oil->oil_size;
- channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask;
-
- if (PIM_DEBUG_MROUTE) {
- char group_str[100];
- char source_str[100];
- pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
- zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE",
- __FILE__, __PRETTY_FUNCTION__,
- source_str, group_str,
- proto_mask, oif->name, pim_ifp->mroute_vif_index);
- }
-
- return 0;
-}
-
static int del_oif(struct channel_oil *channel_oil,
struct interface *oif,
uint32_t proto_mask)
}
}
- result = add_oif(source->source_channel_oil,
- group->group_igmp_sock->interface,
- PIM_OIF_FLAG_PROTO_IGMP);
+ result = pim_channel_add_oif(source->source_channel_oil,
+ group->group_igmp_sock->interface,
+ PIM_OIF_FLAG_PROTO_IGMP);
if (result) {
zlog_warn("%s: add_oif() failed with return=%d",
__func__, result);
}
}
- add_oif(up->channel_oil,
- ch->interface,
- PIM_OIF_FLAG_PROTO_PIM);
+ pim_channel_add_oif(up->channel_oil,
+ ch->interface,
+ PIM_OIF_FLAG_PROTO_PIM);
}
void pim_forward_stop(struct pim_ifchannel *ch)