diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c index f43a31fde2..3fabd10ba2 100644 --- a/pimd/pim_bsm.c +++ b/pimd/pim_bsm.c @@ -44,7 +44,7 @@ static inline void pim_g2rp_timer_restart(struct bsm_rpinfo *bsrp, /* Memory Types */ DEFINE_MTYPE_STATIC(PIMD, PIM_BSGRP_NODE, "PIM BSR advertised grp info"); DEFINE_MTYPE_STATIC(PIMD, PIM_BSRP_NODE, "PIM BSR advertised RP info"); -DEFINE_MTYPE_STATIC(PIMD, PIM_BSM_INFO, "PIM BSM Info"); +DEFINE_MTYPE_STATIC(PIMD, PIM_BSM_FRAG, "PIM BSM fragment"); DEFINE_MTYPE_STATIC(PIMD, PIM_BSM_PKT_VAR_MEM, "PIM BSM Packet"); /* All bsm packets forwarded shall be fit within ip mtu less iphdr(max) */ @@ -84,10 +84,17 @@ void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp) } } -static void pim_bsm_node_free(struct bsm_info *bsm) +static void pim_bsm_frag_free(struct bsm_frag *bsfrag) { - XFREE(MTYPE_PIM_BSM_PKT_VAR_MEM, bsm->bsm); - XFREE(MTYPE_PIM_BSM_INFO, bsm); + XFREE(MTYPE_PIM_BSM_FRAG, bsfrag); +} + +void pim_bsm_frags_free(struct bsm_scope *scope) +{ + struct bsm_frag *bsfrag; + + while ((bsfrag = bsm_frags_pop(scope->bsm_frags))) + pim_bsm_frag_free(bsfrag); } static int pim_g2rp_list_compare(struct bsm_rpinfo *node1, @@ -197,7 +204,7 @@ static int pim_on_bs_timer(struct thread *t) scope->current_bsr_first_ts = 0; scope->current_bsr_last_ts = 0; scope->bsm_frag_tag = 0; - list_delete_all_node(scope->bsm_list); + pim_bsm_frags_free(scope); for (rn = route_top(scope->bsrp_table); rn; rn = route_next(rn)) { @@ -260,8 +267,7 @@ void pim_bsm_proc_init(struct pim_instance *pim) pim->global_scope.accept_nofwd_bsm = true; pim->global_scope.state = NO_INFO; pim->global_scope.pim = pim; - pim->global_scope.bsm_list = list_new(); - pim->global_scope.bsm_list->del = (void (*)(void *))pim_bsm_node_free; + bsm_frags_init(pim->global_scope.bsm_frags); pim_bs_timer_start(&pim->global_scope, PIM_BS_TIME); } @@ -271,9 +277,7 @@ void pim_bsm_proc_free(struct pim_instance *pim) struct bsgrp_node *bsgrp; pim_bs_timer_stop(&pim->global_scope); - - if (pim->global_scope.bsm_list) - list_delete(&pim->global_scope.bsm_list); + pim_bsm_frags_free(&pim->global_scope); for (rn = route_top(pim->global_scope.bsrp_table); rn; rn = route_next(rn)) { @@ -896,8 +900,7 @@ bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp) struct in_addr dst_addr; struct pim_interface *pim_ifp; struct bsm_scope *scope; - struct listnode *bsm_ln; - struct bsm_info *bsminfo; + struct bsm_frag *bsfrag; char neigh_src_str[INET_ADDRSTRLEN]; uint32_t pim_mtu; bool no_fwd = true; @@ -929,7 +932,7 @@ bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp) scope = &pim_ifp->pim->global_scope; - if (!scope->bsm_list->count) { + if (!bsm_frags_count(scope->bsm_frags)) { if (PIM_DEBUG_BSM) zlog_debug("%s: BSM list for the scope is empty", __func__); @@ -950,10 +953,10 @@ bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp) pim_mtu = ifp->mtu - MAX_IP_HDR_LEN; pim_hello_require(ifp); - for (ALL_LIST_ELEMENTS_RO(scope->bsm_list, bsm_ln, bsminfo)) { - if (pim_mtu < bsminfo->size) { - ret = pim_bsm_frag_send(bsminfo->bsm, bsminfo->size, - ifp, pim_mtu, dst_addr, no_fwd); + frr_each (bsm_frags, scope->bsm_frags, bsfrag) { + if (pim_mtu < bsfrag->size) { + ret = pim_bsm_frag_send(bsfrag->data, bsfrag->size, ifp, + pim_mtu, dst_addr, no_fwd); if (!ret) { if (PIM_DEBUG_BSM) zlog_debug( @@ -962,10 +965,10 @@ bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp) } } else { /* Pim header needs to be constructed */ - pim_msg_build_header(bsminfo->bsm, bsminfo->size, + pim_msg_build_header(bsfrag->data, bsfrag->size, PIM_MSG_TYPE_BOOTSTRAP, no_fwd); - ret = pim_bsm_send_intf(bsminfo->bsm, bsminfo->size, - ifp, dst_addr); + ret = pim_bsm_send_intf(bsfrag->data, bsfrag->size, ifp, + dst_addr); if (!ret) { if (PIM_DEBUG_BSM) zlog_debug( @@ -1227,7 +1230,7 @@ int pim_bsm_process(struct interface *ifp, struct ip *ip_hdr, uint8_t *buf, int sz = PIM_GBL_SZ_ID; struct bsmmsg_grpinfo *msg_grp; struct pim_interface *pim_ifp = NULL; - struct bsm_info *bsminfo; + struct bsm_frag *bsfrag; struct pim_instance *pim; char bsr_str[INET_ADDRSTRLEN]; uint16_t frag_tag; @@ -1383,7 +1386,7 @@ int pim_bsm_process(struct interface *ifp, struct ip *ip_hdr, uint8_t *buf, pim_ifp->pim->global_scope.bsm_frag_tag, frag_tag); } - list_delete_all_node(pim_ifp->pim->global_scope.bsm_list); + pim_bsm_frags_free(&pim_ifp->pim->global_scope); pim_ifp->pim->global_scope.bsm_frag_tag = frag_tag; } @@ -1392,13 +1395,13 @@ int pim_bsm_process(struct interface *ifp, struct ip *ip_hdr, uint8_t *buf, if (!no_fwd) { pim_bsm_fwd_whole_sz(pim_ifp->pim, buf, buf_size, sz); - bsminfo = XCALLOC(MTYPE_PIM_BSM_INFO, sizeof(struct bsm_info)); + bsfrag = XCALLOC(MTYPE_PIM_BSM_FRAG, + sizeof(struct bsm_frag) + buf_size); - bsminfo->bsm = XCALLOC(MTYPE_PIM_BSM_PKT_VAR_MEM, buf_size); - - bsminfo->size = buf_size; - memcpy(bsminfo->bsm, buf, buf_size); - listnode_add(pim_ifp->pim->global_scope.bsm_list, bsminfo); + bsfrag->size = buf_size; + memcpy(bsfrag->data, buf, buf_size); + bsm_frags_add_tail(pim_ifp->pim->global_scope.bsm_frags, + bsfrag); } return 0; diff --git a/pimd/pim_bsm.h b/pimd/pim_bsm.h index ac12cd032f..eee2a652dd 100644 --- a/pimd/pim_bsm.h +++ b/pimd/pim_bsm.h @@ -25,6 +25,7 @@ #include "if.h" #include "vty.h" +#include "typesafe.h" #include "linklist.h" #include "table.h" #include "pim_rp.h" @@ -54,6 +55,8 @@ enum ncbsr_state { ACCEPT_PREFERRED }; +PREDECL_DLIST(bsm_frags); + /* BSM scope - bsm processing is per scope */ struct bsm_scope { int sz_id; /* scope zone id */ @@ -66,19 +69,26 @@ struct bsm_scope { uint16_t bsm_frag_tag; /* Last received frag tag from E-BSR */ uint8_t hashMasklen; /* Mask in hash calc RFC 7761 4.7.2 */ struct pim_instance *pim; /* Back pointer to pim instance */ - struct list *bsm_list; /* list of bsm frag for frowarding */ + + /* current set of fragments for forwarding */ + struct bsm_frags_head bsm_frags[1]; + struct route_table *bsrp_table; /* group2rp mapping rcvd from BSR */ struct thread *bs_timer; /* Boot strap timer */ }; -/* BSM packet - this is stored as list in bsm_list inside scope +/* BSM packet (= fragment) - this is stored as list in bsm_frags inside scope * This is used for forwarding to new neighbors or restarting mcast routers */ -struct bsm_info { - uint32_t size; /* size of the packet */ - unsigned char *bsm; /* Actual packet */ +struct bsm_frag { + struct bsm_frags_item item; + + uint32_t size; /* size of the packet */ + uint8_t data[0]; /* Actual packet (dyn size) */ }; +DECLARE_DLIST(bsm_frags, struct bsm_frag, item); + /* This is the group node of the bsrp table in scope. * this node maintains the list of rp for the group. */ @@ -195,6 +205,7 @@ bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp); struct bsgrp_node *pim_bsm_get_bsgrp_node(struct bsm_scope *scope, struct prefix *grp); void pim_bs_timer_stop(struct bsm_scope *scope); +void pim_bsm_frags_free(struct bsm_scope *scope); void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node); void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp); #endif diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index c01cfec88e..9682746da9 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3000,15 +3000,14 @@ static void pim_show_nexthop(struct pim_instance *pim, struct vty *vty) /* Display the bsm database details */ static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj) { - struct listnode *bsmnode; int count = 0; int fragment = 1; - struct bsm_info *bsm; + struct bsm_frag *bsfrag; json_object *json = NULL; json_object *json_group = NULL; json_object *json_row = NULL; - count = pim->global_scope.bsm_list->count; + count = bsm_frags_count(pim->global_scope.bsm_frags); if (uj) { json = json_object_new_object(); @@ -3019,7 +3018,7 @@ static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj) vty_out(vty, "\n"); } - for (ALL_LIST_ELEMENTS_RO(pim->global_scope.bsm_list, bsmnode, bsm)) { + frr_each (bsm_frags, pim->global_scope.bsm_frags, bsfrag) { char grp_str[PREFIX_STRLEN]; char rp_str[INET_ADDRSTRLEN]; char bsr_str[INET_ADDRSTRLEN]; @@ -3032,8 +3031,8 @@ static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj) uint32_t len = 0; uint32_t frag_rp_cnt = 0; - buf = bsm->bsm; - len = bsm->size; + buf = bsfrag->data; + len = bsfrag->size; /* skip pim header */ buf += PIM_MSG_HEADER_LEN; @@ -4083,7 +4082,7 @@ static void clear_pim_bsr_db(struct pim_instance *pim) pim->global_scope.current_bsr_first_ts = 0; pim->global_scope.current_bsr_last_ts = 0; pim->global_scope.bsm_frag_tag = 0; - list_delete_all_node(pim->global_scope.bsm_list); + pim_bsm_frags_free(&pim->global_scope); pim_bs_timer_stop(&pim->global_scope);