json_row = json_object_new_object();
json_object_pim_ifp_add(json_row, ifp);
+ if (pim_ifp->update_source.s_addr != INADDR_ANY) {
+ json_object_string_add(json_row, "useSource", inet_ntoa(pim_ifp->update_source));
+ }
if (pim_ifp->sec_addr_list) {
json_object *sec_list = NULL;
json_object_object_add(json, ifp->name, json_row);
} else {
- vty_out(vty, "Interface : %s%s", ifp->name, VTY_NEWLINE);
- vty_out(vty, "State : %s%s", if_is_up(ifp) ? "up" : "down", VTY_NEWLINE);
+ vty_out(vty, "Interface : %s%s", ifp->name, VTY_NEWLINE);
+ vty_out(vty, "State : %s%s", if_is_up(ifp) ? "up" : "down", VTY_NEWLINE);
+ if (pim_ifp->update_source.s_addr != INADDR_ANY) {
+ vty_out(vty, "Use Source : %s%s", inet_ntoa(pim_ifp->update_source), VTY_NEWLINE);
+ }
if (pim_ifp->sec_addr_list) {
- vty_out(vty, "Address : %s (primary)%s",
+ vty_out(vty, "Address : %s (primary)%s",
inet_ntoa(ifaddr), VTY_NEWLINE);
for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) {
- vty_out(vty, " %s%s",
+ vty_out(vty, " %s%s",
inet_ntoa(sec_addr->addr), VTY_NEWLINE);
}
} else {
- vty_out(vty, "Address : %s%s", inet_ntoa(ifaddr), VTY_NEWLINE);
+ vty_out(vty, "Address : %s%s", inet_ntoa(ifaddr), VTY_NEWLINE);
}
vty_out(vty, "%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
+static int
+interface_pim_use_src_cmd_worker(struct vty *vty, const char *source)
+{
+ int result;
+ struct in_addr source_addr;
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+
+ result = inet_pton(AF_INET, source, &source_addr);
+ if (result <= 0) {
+ vty_out(vty, "%% Bad source address %s: errno=%d: %s%s",
+ source, errno, safe_strerror(errno), VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ result = pim_update_source_set(ifp, source_addr);
+ switch (result) {
+ case PIM_SUCCESS:
+ break;
+ case PIM_UPDATE_SOURCE_DUP:
+ vty_out(vty, "%% Source already set to %s%s", source, VTY_NEWLINE);
+ break;
+ default:
+ vty_out(vty, "%% Source set failed%s", VTY_NEWLINE);
+ }
+
+ return result?CMD_WARNING:CMD_SUCCESS;
+}
+
+DEFUN (interface_pim_use_source,
+ interface_pim_use_source_cmd,
+ "ip pim use-source A.B.C.D",
+ IP_STR
+ "pim multicast routing\n"
+ "Configure primary IP address\n"
+ "source ip address\n")
+{
+ return interface_pim_use_src_cmd_worker (vty, argv[3]->arg);
+}
+
+DEFUN (interface_no_pim_use_source,
+ interface_no_pim_use_source_cmd,
+ "no ip pim use-source",
+ NO_STR
+ IP_STR
+ "pim multicast routing\n"
+ "Delete source IP address\n")
+{
+ return interface_pim_use_src_cmd_worker (vty, "0.0.0.0");
+}
+
static int
ip_msdp_peer_cmd_worker (struct vty *vty, const char *peer, const char *local)
{
install_element (VIEW_NODE, &show_ip_msdp_sa_detail_cmd);
install_element (VIEW_NODE, &show_ip_msdp_sa_sg_cmd);
install_element (VIEW_NODE, &show_ip_msdp_mesh_group_cmd);
+ install_element (INTERFACE_NODE, &interface_pim_use_source_cmd);
+ install_element (INTERFACE_NODE, &interface_no_pim_use_source_cmd);
}
int force_prim_as_any,
const char *caller)
{
- struct pim_interface *pim_ifp;
+ struct pim_interface *pim_ifp = ifp->info;
struct in_addr new_prim_addr;
int changed;
- pim_ifp = ifp->info;
- if (!pim_ifp)
- return 0;
-
if (force_prim_as_any)
new_prim_addr = qpim_inaddr_any;
else
if (changed) {
pim_ifp->primary_address = new_prim_addr;
-
- if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
- return changed;
- }
-
- pim_addr_change(ifp);
}
return changed;
return changed;
}
-static void detect_secondary_address_change(struct interface *ifp,
+static int detect_secondary_address_change(struct interface *ifp,
int force_prim_as_any,
const char *caller)
{
- struct pim_interface *pim_ifp;
+ struct pim_interface *pim_ifp = ifp->info;
int changed = 0;
- pim_ifp = ifp->info;
- if (!pim_ifp)
- return;
-
if (force_prim_as_any) {
/* if primary address is being forced to zero just flush the
* secondary address list */
- pim_sec_addr_del_all(pim_ifp);
+ changed = pim_sec_addr_del_all(pim_ifp);
} else {
/* re-evaluate the secondary address list */
changed = pim_sec_addr_update(ifp);
}
- if (PIM_DEBUG_ZEBRA)
- zlog_debug("FIXME T31 C15 %s: on interface %s: acting on any addr change",
- __PRETTY_FUNCTION__, ifp->name);
+ return changed;
+}
+
+static void detect_address_change(struct interface *ifp,
+ int force_prim_as_any,
+ const char *caller)
+{
+ int changed = 0;
+ struct pim_interface *pim_ifp;
- if (!changed) {
+ pim_ifp = ifp->info;
+ if (!pim_ifp)
return;
+
+ if (detect_primary_address_change(ifp, force_prim_as_any, caller)) {
+ changed = 1;
}
- if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
- return;
+ if (detect_secondary_address_change(ifp, force_prim_as_any, caller)) {
+ changed = 1;
+ }
+
+
+ if (changed) {
+ if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
+ return;
+ }
+
+ pim_addr_change(ifp);
}
- /* XXX - re-evaluate i_am_rp on addr change */
- //pim_addr_change(ifp);
+ /* XXX: if we have unnumbered interfaces we need to run detect address
+ * address change on all of them when the lo address changes */
}
-static void detect_address_change(struct interface *ifp,
- int force_prim_as_any,
- const char *caller)
+int pim_update_source_set(struct interface *ifp, struct in_addr source)
{
- int prim_changed;
+ struct pim_interface *pim_ifp = ifp->info;
- prim_changed = detect_primary_address_change(ifp, force_prim_as_any, caller);
- if (prim_changed) {
- /* no need to detect secondary change because
- the reaction would be the same */
- return;
+ if (!pim_ifp) {
+ return PIM_IFACE_NOT_FOUND;
}
- detect_secondary_address_change(ifp, force_prim_as_any, caller);
+ if (pim_ifp->update_source.s_addr == source.s_addr) {
+ return PIM_UPDATE_SOURCE_DUP;
+ }
+
+ pim_ifp->update_source = source;
+ detect_address_change(ifp, 0 /* force_prim_as_any */,
+ __PRETTY_FUNCTION__);
+
+ return PIM_SUCCESS;
}
void pim_if_addr_add(struct connected *ifc)
struct in_addr addr;
int v4_addrs = 0;
int v6_addrs = 0;
+ struct pim_interface *pim_ifp = ifp->info;
+
+ if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) {
+ return pim_ifp->update_source;
+ }
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
struct prefix *p = ifc->address;
ifindex_t mroute_vif_index;
struct in_addr primary_address; /* remember addr to detect change */
struct list *sec_addr_list; /* list of struct pim_secondary_addr */
+ struct in_addr update_source; /* user can statically set the primary
+ * address of the interface */
int igmp_version; /* IGMP version */
int igmp_default_robustness_variable; /* IGMPv3 QRV */
void pim_if_create_pimreg(void);
int pim_if_connected_to_source (struct interface *ifp, struct in_addr src);
+int pim_update_source_set(struct interface *ifp, struct in_addr source);
#endif /* PIM_IFACE_H */
vty_out(vty, "%s", VTY_NEWLINE);
}
+ /* update source */
+ if (PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) {
+ char src_str[INET_ADDRSTRLEN];
+ pim_inet4_dump("<src?>", pim_ifp->update_source, src_str,
+ sizeof(src_str));
+ vty_out(vty, " ip pim use-source %s%s", src_str, VTY_NEWLINE);
+ ++writes;
+ }
+
/* IF ip igmp */
if (PIM_IF_TEST_IGMP(pim_ifp->options)) {
vty_out(vty, " ip igmp%s", VTY_NEWLINE);
#define PIM_RP_NO_PATH -6
#define PIM_RP_NOT_FOUND -7
#define PIM_RP_PFXLIST_IN_USE -8
+#define PIM_IFACE_NOT_FOUND -9
+#define PIM_UPDATE_SOURCE_DUP -10
const char *const PIM_ALL_SYSTEMS;
const char *const PIM_ALL_ROUTERS;