diff options
author | saravanank <saravanank@vmware.com> | 2019-05-02 04:24:14 +0200 |
---|---|---|
committer | saravanank <saravanank@vmware.com> | 2019-05-15 05:23:15 +0200 |
commit | 361b5843947b44fad4fe19065a5c39fb59b9782a (patch) | |
tree | c356e9b343bc220d01130938d7c1f5f04b6dc647 | |
parent | pimd: adding datastructure to accomodate to source of RP. (diff) | |
download | frr-361b5843947b44fad4fe19065a5c39fb59b9782a.tar.xz frr-361b5843947b44fad4fe19065a5c39fb59b9782a.zip |
pimd: PIM BSM Processing datastructure definition/initialization/deinit
Apart from datastructure, bsm scope initialization and deinitialiation
routines called during pim instance init and deinit. Also makefile changes.
Signed-off-by: Saravanan K <saravanank@vmware.com>
-rw-r--r-- | pimd/pim_bsm.c | 122 | ||||
-rw-r--r-- | pimd/pim_bsm.h | 191 | ||||
-rw-r--r-- | pimd/pim_cmd.h | 2 | ||||
-rw-r--r-- | pimd/pim_instance.c | 5 | ||||
-rw-r--r-- | pimd/pim_instance.h | 6 | ||||
-rw-r--r-- | pimd/pim_memory.c | 4 | ||||
-rw-r--r-- | pimd/pim_memory.h | 4 | ||||
-rw-r--r-- | pimd/pimd.h | 6 | ||||
-rw-r--r-- | pimd/subdir.am | 2 |
9 files changed, 341 insertions, 1 deletions
diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c new file mode 100644 index 000000000..52331625a --- /dev/null +++ b/pimd/pim_bsm.c @@ -0,0 +1,122 @@ +/* + * pim_bsm.c: PIM BSM handling routines + * + * Copyright (C) 2018-19 Vmware, Inc. + * Saravanan K + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +#include "if.h" +#include "pimd.h" +#include "pim_iface.h" +#include "pim_cmd.h" +#include "pim_instance.h" +#include "pim_rpf.h" +#include "pim_hello.h" +#include "pim_pim.h" +#include "pim_nht.h" +#include "pim_bsm.h" +#include "pim_time.h" + +/* Functions forward declaration */ +static void pim_bs_timer_start(struct bsm_scope *scope, int bs_timeout); +static int pim_on_bs_timer(struct thread *t); +static void pim_bs_timer_stop(struct bsm_scope *scope); + +static void pim_free_bsgrp_data(struct bsgrp_node * bsgrp_node) +{ + if (bsgrp_node->bsrp_list) + list_delete(&bsgrp_node->bsrp_list); + if (bsgrp_node->partial_bsrp_list) + list_delete(&bsgrp_node->partial_bsrp_list); + + XFREE(MTYPE_PIM_BSGRP_NODE, bsgrp_node); +} + +static void pim_bsm_node_free(struct bsm_info *bsm) +{ + if (bsm->bsm) + XFREE(MTYPE_PIM_BSM_PKT_VAR_MEM, bsm->bsm); + XFREE(MTYPE_PIM_BSM_INFO, bsm); +} + +void pim_bsm_proc_init(struct pim_instance *pim) +{ + memset(&pim->global_scope, 0, sizeof(struct bsm_scope)); + + pim->global_scope.sz_id = PIM_GBL_SZ_ID; + pim->global_scope.bsrp_table = route_table_init(); + 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; + pim_bs_timer_start(&pim->global_scope, PIM_BS_TIME); +} + +void pim_bsm_proc_free(struct pim_instance *pim) +{ + struct route_node *rn; + struct bsgrp_node *bsgrp; + + pim_bs_timer_stop(&pim->global_scope); + + if (pim->global_scope.bsm_list) + list_delete(&pim->global_scope.bsm_list); + + for(rn = route_top(pim->global_scope.bsrp_table); + rn; rn = route_next(rn)) { + bsgrp = rn->info; + if (!bsgrp) + continue; + pim_free_bsgrp_data(bsgrp); + } + + if (pim->global_scope.bsrp_table) + route_table_finish(pim->global_scope.bsrp_table); +} + +static int pim_on_bs_timer(struct thread *t) +{ + return 0; +} + +static void pim_bs_timer_stop(struct bsm_scope *scope) +{ + if (PIM_DEBUG_BSM) + zlog_debug("%s : BS timer being stopped of sz: %d", + __PRETTY_FUNCTION__, + scope->sz_id); + THREAD_OFF(scope->bs_timer); +} + +static void pim_bs_timer_start(struct bsm_scope *scope, int bs_timeout) +{ + if (!scope) { + if (PIM_DEBUG_BSM) + zlog_debug("%s : Invalid scope(NULL).", + __PRETTY_FUNCTION__); + } + + THREAD_OFF(scope->bs_timer); + + if (PIM_DEBUG_BSM) + zlog_debug("%s : starting bs timer for scope %d with timeout %d secs", + __PRETTY_FUNCTION__, scope->sz_id, bs_timeout); + thread_add_timer(router->master, pim_on_bs_timer, scope, bs_timeout, + &scope->bs_timer); +} + diff --git a/pimd/pim_bsm.h b/pimd/pim_bsm.h new file mode 100644 index 000000000..1ab50c8b2 --- /dev/null +++ b/pimd/pim_bsm.h @@ -0,0 +1,191 @@ +/* + * pim_bsm.h: PIM BSM handling related + * + * Copyright (C) 2018-19 Vmware, Inc. + * Saravanan K + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifndef __PIM_BSM_H__ +#define __PIM_BSM_H__ + +#include "if.h" +#include "vty.h" +#include "linklist.h" +#include "table.h" +#include "pim_rp.h" +#include "pim_msg.h" + +/* Defines */ +#define PIM_GBL_SZ_ID 0 /* global scope zone id set to 0 */ +#define PIM_BS_TIME 60 /* RFC 5059 - Sec 5 */ +#define PIM_BSR_DEFAULT_TIMEOUT 130 /* RFC 5059 - Sec 5 */ + +/* These structures are only encoded IPv4 specific */ +#define PIM_BSM_HDR_LEN sizeof(struct bsm_hdr) +#define PIM_BSM_GRP_LEN sizeof(struct bsmmsg_grpinfo) +#define PIM_BSM_RP_LEN sizeof(struct bsmmsg_rpinfo) + +#define PIM_MIN_BSM_LEN (PIM_HDR_LEN + \ + PIM_BSM_HDR_LEN + \ + PIM_BSM_GRP_LEN + \ + PIM_BSM_RP_LEN) +/* Datastructures + * ============== + */ + +/* Non candidate BSR states */ +enum ncbsr_state{ + NO_INFO = 0, + ACCEPT_ANY, + ACCEPT_PREFERRED +}; + +/* BSM scope - bsm processing is per scope */ +struct bsm_scope { + int sz_id; /* scope zone id */ + enum ncbsr_state state; /* non candidate BSR state */ + bool accept_nofwd_bsm; /* no fwd bsm accepted for scope */ + struct in_addr current_bsr; /* current elected BSR for the sz */ + uint32_t current_bsr_prio; /* current BSR priority */ + int64_t current_bsr_first_ts; /* current BSR elected time */ + int64_t current_bsr_last_ts; /* Last BSM received from E-BSR */ + 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 */ + struct route_table *bsrp_table; /* group2rp mapping rcvd from BSR */ + struct thread *bs_timer; /* Boot strap timer */ + struct thread *sz_timer; +}; + +/* BSM packet - this is stored as list in bsm_list 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 */ +}; + +/* This is the group node of the bsrp table in scope. + * this node maintains the list of rp for the group. + */ +struct bsgrp_node { + struct prefix group; /* Group range */ + struct bsm_scope *scope; /* Back ptr to scope */ + struct list *bsrp_list; /* list of RPs adv by BSR */ + struct list *partial_bsrp_list; /* maintained until all RPs received */ + int pend_rp_cnt; /* Total RP - Received RP */ + uint16_t frag_tag; /* frag tag to identify the fragment */ +}; + +/* This is the list node of bsrp_list and partial bsrp list in + * bsgrp_node. Hold info of each RP received for the group + */ +struct bsm_rpinfo { + uint32_t hash; /* Hash Value as per RFC 7761 4.7.2 */ + uint32_t elapse_time; /* upd at expiry of elected RP node */ + uint16_t rp_prio; /* RP priority */ + uint16_t rp_holdtime; /* RP holdtime - g2rp timer value */ + struct in_addr rp_address; /* RP Address */ + struct bsgrp_node *bsgrp_node; /* Back ptr to bsgrp_node */ + struct thread *g2rp_timer; /* Run only for elected RP node */ +}; + +/* Structures to extract Bootstrap Message header and Grp to RP Mappings + * ===================================================================== + * BSM Format: + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |PIM Ver| Type |N| Reserved | Checksum | PIM HDR + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Fragment Tag | Hash Mask Len | BSR Priority | BS HDR(1) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | BSR Address (Encoded-Unicast format) | BS HDR(2) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Group Address 1 (Encoded-Group format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RP Count 1 | Frag RP Cnt 1 | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RP Address 1 (Encoded-Unicast format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RP1 Holdtime | RP1 Priority | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RP Address 2 (Encoded-Unicast format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RP2 Holdtime | RP2 Priority | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | . | + * | . | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RP Address m (Encoded-Unicast format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RPm Holdtime | RPm Priority | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Group Address 2 (Encoded-Group format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | . | + * | . | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Group Address n (Encoded-Group format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RP Count n | Frag RP Cnt n | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RP Address 1 (Encoded-Unicast format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RP1 Holdtime | RP1 Priority | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RP Address 2 (Encoded-Unicast format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RP2 Holdtime | RP2 Priority | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | . | + * | . | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RP Address m (Encoded-Unicast format) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RPm Holdtime | RPm Priority | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +struct bsm_hdr { + uint16_t frag_tag; + uint8_t hm_len; + uint8_t bsr_prio; + struct pim_encoded_ipv4_unicast bsr_addr; +}__attribute__((packed)); + +struct bsmmsg_grpinfo { + struct pim_encoded_group_ipv4 group; + uint8_t rp_count; + uint8_t frag_rp_count; + uint16_t reserved; +}__attribute__((packed)); + +struct bsmmsg_rpinfo { + struct pim_encoded_ipv4_unicast rpaddr; + uint16_t rp_holdtime; + uint8_t rp_pri; + uint8_t reserved; +}__attribute__((packed)); + +/* API */ +void pim_bsm_proc_init(struct pim_instance *pim); +void pim_bsm_proc_free(struct pim_instance *pim); + +#endif diff --git a/pimd/pim_cmd.h b/pimd/pim_cmd.h index 67d6e43c3..558f28231 100644 --- a/pimd/pim_cmd.h +++ b/pimd/pim_cmd.h @@ -65,6 +65,8 @@ #define DEBUG_MSDP_INTERNAL_STR "MSDP protocol internal\n" #define DEBUG_MSDP_PACKETS_STR "MSDP protocol packets\n" #define DEBUG_MTRACE_STR "Mtrace protocol activity\n" +#define DEBUG_PIM_BSM_STR "BSR message processing activity\n" + void pim_cmd_init(void); diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c index a2bf3d278..6848d2dab 100644 --- a/pimd/pim_instance.c +++ b/pimd/pim_instance.c @@ -33,6 +33,7 @@ #include "pim_static.h" #include "pim_ssmpingd.h" #include "pim_vty.h" +#include "pim_bsm.h" static void pim_instance_terminate(struct pim_instance *pim) { @@ -50,6 +51,8 @@ static void pim_instance_terminate(struct pim_instance *pim) pim_rp_free(pim); + pim_bsm_proc_free(pim); + /* Traverse and cleanup rpf_hash */ if (pim->rpf_hash) { hash_clean(pim->rpf_hash, (void *)pim_rp_list_hash_clean); @@ -106,6 +109,8 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf) pim_rp_init(pim); + pim_bsm_proc_init(pim); + pim_oil_init(pim); pim_upstream_init(pim); diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h index 1740bcc79..06d41c4b5 100644 --- a/pimd/pim_instance.h +++ b/pimd/pim_instance.h @@ -26,6 +26,7 @@ #include "pim_str.h" #include "pim_msdp.h" #include "pim_assert.h" +#include "pim_bsm.h" #include "pim_vxlan_instance.h" #if defined(HAVE_LINUX_MROUTE_H) @@ -121,6 +122,11 @@ struct pim_instance { bool ecmp_enable; bool ecmp_rebalance_enable; + /* Bsm related */ + struct bsm_scope global_scope; + uint64_t bsm_rcvd; + uint64_t bsm_sent; + uint64_t bsm_dropped; /* If we need to rescan all our upstreams */ struct thread *rpf_cache_refresher; diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c index 2bbab67e4..0562dba70 100644 --- a/pimd/pim_memory.c +++ b/pimd/pim_memory.c @@ -53,3 +53,7 @@ DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE, "PIM nexthop cache state") DEFINE_MTYPE(PIMD, PIM_SSM_INFO, "PIM SSM configuration") DEFINE_MTYPE(PIMD, PIM_SPT_PLIST_NAME, "PIM SPT Prefix List Name") DEFINE_MTYPE(PIMD, PIM_VXLAN_SG, "PIM VxLAN mroute cache") +DEFINE_MTYPE(PIMD, PIM_BSGRP_NODE, "PIM BSR advertised grp info") +DEFINE_MTYPE(PIMD, PIM_BSRP_NODE, "PIM BSR advertised RP info") +DEFINE_MTYPE(PIMD, PIM_BSM_INFO, "PIM BSM Info") +DEFINE_MTYPE(PIMD, PIM_BSM_PKT_VAR_MEM, "PIM BSM Packet") diff --git a/pimd/pim_memory.h b/pimd/pim_memory.h index e5ca57a15..9495db43b 100644 --- a/pimd/pim_memory.h +++ b/pimd/pim_memory.h @@ -52,5 +52,9 @@ DECLARE_MTYPE(PIM_NEXTHOP_CACHE) DECLARE_MTYPE(PIM_SSM_INFO) DECLARE_MTYPE(PIM_SPT_PLIST_NAME); DECLARE_MTYPE(PIM_VXLAN_SG) +DECLARE_MTYPE(PIM_BSRP_NODE) +DECLARE_MTYPE(PIM_BSGRP_NODE) +DECLARE_MTYPE(PIM_BSM_INFO) +DECLARE_MTYPE(PIM_BSM_PKT_VAR_MEM) #endif /* _QUAGGA_PIM_MEMORY_H */ diff --git a/pimd/pimd.h b/pimd/pimd.h index 2f2a87037..cdeaed397 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -114,6 +114,7 @@ #define PIM_MASK_PIM_NHT_RP (1 << 24) #define PIM_MASK_MTRACE (1 << 25) #define PIM_MASK_VXLAN (1 << 26) +#define PIM_MASK_BSM_PROC (1 << 27) /* Remember 32 bits!!! */ /* PIM error codes */ @@ -182,11 +183,12 @@ extern uint8_t qpim_ecmp_rebalance_enable; #define PIM_DEBUG_PIM_NHT_RP (router->debugs & PIM_MASK_PIM_NHT_RP) #define PIM_DEBUG_MTRACE (router->debugs & PIM_MASK_MTRACE) #define PIM_DEBUG_VXLAN (router->debugs & PIM_MASK_VXLAN) +#define PIM_DEBUG_BSM (router->debugs & PIM_MASK_BSM_PROC) #define PIM_DEBUG_EVENTS \ (router->debugs \ & (PIM_MASK_PIM_EVENTS | PIM_MASK_IGMP_EVENTS \ - | PIM_MASK_MSDP_EVENTS)) + | PIM_MASK_MSDP_EVENTS | PIM_MASK_BSM_PROC)) #define PIM_DEBUG_PACKETS \ (router->debugs \ & (PIM_MASK_PIM_PACKETS | PIM_MASK_IGMP_PACKETS \ @@ -212,6 +214,7 @@ extern uint8_t qpim_ecmp_rebalance_enable; #define PIM_DO_DEBUG_SSMPINGD (router->debugs |= PIM_MASK_SSMPINGD) #define PIM_DO_DEBUG_MROUTE (router->debugs |= PIM_MASK_MROUTE) #define PIM_DO_DEBUG_MROUTE_DETAIL (router->debugs |= PIM_MASK_MROUTE_DETAIL) +#define PIM_DO_DEBUG_BSM (router->debugs |= PIM_MASK_BSM_PROC) #define PIM_DO_DEBUG_PIM_HELLO (router->debugs |= PIM_MASK_PIM_HELLO) #define PIM_DO_DEBUG_PIM_J_P (router->debugs |= PIM_MASK_PIM_J_P) #define PIM_DO_DEBUG_PIM_REG (router->debugs |= PIM_MASK_PIM_REG) @@ -253,6 +256,7 @@ extern uint8_t qpim_ecmp_rebalance_enable; #define PIM_DONT_DEBUG_PIM_NHT_RP (router->debugs &= ~PIM_MASK_PIM_NHT_RP) #define PIM_DONT_DEBUG_MTRACE (router->debugs &= ~PIM_MASK_MTRACE) #define PIM_DONT_DEBUG_VXLAN (router->debugs &= ~PIM_MASK_VXLAN) +#define PIM_DONT_DEBUG_BSM (router->debugs &= ~PIM_MASK_BSM_PROC) void pim_router_init(void); void pim_router_terminate(void); diff --git a/pimd/subdir.am b/pimd/subdir.am index 7f4810722..240b62804 100644 --- a/pimd/subdir.am +++ b/pimd/subdir.am @@ -17,6 +17,7 @@ pimd_libpim_a_SOURCES = \ pimd/pim_assert.c \ pimd/pim_bfd.c \ pimd/pim_br.c \ + pimd/pim_bsm.c \ pimd/pim_cmd.c \ pimd/pim_errors.c \ pimd/pim_hello.c \ @@ -68,6 +69,7 @@ noinst_HEADERS += \ pimd/pim_assert.h \ pimd/pim_bfd.h \ pimd/pim_br.h \ + pimd/pim_bsm.h \ pimd/pim_cmd.h \ pimd/pim_errors.h \ pimd/pim_hello.h \ |