mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 06:03:10 +00:00
pimd: Fix crash on iface down due to secondary address list
The secondary address list was being added/removed as we went. I see no reason to have special bookkeeping for this list. Just add it on interface startup and then remove it on deletion. Removes some very specialized coding that was saving a very small amount of space. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
parent
8e7a4c6e2b
commit
f09eaf1c8e
146
pimd/pim_iface.c
146
pimd/pim_iface.c
@ -69,17 +69,14 @@ static void *if_list_clean(struct pim_interface *pim_ifp)
|
|||||||
{
|
{
|
||||||
struct pim_ifchannel *ch;
|
struct pim_ifchannel *ch;
|
||||||
|
|
||||||
if (pim_ifp->igmp_join_list) {
|
if (pim_ifp->igmp_join_list)
|
||||||
list_delete(pim_ifp->igmp_join_list);
|
list_delete(pim_ifp->igmp_join_list);
|
||||||
}
|
|
||||||
|
|
||||||
if (pim_ifp->igmp_socket_list) {
|
if (pim_ifp->igmp_socket_list)
|
||||||
list_delete(pim_ifp->igmp_socket_list);
|
list_delete(pim_ifp->igmp_socket_list);
|
||||||
}
|
|
||||||
|
|
||||||
if (pim_ifp->pim_neighbor_list) {
|
if (pim_ifp->pim_neighbor_list)
|
||||||
list_delete(pim_ifp->pim_neighbor_list);
|
list_delete(pim_ifp->pim_neighbor_list);
|
||||||
}
|
|
||||||
|
|
||||||
if (pim_ifp->upstream_switch_list)
|
if (pim_ifp->upstream_switch_list)
|
||||||
list_delete(pim_ifp->upstream_switch_list);
|
list_delete(pim_ifp->upstream_switch_list);
|
||||||
@ -96,6 +93,38 @@ static void *if_list_clean(struct pim_interface *pim_ifp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr)
|
||||||
|
{
|
||||||
|
XFREE(MTYPE_PIM_SEC_ADDR, sec_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pim_sec_addr_comp(const void *p1, const void *p2)
|
||||||
|
{
|
||||||
|
const struct pim_secondary_addr *sec1 = p1;
|
||||||
|
const struct pim_secondary_addr *sec2 = p2;
|
||||||
|
|
||||||
|
if (sec1->addr.family == AF_INET && sec2->addr.family == AF_INET6)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (sec1->addr.family == AF_INET6 && sec2->addr.family == AF_INET)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (sec1->addr.family == AF_INET) {
|
||||||
|
if (ntohl(sec1->addr.u.prefix4.s_addr)
|
||||||
|
< ntohl(sec2->addr.u.prefix4.s_addr))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ntohl(sec1->addr.u.prefix4.s_addr)
|
||||||
|
> ntohl(sec2->addr.u.prefix4.s_addr))
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return memcmp(&sec1->addr.u.prefix6, &sec2->addr.u.prefix6,
|
||||||
|
sizeof(struct in6_addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
|
struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
|
||||||
{
|
{
|
||||||
struct pim_interface *pim_ifp;
|
struct pim_interface *pim_ifp;
|
||||||
@ -146,8 +175,8 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
|
|||||||
/* list of struct igmp_sock */
|
/* list of struct igmp_sock */
|
||||||
pim_ifp->igmp_socket_list = list_new();
|
pim_ifp->igmp_socket_list = list_new();
|
||||||
if (!pim_ifp->igmp_socket_list) {
|
if (!pim_ifp->igmp_socket_list) {
|
||||||
zlog_err("%s %s: failure: igmp_socket_list=list_new()",
|
zlog_err("%s: failure: igmp_socket_list=list_new()",
|
||||||
__FILE__, __PRETTY_FUNCTION__);
|
__PRETTY_FUNCTION__);
|
||||||
return if_list_clean(pim_ifp);
|
return if_list_clean(pim_ifp);
|
||||||
}
|
}
|
||||||
pim_ifp->igmp_socket_list->del = (void (*)(void *))igmp_sock_free;
|
pim_ifp->igmp_socket_list->del = (void (*)(void *))igmp_sock_free;
|
||||||
@ -155,22 +184,31 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
|
|||||||
/* list of struct pim_neighbor */
|
/* list of struct pim_neighbor */
|
||||||
pim_ifp->pim_neighbor_list = list_new();
|
pim_ifp->pim_neighbor_list = list_new();
|
||||||
if (!pim_ifp->pim_neighbor_list) {
|
if (!pim_ifp->pim_neighbor_list) {
|
||||||
zlog_err("%s %s: failure: pim_neighbor_list=list_new()",
|
zlog_err("%s: failure: pim_neighbor_list=list_new()",
|
||||||
__FILE__, __PRETTY_FUNCTION__);
|
__PRETTY_FUNCTION__);
|
||||||
return if_list_clean(pim_ifp);
|
return if_list_clean(pim_ifp);
|
||||||
}
|
}
|
||||||
pim_ifp->pim_neighbor_list->del = (void (*)(void *))pim_neighbor_free;
|
pim_ifp->pim_neighbor_list->del = (void (*)(void *))pim_neighbor_free;
|
||||||
|
|
||||||
pim_ifp->upstream_switch_list = list_new();
|
pim_ifp->upstream_switch_list = list_new();
|
||||||
if (!pim_ifp->upstream_switch_list) {
|
if (!pim_ifp->upstream_switch_list) {
|
||||||
zlog_err("%s %s: failure: upstream_switch_list=list_new()",
|
zlog_err("%s: failure: upstream_switch_list=list_new()",
|
||||||
__FILE__, __PRETTY_FUNCTION__);
|
__PRETTY_FUNCTION__);
|
||||||
return if_list_clean(pim_ifp);
|
return if_list_clean(pim_ifp);
|
||||||
}
|
}
|
||||||
pim_ifp->upstream_switch_list->del =
|
pim_ifp->upstream_switch_list->del =
|
||||||
(void (*)(void *))pim_jp_agg_group_list_free;
|
(void (*)(void *))pim_jp_agg_group_list_free;
|
||||||
pim_ifp->upstream_switch_list->cmp = pim_jp_agg_group_list_cmp;
|
pim_ifp->upstream_switch_list->cmp = pim_jp_agg_group_list_cmp;
|
||||||
|
|
||||||
|
pim_ifp->sec_addr_list = list_new();
|
||||||
|
if (!pim_ifp->sec_addr_list) {
|
||||||
|
zlog_err("%s: failure: secondary addresslist",
|
||||||
|
__PRETTY_FUNCTION__);
|
||||||
|
}
|
||||||
|
pim_ifp->sec_addr_list->del = (void (*)(void *))pim_sec_addr_free;
|
||||||
|
pim_ifp->sec_addr_list->cmp =
|
||||||
|
(int (*)(void *, void *))pim_sec_addr_comp;
|
||||||
|
|
||||||
RB_INIT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
|
RB_INIT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
|
||||||
|
|
||||||
ifp->info = pim_ifp;
|
ifp->info = pim_ifp;
|
||||||
@ -314,48 +352,12 @@ static int detect_primary_address_change(struct interface *ifp,
|
|||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pim_sec_addr_comp(const void *p1, const void *p2)
|
|
||||||
{
|
|
||||||
const struct pim_secondary_addr *sec1 = p1;
|
|
||||||
const struct pim_secondary_addr *sec2 = p2;
|
|
||||||
|
|
||||||
if (sec1->addr.family == AF_INET && sec2->addr.family == AF_INET6)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (sec1->addr.family == AF_INET6 && sec2->addr.family == AF_INET)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (sec1->addr.family == AF_INET) {
|
|
||||||
if (ntohl(sec1->addr.u.prefix4.s_addr)
|
|
||||||
< ntohl(sec2->addr.u.prefix4.s_addr))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (ntohl(sec1->addr.u.prefix4.s_addr)
|
|
||||||
> ntohl(sec2->addr.u.prefix4.s_addr))
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return memcmp(&sec1->addr.u.prefix6, &sec2->addr.u.prefix6,
|
|
||||||
sizeof(struct in6_addr));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr)
|
|
||||||
{
|
|
||||||
XFREE(MTYPE_PIM_SEC_ADDR, sec_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct pim_secondary_addr *
|
static struct pim_secondary_addr *
|
||||||
pim_sec_addr_find(struct pim_interface *pim_ifp, struct prefix *addr)
|
pim_sec_addr_find(struct pim_interface *pim_ifp, struct prefix *addr)
|
||||||
{
|
{
|
||||||
struct pim_secondary_addr *sec_addr;
|
struct pim_secondary_addr *sec_addr;
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
|
|
||||||
if (!pim_ifp->sec_addr_list) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
|
for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
|
||||||
if (prefix_cmp(&sec_addr->addr, addr)) {
|
if (prefix_cmp(&sec_addr->addr, addr)) {
|
||||||
return sec_addr;
|
return sec_addr;
|
||||||
@ -383,22 +385,9 @@ static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct prefix *addr)
|
|||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pim_ifp->sec_addr_list) {
|
|
||||||
pim_ifp->sec_addr_list = list_new();
|
|
||||||
pim_ifp->sec_addr_list->del =
|
|
||||||
(void (*)(void *))pim_sec_addr_free;
|
|
||||||
pim_ifp->sec_addr_list->cmp =
|
|
||||||
(int (*)(void *, void *))pim_sec_addr_comp;
|
|
||||||
}
|
|
||||||
|
|
||||||
sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr));
|
sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr));
|
||||||
if (!sec_addr) {
|
if (!sec_addr)
|
||||||
if (list_isempty(pim_ifp->sec_addr_list)) {
|
|
||||||
list_free(pim_ifp->sec_addr_list);
|
|
||||||
pim_ifp->sec_addr_list = NULL;
|
|
||||||
}
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
|
||||||
|
|
||||||
changed = 1;
|
changed = 1;
|
||||||
sec_addr->addr = *addr;
|
sec_addr->addr = *addr;
|
||||||
@ -411,15 +400,10 @@ static int pim_sec_addr_del_all(struct pim_interface *pim_ifp)
|
|||||||
{
|
{
|
||||||
int changed = 0;
|
int changed = 0;
|
||||||
|
|
||||||
if (!pim_ifp->sec_addr_list) {
|
|
||||||
return changed;
|
|
||||||
}
|
|
||||||
if (!list_isempty(pim_ifp->sec_addr_list)) {
|
if (!list_isempty(pim_ifp->sec_addr_list)) {
|
||||||
changed = 1;
|
changed = 1;
|
||||||
/* remove all nodes and free up the list itself */
|
/* remove all nodes and free up the list itself */
|
||||||
list_delete_all_node(pim_ifp->sec_addr_list);
|
list_delete_all_node(pim_ifp->sec_addr_list);
|
||||||
list_free(pim_ifp->sec_addr_list);
|
|
||||||
pim_ifp->sec_addr_list = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
@ -434,11 +418,9 @@ static int pim_sec_addr_update(struct interface *ifp)
|
|||||||
struct pim_secondary_addr *sec_addr;
|
struct pim_secondary_addr *sec_addr;
|
||||||
int changed = 0;
|
int changed = 0;
|
||||||
|
|
||||||
if (pim_ifp->sec_addr_list) {
|
for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node,
|
||||||
for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node,
|
sec_addr)) {
|
||||||
sec_addr)) {
|
sec_addr->flags |= PIM_SEC_ADDRF_STALE;
|
||||||
sec_addr->flags |= PIM_SEC_ADDRF_STALE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
|
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
|
||||||
@ -459,20 +441,12 @@ static int pim_sec_addr_update(struct interface *ifp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pim_ifp->sec_addr_list) {
|
/* Drop stale entries */
|
||||||
/* Drop stale entries */
|
for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode,
|
||||||
for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode,
|
sec_addr)) {
|
||||||
sec_addr)) {
|
if (sec_addr->flags & PIM_SEC_ADDRF_STALE) {
|
||||||
if (sec_addr->flags & PIM_SEC_ADDRF_STALE) {
|
pim_sec_addr_del(pim_ifp, sec_addr);
|
||||||
pim_sec_addr_del(pim_ifp, sec_addr);
|
changed = 1;
|
||||||
changed = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the list went empty free it up */
|
|
||||||
if (list_isempty(pim_ifp->sec_addr_list)) {
|
|
||||||
list_free(pim_ifp->sec_addr_list);
|
|
||||||
pim_ifp->sec_addr_list = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user