summaryrefslogtreecommitdiff
path: root/pimd/pim_iface.c
diff options
context:
space:
mode:
Diffstat (limited to 'pimd/pim_iface.c')
-rw-r--r--pimd/pim_iface.c405
1 files changed, 261 insertions, 144 deletions
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index e007bdcc10..8e0e418a99 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -50,10 +50,12 @@
#include "pim_igmp_join.h"
#include "pim_vxlan.h"
+#if PIM_IPV == 4
static void pim_if_igmp_join_del_all(struct interface *ifp);
static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
- struct in_addr group_addr,
- struct in_addr source_addr);
+ struct in_addr group_addr, struct in_addr source_addr,
+ struct pim_interface *pim_ifp);
+#endif
void pim_if_init(struct pim_instance *pim)
{
@@ -83,6 +85,7 @@ static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr)
XFREE(MTYPE_PIM_SEC_ADDR, sec_addr);
}
+__attribute__((unused))
static int pim_sec_addr_comp(const void *p1, const void *p2)
{
const struct pim_secondary_addr *sec1 = p1;
@@ -125,15 +128,14 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
pim_ifp->mroute_vif_index = -1;
pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
- pim_ifp->igmp_default_robustness_variable =
+ pim_ifp->gm_default_robustness_variable =
IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
- pim_ifp->igmp_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL;
- pim_ifp->igmp_query_max_response_time_dsec =
+ pim_ifp->gm_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL;
+ pim_ifp->gm_query_max_response_time_dsec =
IGMP_QUERY_MAX_RESPONSE_TIME_DSEC;
- pim_ifp->igmp_specific_query_max_response_time_dsec =
+ pim_ifp->gm_specific_query_max_response_time_dsec =
IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC;
- pim_ifp->igmp_last_member_query_count =
- IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
+ pim_ifp->gm_last_member_query_count = IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
/* BSM config on interface: true by default */
pim_ifp->bsm_enable = true;
@@ -145,22 +147,24 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
The number of seconds represented by the [Query Response Interval]
must be less than the [Query Interval].
*/
- assert(pim_ifp->igmp_query_max_response_time_dsec
- < pim_ifp->igmp_default_query_interval);
+ assert(pim_ifp->gm_query_max_response_time_dsec <
+ pim_ifp->gm_default_query_interval);
if (pim)
PIM_IF_DO_PIM(pim_ifp->options);
+#if PIM_IPV == 4
if (igmp)
PIM_IF_DO_IGMP(pim_ifp->options);
PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options);
+#endif
- pim_ifp->igmp_join_list = NULL;
+ pim_ifp->gm_join_list = NULL;
pim_ifp->pim_neighbor_list = NULL;
pim_ifp->upstream_switch_list = NULL;
pim_ifp->pim_generation_id = 0;
- /* list of struct igmp_sock */
+ /* list of struct gm_sock */
pim_igmp_if_init(pim_ifp, ifp);
/* list of struct pim_neighbor */
@@ -183,7 +187,9 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
ifp->info = pim_ifp;
+#if PIM_IPV == 4
pim_sock_reset(ifp);
+#endif
pim_if_add_vif(ifp, ispimreg, is_vxlan_term);
pim_ifp->pim->mcast_if_count++;
@@ -194,23 +200,26 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
void pim_if_delete(struct interface *ifp)
{
struct pim_interface *pim_ifp;
- struct pim_ifchannel *ch;
assert(ifp);
pim_ifp = ifp->info;
assert(pim_ifp);
- if (pim_ifp->igmp_join_list) {
+ pim_ifp->pim->mcast_if_count--;
+#if PIM_IPV == 4
+ if (pim_ifp->gm_join_list) {
pim_if_igmp_join_del_all(ifp);
}
+#endif
pim_ifchannel_delete_all(ifp);
+#if PIM_IPV == 4
igmp_sock_delete_all(ifp);
+#endif
pim_neighbor_delete_all(ifp, "Interface removed from configuration");
pim_if_del_vif(ifp);
- pim_ifp->pim->mcast_if_count--;
pim_igmp_if_fini(pim_ifp);
@@ -219,13 +228,6 @@ void pim_if_delete(struct interface *ifp)
list_delete(&pim_ifp->sec_addr_list);
XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
-
- while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
- ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
-
- pim_ifchannel_delete(ch);
- }
-
XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
ifp->info = NULL;
@@ -289,7 +291,7 @@ static void pim_addr_change(struct interface *ifp)
HoldTime should be sent immediately.
-- FIXME See TODO T31
*/
- pim_ifp->pim_ifstat_hello_sent = 0; /* reset hello counter */
+ PIM_IF_FLAG_UNSET_HELLO_SENT(pim_ifp->flags);
if (pim_ifp->pim_sock_fd < 0)
return;
pim_hello_restart_now(ifp); /* send hello and restart timer */
@@ -300,27 +302,20 @@ static int detect_primary_address_change(struct interface *ifp,
const char *caller)
{
struct pim_interface *pim_ifp = ifp->info;
- struct in_addr new_prim_addr;
+ pim_addr new_prim_addr;
int changed;
if (force_prim_as_any)
- new_prim_addr.s_addr = INADDR_ANY;
+ new_prim_addr = PIMADDR_ANY;
else
new_prim_addr = pim_find_primary_addr(ifp);
- changed = new_prim_addr.s_addr != pim_ifp->primary_address.s_addr;
+ changed = pim_addr_cmp(new_prim_addr, pim_ifp->primary_address);
- if (PIM_DEBUG_ZEBRA) {
- char new_prim_str[INET_ADDRSTRLEN];
- char old_prim_str[INET_ADDRSTRLEN];
- 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=%s new=%s on interface %s: %s", __func__,
- old_prim_str, new_prim_str, ifp->name,
- changed ? "changed" : "unchanged");
- }
+ if (PIM_DEBUG_ZEBRA)
+ zlog_debug("%s: old=%pPA new=%pPA on interface %s: %s",
+ __func__, &pim_ifp->primary_address, &new_prim_addr,
+ ifp->name, changed ? "changed" : "unchanged");
if (changed) {
/* Before updating pim_ifp send Hello time with 0 hold time */
@@ -402,19 +397,18 @@ static int pim_sec_addr_update(struct interface *ifp)
}
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
- struct prefix *p = ifc->address;
+ pim_addr addr = pim_addr_from_prefix(ifc->address);
- if (PIM_INADDR_IS_ANY(p->u.prefix4)) {
+ if (pim_addr_is_any(addr))
continue;
- }
- if (pim_ifp->primary_address.s_addr == p->u.prefix4.s_addr) {
+ if (!pim_addr_cmp(addr, pim_ifp->primary_address)) {
/* don't add the primary address into the secondary
* address list */
continue;
}
- if (pim_sec_addr_add(pim_ifp, p)) {
+ if (pim_sec_addr_add(pim_ifp, ifc->address)) {
changed = 1;
}
}
@@ -481,7 +475,7 @@ static void detect_address_change(struct interface *ifp, int force_prim_as_any,
* address change on all of them when the lo address changes */
}
-int pim_update_source_set(struct interface *ifp, struct in_addr source)
+int pim_update_source_set(struct interface *ifp, pim_addr source)
{
struct pim_interface *pim_ifp = ifp->info;
@@ -489,7 +483,7 @@ int pim_update_source_set(struct interface *ifp, struct in_addr source)
return PIM_IFACE_NOT_FOUND;
}
- if (pim_ifp->update_source.s_addr == source.s_addr) {
+ if (!pim_addr_cmp(pim_ifp->update_source, source)) {
return PIM_UPDATE_SOURCE_DUP;
}
@@ -503,7 +497,6 @@ void pim_if_addr_add(struct connected *ifc)
{
struct pim_interface *pim_ifp;
struct interface *ifp;
- struct in_addr ifaddr;
bool vxlan_term;
assert(ifc);
@@ -523,46 +516,67 @@ void pim_if_addr_add(struct connected *ifc)
CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
? "secondary"
: "primary");
-
- ifaddr = ifc->address->u.prefix4;
+#if PIM_IPV != 4
+ if (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6) ||
+ IN6_IS_ADDR_LOOPBACK(&ifc->address->u.prefix6)) {
+ if (IN6_IS_ADDR_UNSPECIFIED(&pim_ifp->ll_lowest))
+ pim_ifp->ll_lowest = ifc->address->u.prefix6;
+ else if (IPV6_ADDR_CMP(&ifc->address->u.prefix6,
+ &pim_ifp->ll_lowest) < 0)
+ pim_ifp->ll_lowest = ifc->address->u.prefix6;
+
+ if (IPV6_ADDR_CMP(&ifc->address->u.prefix6,
+ &pim_ifp->ll_highest) > 0)
+ pim_ifp->ll_highest = ifc->address->u.prefix6;
+
+ if (PIM_DEBUG_ZEBRA)
+ zlog_debug(
+ "%s: new link-local %pI6, lowest now %pI6, highest %pI6",
+ ifc->ifp->name, &ifc->address->u.prefix6,
+ &pim_ifp->ll_lowest, &pim_ifp->ll_highest);
+ }
+#endif
detect_address_change(ifp, 0, __func__);
// if (ifc->address->family != AF_INET)
// return;
+#if PIM_IPV == 4
+ struct in_addr ifaddr = ifc->address->u.prefix4;
+
if (PIM_IF_TEST_IGMP(pim_ifp->options)) {
- struct igmp_sock *igmp;
+ struct gm_sock *igmp;
/* lookup IGMP socket */
- igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
+ igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list,
ifaddr);
if (!igmp) {
/* if addr new, add IGMP socket */
if (ifc->address->family == AF_INET)
- pim_igmp_sock_add(pim_ifp->igmp_socket_list,
+ pim_igmp_sock_add(pim_ifp->gm_socket_list,
ifaddr, ifp, false);
} else if (igmp->mtrace_only) {
igmp_sock_delete(igmp);
- pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr,
- ifp, false);
+ pim_igmp_sock_add(pim_ifp->gm_socket_list, ifaddr, ifp,
+ false);
}
/* Replay Static IGMP groups */
- if (pim_ifp->igmp_join_list) {
+ if (pim_ifp->gm_join_list) {
struct listnode *node;
struct listnode *nextnode;
- struct igmp_join *ij;
+ struct gm_join *ij;
int join_fd;
- for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node,
+ for (ALL_LIST_ELEMENTS(pim_ifp->gm_join_list, node,
nextnode, ij)) {
/* Close socket and reopen with Source and Group
*/
close(ij->sock_fd);
join_fd = igmp_join_sock(
ifp->name, ifp->ifindex, ij->group_addr,
- ij->source_addr);
+ ij->source_addr, pim_ifp);
if (join_fd < 0) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
@@ -583,23 +597,24 @@ void pim_if_addr_add(struct connected *ifc)
}
} /* igmp */
else {
- struct igmp_sock *igmp;
+ struct gm_sock *igmp;
/* lookup IGMP socket */
- igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
+ igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list,
ifaddr);
if (ifc->address->family == AF_INET) {
if (igmp)
igmp_sock_delete(igmp);
/* if addr new, add IGMP socket */
- pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr,
- ifp, true);
+ pim_igmp_sock_add(pim_ifp->gm_socket_list, ifaddr, ifp,
+ true);
}
} /* igmp mtrace only */
+#endif
if (PIM_IF_TEST_PIM(pim_ifp->options)) {
- if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
+ if (!pim_addr_is_any(pim_ifp->primary_address)) {
/* Interface has a valid socket ? */
if (pim_ifp->pim_sock_fd < 0) {
@@ -647,8 +662,9 @@ void pim_if_addr_add(struct connected *ifc)
static void pim_if_addr_del_igmp(struct connected *ifc)
{
+#if PIM_IPV == 4
struct pim_interface *pim_ifp = ifc->ifp->info;
- struct igmp_sock *igmp;
+ struct gm_sock *igmp;
struct in_addr ifaddr;
if (ifc->address->family != AF_INET) {
@@ -664,11 +680,12 @@ static void pim_if_addr_del_igmp(struct connected *ifc)
ifaddr = ifc->address->u.prefix4;
/* lookup IGMP socket */
- igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr);
+ igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list, ifaddr);
if (igmp) {
/* if addr found, del IGMP socket */
igmp_sock_delete(igmp);
}
+#endif
}
static void pim_if_addr_del_pim(struct connected *ifc)
@@ -685,7 +702,7 @@ static void pim_if_addr_del_pim(struct connected *ifc)
return;
}
- if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
+ if (!pim_addr_is_any(pim_ifp->primary_address)) {
/* Interface keeps a valid primary address */
return;
}
@@ -718,6 +735,43 @@ void pim_if_addr_del(struct connected *ifc, int force_prim_as_any)
? "secondary"
: "primary");
+#if PIM_IPV == 6
+ struct pim_interface *pim_ifp = ifc->ifp->info;
+
+ if (pim_ifp &&
+ (!IPV6_ADDR_CMP(&ifc->address->u.prefix6, &pim_ifp->ll_lowest) ||
+ !IPV6_ADDR_CMP(&ifc->address->u.prefix6, &pim_ifp->ll_highest))) {
+ struct listnode *cnode;
+ struct connected *cc;
+
+ memset(&pim_ifp->ll_lowest, 0xff, sizeof(pim_ifp->ll_lowest));
+ memset(&pim_ifp->ll_highest, 0, sizeof(pim_ifp->ll_highest));
+
+ for (ALL_LIST_ELEMENTS_RO(ifc->ifp->connected, cnode, cc)) {
+ if (!IN6_IS_ADDR_LINKLOCAL(&cc->address->u.prefix6) &&
+ !IN6_IS_ADDR_LOOPBACK(&cc->address->u.prefix6))
+ continue;
+
+ if (IPV6_ADDR_CMP(&cc->address->u.prefix6,
+ &pim_ifp->ll_lowest) < 0)
+ pim_ifp->ll_lowest = cc->address->u.prefix6;
+ if (IPV6_ADDR_CMP(&cc->address->u.prefix6,
+ &pim_ifp->ll_highest) > 0)
+ pim_ifp->ll_highest = cc->address->u.prefix6;
+ }
+
+ if (pim_ifp->ll_lowest.s6_addr[0] == 0xff)
+ memset(&pim_ifp->ll_lowest, 0,
+ sizeof(pim_ifp->ll_lowest));
+
+ if (PIM_DEBUG_ZEBRA)
+ zlog_debug(
+ "%s: removed link-local %pI6, lowest now %pI6, highest %pI6",
+ ifc->ifp->name, &ifc->address->u.prefix6,
+ &pim_ifp->ll_lowest, &pim_ifp->ll_highest);
+ }
+#endif
+
detect_address_change(ifp, force_prim_as_any, __func__);
pim_if_addr_del_igmp(ifc);
@@ -753,7 +807,7 @@ void pim_if_addr_add_all(struct interface *ifp)
if (PIM_IF_TEST_PIM(pim_ifp->options)) {
/* Interface has a valid primary address ? */
- if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
+ if (!pim_addr_is_any(pim_ifp->primary_address)) {
/* Interface has a valid socket ? */
if (pim_ifp->pim_sock_fd < 0) {
@@ -828,40 +882,58 @@ void pim_if_addr_del_all_igmp(struct interface *ifp)
}
}
-struct in_addr pim_find_primary_addr(struct interface *ifp)
+pim_addr pim_find_primary_addr(struct interface *ifp)
{
struct connected *ifc;
struct listnode *node;
- struct in_addr addr = {0};
- 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)) {
+ if (pim_ifp && !pim_addr_is_any(pim_ifp->update_source))
return pim_ifp->update_source;
- }
+
+#if PIM_IPV == 6
+ if (pim_ifp)
+ return pim_ifp->ll_highest;
+
+ pim_addr best_addr = PIMADDR_ANY;
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
- struct prefix *p = ifc->address;
+ pim_addr addr;
- if (p->family != AF_INET) {
- v6_addrs++;
+ if (ifc->address->family != AF_INET6)
continue;
- }
- if (PIM_INADDR_IS_ANY(p->u.prefix4)) {
- zlog_warn(
- "%s: null IPv4 address connected to interface %s",
- __func__, ifp->name);
+ addr = pim_addr_from_prefix(ifc->address);
+ if (!IN6_IS_ADDR_LINKLOCAL(&addr))
continue;
- }
+ if (pim_addr_cmp(addr, best_addr) > 0)
+ best_addr = addr;
+ }
+
+ return best_addr;
+#else
+ int v4_addrs = 0;
+ int v6_addrs = 0;
- v4_addrs++;
+ for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
+ switch (ifc->address->family) {
+ case AF_INET:
+ v4_addrs++;
+ break;
+ case AF_INET6:
+ v6_addrs++;
+ break;
+ default:
+ continue;
+ }
if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
continue;
- return p->u.prefix4;
+ if (ifc->address->family != PIM_AF)
+ continue;
+
+ return pim_addr_from_prefix(ifc->address);
}
/*
@@ -883,10 +955,8 @@ struct in_addr pim_find_primary_addr(struct interface *ifp)
if (lo_ifp && (lo_ifp != ifp))
return pim_find_primary_addr(lo_ifp);
}
-
- addr.s_addr = PIM_NET_INADDR_ANY;
-
- return addr;
+ return PIMADDR_ANY;
+#endif
}
static int pim_iface_next_vif_index(struct interface *ifp)
@@ -917,7 +987,7 @@ static int pim_iface_next_vif_index(struct interface *ifp)
int pim_if_add_vif(struct interface *ifp, bool ispimreg, bool is_vxlan_term)
{
struct pim_interface *pim_ifp = ifp->info;
- struct in_addr ifaddr;
+ pim_addr ifaddr;
unsigned char flags = 0;
assert(pim_ifp);
@@ -936,7 +1006,7 @@ int pim_if_add_vif(struct interface *ifp, bool ispimreg, bool is_vxlan_term)
}
ifaddr = pim_ifp->primary_address;
- if (!ispimreg && !is_vxlan_term && PIM_INADDR_IS_ANY(ifaddr)) {
+ if (!ispimreg && !is_vxlan_term && pim_addr_is_any(ifaddr)) {
zlog_warn(
"%s: could not get address for interface %s ifindex=%d",
__func__, ifp->name, ifp->ifindex);
@@ -1095,8 +1165,7 @@ uint16_t pim_if_jp_override_interval_msec(struct interface *ifp)
router (Section 4.3.4). The primary IP address of a neighbor is the
address that it uses as the source of its PIM Hello messages.
*/
-struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
- struct in_addr addr)
+struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, pim_addr addr)
{
struct listnode *neighnode;
struct pim_neighbor *neigh;
@@ -1112,15 +1181,13 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
return 0;
}
- p.family = AF_INET;
- p.u.prefix4 = addr;
- p.prefixlen = IPV4_MAX_BITLEN;
+ pim_addr_to_prefix(&p, addr);
for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
neigh)) {
/* primary address ? */
- if (neigh->source_addr.s_addr == addr.s_addr)
+ if (!pim_addr_cmp(neigh->source_addr, addr))
return neigh;
/* secondary address ? */
@@ -1128,13 +1195,10 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
return neigh;
}
- if (PIM_DEBUG_PIM_TRACE) {
- char addr_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
+ if (PIM_DEBUG_PIM_TRACE)
zlog_debug(
- "%s: neighbor not found for address %s on interface %s",
- __func__, addr_str, ifp->name);
- }
+ "%s: neighbor not found for address %pPA on interface %s",
+ __func__, &addr, ifp->name);
return NULL;
}
@@ -1159,17 +1223,18 @@ long pim_if_t_suppressed_msec(struct interface *ifp)
return t_suppressed_msec;
}
-static void igmp_join_free(struct igmp_join *ij)
+#if PIM_IPV == 4
+static void igmp_join_free(struct gm_join *ij)
{
XFREE(MTYPE_PIM_IGMP_JOIN, ij);
}
-static struct igmp_join *igmp_join_find(struct list *join_list,
- struct in_addr group_addr,
- struct in_addr source_addr)
+static struct gm_join *igmp_join_find(struct list *join_list,
+ struct in_addr group_addr,
+ struct in_addr source_addr)
{
struct listnode *node;
- struct igmp_join *ij;
+ struct gm_join *ij;
assert(join_list);
@@ -1183,12 +1248,16 @@ static struct igmp_join *igmp_join_find(struct list *join_list,
}
static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
- struct in_addr group_addr, struct in_addr source_addr)
+ struct in_addr group_addr, struct in_addr source_addr,
+ struct pim_interface *pim_ifp)
{
int join_fd;
+ pim_ifp->igmp_ifstat_joins_sent++;
+
join_fd = pim_socket_raw(IPPROTO_IGMP);
if (join_fd < 0) {
+ pim_ifp->igmp_ifstat_joins_failed++;
return -1;
}
@@ -1204,6 +1273,8 @@ static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
__func__, join_fd, group_str, source_str, ifindex,
ifname, errno, safe_strerror(errno));
+ pim_ifp->igmp_ifstat_joins_failed++;
+
close(join_fd);
return -2;
}
@@ -1211,19 +1282,20 @@ static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
return join_fd;
}
-static struct igmp_join *igmp_join_new(struct interface *ifp,
- struct in_addr group_addr,
- struct in_addr source_addr)
+#if PIM_IPV == 4
+static struct gm_join *igmp_join_new(struct interface *ifp,
+ struct in_addr group_addr,
+ struct in_addr source_addr)
{
struct pim_interface *pim_ifp;
- struct igmp_join *ij;
+ struct gm_join *ij;
int join_fd;
pim_ifp = ifp->info;
assert(pim_ifp);
join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr,
- source_addr);
+ source_addr, pim_ifp);
if (join_fd < 0) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
@@ -1245,16 +1317,18 @@ static struct igmp_join *igmp_join_new(struct interface *ifp,
ij->source_addr = source_addr;
ij->sock_creation = pim_time_monotonic_sec();
- listnode_add(pim_ifp->igmp_join_list, ij);
+ listnode_add(pim_ifp->gm_join_list, ij);
return ij;
}
+#endif /* PIM_IPV == 4 */
+#if PIM_IPV == 4
ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
struct in_addr source_addr)
{
struct pim_interface *pim_ifp;
- struct igmp_join *ij;
+ struct gm_join *ij;
pim_ifp = ifp->info;
if (!pim_ifp) {
@@ -1262,12 +1336,12 @@ ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
ifp->name);
}
- if (!pim_ifp->igmp_join_list) {
- pim_ifp->igmp_join_list = list_new();
- pim_ifp->igmp_join_list->del = (void (*)(void *))igmp_join_free;
+ if (!pim_ifp->gm_join_list) {
+ pim_ifp->gm_join_list = list_new();
+ pim_ifp->gm_join_list->del = (void (*)(void *))igmp_join_free;
}
- ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr);
+ ij = igmp_join_find(pim_ifp->gm_join_list, group_addr, source_addr);
/* This interface has already been configured to join this IGMP group
*/
@@ -1291,13 +1365,13 @@ ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
return ferr_ok();
}
-
+#endif /* PIM_IPV == 4 */
int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,
struct in_addr source_addr)
{
struct pim_interface *pim_ifp;
- struct igmp_join *ij;
+ struct gm_join *ij;
pim_ifp = ifp->info;
if (!pim_ifp) {
@@ -1306,13 +1380,13 @@ int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,
return -1;
}
- if (!pim_ifp->igmp_join_list) {
+ if (!pim_ifp->gm_join_list) {
zlog_warn("%s: no IGMP join on interface %s", __func__,
ifp->name);
return -2;
}
- ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr);
+ ij = igmp_join_find(pim_ifp->gm_join_list, group_addr, source_addr);
if (!ij) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
@@ -1339,22 +1413,23 @@ int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,
errno, safe_strerror(errno));
/* warning only */
}
- listnode_delete(pim_ifp->igmp_join_list, ij);
+ listnode_delete(pim_ifp->gm_join_list, ij);
igmp_join_free(ij);
- if (listcount(pim_ifp->igmp_join_list) < 1) {
- list_delete(&pim_ifp->igmp_join_list);
- pim_ifp->igmp_join_list = 0;
+ if (listcount(pim_ifp->gm_join_list) < 1) {
+ list_delete(&pim_ifp->gm_join_list);
+ pim_ifp->gm_join_list = 0;
}
return 0;
}
+__attribute__((unused))
static void pim_if_igmp_join_del_all(struct interface *ifp)
{
struct pim_interface *pim_ifp;
struct listnode *node;
struct listnode *nextnode;
- struct igmp_join *ij;
+ struct gm_join *ij;
pim_ifp = ifp->info;
if (!pim_ifp) {
@@ -1363,12 +1438,25 @@ static void pim_if_igmp_join_del_all(struct interface *ifp)
return;
}
- if (!pim_ifp->igmp_join_list)
+ if (!pim_ifp->gm_join_list)
return;
- for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, nextnode, ij))
+ for (ALL_LIST_ELEMENTS(pim_ifp->gm_join_list, node, nextnode, ij))
pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr);
}
+#else /* PIM_IPV != 4 */
+ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
+ struct in_addr source_addr)
+{
+ return ferr_ok();
+}
+
+int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,
+ struct in_addr source_addr)
+{
+ return 0;
+}
+#endif /* PIM_IPV != 4 */
/*
RFC 4601
@@ -1384,8 +1472,7 @@ static void pim_if_igmp_join_del_all(struct interface *ifp)
gone down (and may have come back up), and so we must assume it no
longer knows it was the winner.
*/
-void pim_if_assert_on_neighbor_down(struct interface *ifp,
- struct in_addr neigh_addr)
+void pim_if_assert_on_neighbor_down(struct interface *ifp, pim_addr neigh_addr)
{
struct pim_interface *pim_ifp;
struct pim_ifchannel *ch;
@@ -1398,7 +1485,7 @@ void pim_if_assert_on_neighbor_down(struct interface *ifp,
if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER)
continue;
/* Dead neighbor was winner ? */
- if (ch->ifassert_winner.s_addr != neigh_addr.s_addr)
+ if (pim_addr_cmp(ch->ifassert_winner, neigh_addr))
continue;
assert_action_a5(ch);
@@ -1474,7 +1561,7 @@ void pim_if_create_pimreg(struct pim_instance *pim)
}
}
-struct prefix *pim_if_connected_to_source(struct interface *ifp, struct in_addr src)
+struct prefix *pim_if_connected_to_source(struct interface *ifp, pim_addr src)
{
struct listnode *cnode;
struct connected *c;
@@ -1483,12 +1570,10 @@ struct prefix *pim_if_connected_to_source(struct interface *ifp, struct in_addr
if (!ifp)
return NULL;
- p.family = AF_INET;
- p.u.prefix4 = src;
- p.prefixlen = IPV4_MAX_BITLEN;
+ pim_addr_to_prefix(&p, src);
for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
- if (c->address->family != AF_INET)
+ if (c->address->family != PIM_AF)
continue;
if (prefix_match(c->address, &p))
return c->address;
@@ -1522,7 +1607,7 @@ int pim_if_ifchannel_count(struct pim_interface *pim_ifp)
return count;
}
-int pim_ifp_create(struct interface *ifp)
+static int pim_ifp_create(struct interface *ifp)
{
struct pim_instance *pim;
@@ -1559,6 +1644,7 @@ int pim_ifp_create(struct interface *ifp)
pim_if_create_pimreg(pim);
}
+#if PIM_IPV == 4
/*
* If we are a vrf device that is up, open up the pim_socket for
* listening
@@ -1586,15 +1672,16 @@ int pim_ifp_create(struct interface *ifp)
"%s: Cannot enable pim on %s. MAXVIFS(%d) reached. Deleting and readding the vxlan termimation device after unconfiguring pim from other interfaces may succeed.",
__func__, ifp->name, MAXVIFS);
}
+#endif
return 0;
}
-int pim_ifp_up(struct interface *ifp)
+static int pim_ifp_up(struct interface *ifp)
{
+ uint32_t table_id;
struct pim_interface *pim_ifp;
struct pim_instance *pim;
- uint32_t table_id;
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
@@ -1646,7 +1733,7 @@ int pim_ifp_up(struct interface *ifp)
return 0;
}
-int pim_ifp_down(struct interface *ifp)
+static int pim_ifp_down(struct interface *ifp)
{
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
@@ -1664,6 +1751,7 @@ int pim_ifp_down(struct interface *ifp)
*/
pim_if_addr_del_all(ifp);
+#if PIM_IPV == 4
/*
pim_sock_delete() closes the socket, stops read and timer
threads,
@@ -1672,18 +1760,21 @@ int pim_ifp_down(struct interface *ifp)
if (ifp->info) {
pim_sock_delete(ifp, "link down");
}
+#endif
}
- if (ifp->info)
+ if (ifp->info) {
pim_if_del_vif(ifp);
+#if PIM_IPV == 4
+ pim_ifstat_reset(ifp);
+#endif
+ }
return 0;
}
-int pim_ifp_destroy(struct interface *ifp)
+static int pim_ifp_destroy(struct interface *ifp)
{
- struct pim_instance *pim;
-
if (PIM_DEBUG_ZEBRA) {
zlog_debug(
"%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
@@ -1695,9 +1786,35 @@ int pim_ifp_destroy(struct interface *ifp)
if (!if_is_operative(ifp))
pim_if_addr_del_all(ifp);
+#if PIM_IPV == 4
+ struct pim_instance *pim;
+
pim = ifp->vrf->info;
if (pim && pim->vxlan.term_if == ifp)
pim_vxlan_del_term_dev(pim);
+#endif
return 0;
}
+
+static int pim_if_new_hook(struct interface *ifp)
+{
+ return 0;
+}
+
+static int pim_if_delete_hook(struct interface *ifp)
+{
+ if (ifp->info)
+ pim_if_delete(ifp);
+
+ return 0;
+}
+
+void pim_iface_init(void)
+{
+ hook_register_prio(if_add, 0, pim_if_new_hook);
+ hook_register_prio(if_del, 0, pim_if_delete_hook);
+
+ if_zapi_callbacks(pim_ifp_create, pim_ifp_up, pim_ifp_down,
+ pim_ifp_destroy);
+}