pimd: FIXED C14 T32 Detection of interface primary address changes may fail.
diff --git a/pimd/CAVEATS b/pimd/CAVEATS
index ba6426d..7e2820b 100644
--- a/pimd/CAVEATS
+++ b/pimd/CAVEATS
@@ -109,8 +109,8 @@
See also pim_sock_delete().
-C14 Detection of interface primary address changes may fail when there
- are multiple addresses.
+C14 FIXED Detection of interface primary address changes may fail when
+ there are multiple addresses.
See also TODO T32.
C15 Changes in interface secondary address list are not immediately
diff --git a/pimd/TODO b/pimd/TODO
index 3a3330d..80835e4 100644
--- a/pimd/TODO
+++ b/pimd/TODO
@@ -267,8 +267,8 @@
See also CAVEAT C15.
See also RFC 4601: 4.3.1. Sending Hello Messages
-T32 Detection of interface primary address changes may fail when there
- are multiple addresses.
+T32 FIXED Detection of interface primary address changes may fail when
+ there are multiple addresses.
See also CAVEAT C14.
pim_find_primary_addr() should return interface primary address
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index 72626ec..3dee751 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -286,6 +286,7 @@
{
struct pim_interface *pim_ifp;
struct in_addr new_prim_addr;
+ int changed;
pim_ifp = ifp->info;
if (!pim_ifp)
@@ -293,17 +294,20 @@
new_prim_addr = pim_find_primary_addr(ifp);
+ changed = new_prim_addr.s_addr != pim_ifp->primary_address.s_addr;
+
if (PIM_DEBUG_ZEBRA) {
char new_prim_str[100];
char old_prim_str[100];
pim_inet4_dump("<new?>", new_prim_addr, new_prim_str, sizeof(new_prim_str));
pim_inet4_dump("<old?>", pim_ifp->primary_address, old_prim_str, sizeof(old_prim_str));
- zlog_debug("%s: old primary addr %s, new primary addr %s on interface %s",
+ zlog_debug("%s: old=%s new=%s on interface %s: %s",
__PRETTY_FUNCTION__,
- old_prim_str, new_prim_str, ifp->name);
+ old_prim_str, new_prim_str, ifp->name,
+ changed ? "changed" : "unchanged");
}
- if (new_prim_addr.s_addr != pim_ifp->primary_address.s_addr) {
+ if (changed) {
struct in_addr old_addr = pim_ifp->primary_address;
pim_ifp->primary_address = new_prim_addr;
@@ -328,6 +332,16 @@
if (!if_is_operative(ifp))
return;
+ if (PIM_DEBUG_ZEBRA) {
+ char buf[BUFSIZ];
+ prefix2str(ifc->address, buf, BUFSIZ);
+ zlog_debug("%s: %s connected IP address %s %s",
+ __PRETTY_FUNCTION__,
+ ifp->name, buf,
+ CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ?
+ "secondary" : "primary");
+ }
+
ifaddr = ifc->address->u.prefix4;
detect_primary_address_change(ifp, __PRETTY_FUNCTION__);
@@ -437,6 +451,16 @@
ifp = ifc->ifp;
zassert(ifp);
+ if (PIM_DEBUG_ZEBRA) {
+ char buf[BUFSIZ];
+ prefix2str(ifc->address, buf, BUFSIZ);
+ zlog_debug("%s: %s disconnected IP address %s %s",
+ __PRETTY_FUNCTION__,
+ ifp->name, buf,
+ CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ?
+ "secondary" : "primary");
+ }
+
detect_primary_address_change(ifp, __PRETTY_FUNCTION__);
pim_if_addr_del_igmp(ifc);
@@ -523,7 +547,7 @@
}
}
-static struct in_addr find_first_addr(struct interface *ifp)
+static struct in_addr find_first_nonsec_addr(struct interface *ifp)
{
struct connected *ifc;
struct listnode *node;
@@ -541,6 +565,9 @@
continue;
}
+ if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
+ continue;
+
return p->u.prefix4;
}
@@ -551,7 +578,7 @@
struct in_addr pim_find_primary_addr(struct interface *ifp)
{
- return find_first_addr(ifp);
+ return find_first_nonsec_addr(ifp);
}
/*
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index 820b0ef..f0aa84f 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -203,10 +203,12 @@
if (p->family != AF_INET)
continue;
- zlog_debug("%s %s: interface %s address %s",
+ zlog_debug("%s %s: interface %s address %s %s",
__FILE__, __PRETTY_FUNCTION__,
ifp->name,
- inet_ntoa(p->u.prefix4));
+ inet_ntoa(p->u.prefix4),
+ CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ?
+ "secondary" : "primary");
}
}
#endif
@@ -238,15 +240,36 @@
if (PIM_DEBUG_ZEBRA) {
char buf[BUFSIZ];
prefix2str(p, buf, BUFSIZ);
- zlog_debug("%s: %s connected IP address %s flags %u",
+ zlog_debug("%s: %s connected IP address %s flags %u %s",
__PRETTY_FUNCTION__,
- c->ifp->name, buf, c->flags);
+ c->ifp->name, buf, c->flags,
+ CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary");
#ifdef PIM_DEBUG_IFADDR_DUMP
dump_if_address(c->ifp);
#endif
}
+ if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
+ /* trying to add primary address */
+
+ struct in_addr primary_addr = pim_find_primary_addr(c->ifp);
+ if (primary_addr.s_addr != p->u.prefix4.s_addr) {
+ /* but we had a primary address already */
+
+ char buf[BUFSIZ];
+ char old[100];
+
+ prefix2str(p, buf, BUFSIZ);
+ pim_inet4_dump("<old?>", primary_addr, old, sizeof(old));
+
+ zlog_warn("%s: %s primary addr old=%s: forcing secondary flag on new=%s",
+ __PRETTY_FUNCTION__,
+ c->ifp->name, old, buf);
+ SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
+ }
+ }
+
pim_if_addr_add(c);
return 0;
@@ -279,15 +302,16 @@
if (PIM_DEBUG_ZEBRA) {
char buf[BUFSIZ];
prefix2str(p, buf, BUFSIZ);
- zlog_debug("%s: %s disconnected IP address %s flags %u",
+ zlog_debug("%s: %s disconnected IP address %s flags %u %s",
__PRETTY_FUNCTION__,
- c->ifp->name, buf, c->flags);
+ c->ifp->name, buf, c->flags,
+ CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary");
#ifdef PIM_DEBUG_IFADDR_DUMP
dump_if_address(c->ifp);
#endif
}
-
+
pim_if_addr_del(c);
return 0;