summaryrefslogtreecommitdiff
path: root/pimd/pim_bsm.h
diff options
context:
space:
mode:
Diffstat (limited to 'pimd/pim_bsm.h')
-rw-r--r--pimd/pim_bsm.h187
1 files changed, 183 insertions, 4 deletions
diff --git a/pimd/pim_bsm.h b/pimd/pim_bsm.h
index fb09e3b1cc..1eacc1be57 100644
--- a/pimd/pim_bsm.h
+++ b/pimd/pim_bsm.h
@@ -21,6 +21,13 @@
#define PIM_BS_TIME 60 /* RFC 5059 - Sec 5 */
#define PIM_BSR_DEFAULT_TIMEOUT 130 /* RFC 5059 - Sec 5 */
+/* number of times to include rp-count = 0 ranges */
+#define PIM_BSR_DEAD_COUNT 3
+
+#define PIM_CRP_ADV_TRIGCOUNT 3
+#define PIM_CRP_ADV_INTERVAL 60
+#define PIM_CRP_HOLDTIME 150
+
/* 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)
@@ -33,19 +40,61 @@
* ==============
*/
-/* Non candidate BSR states */
-enum ncbsr_state {
+/* BSR states
+ *
+ * Candidate BSR starts at BSR_PENDING, moves to AP or E depending on
+ * loss/win. Will never go into AA (because in that case it'd become BSR
+ * itself.)
+ *
+ * Non-Candidate BSR starts at NO_INFO, moves to AP & AA depending on
+ * a BSR being available or not.
+ */
+enum bsr_state {
NO_INFO = 0,
ACCEPT_ANY,
- ACCEPT_PREFERRED
+ ACCEPT_PREFERRED, /* = same as C-BSR if candidate */
+ BSR_PENDING,
+ BSR_ELECTED,
+};
+
+enum cand_addr {
+ CAND_ADDR_LO = 0,
+ CAND_ADDR_ANY,
+ CAND_ADDR_IFACE,
+ CAND_ADDR_EXPLICIT,
};
+/* used separately for Cand-RP and Cand-BSR */
+struct cand_addrsel {
+ bool cfg_enable;
+ enum cand_addr cfg_mode : 8;
+
+ /* only valid for mode==CAND_ADDR_IFACE */
+ char cfg_ifname[IFNAMSIZ];
+ /* only valid for mode==CAND_ADDR_EXPLICIT */
+ pim_addr cfg_addr;
+
+ /* running state updated based on above on zebra events */
+ pim_addr run_addr;
+ bool run;
+};
+
+
PREDECL_DLIST(bsm_frags);
+PREDECL_RBTREE_UNIQ(cand_rp_groups);
+
+/* n*m "table" accessed both by-RP and by-group */
+PREDECL_RBTREE_UNIQ(bsr_crp_rps);
+PREDECL_RBTREE_UNIQ(bsr_crp_groups);
+
+PREDECL_RBTREE_UNIQ(bsr_crp_rp_groups);
+PREDECL_RBTREE_UNIQ(bsr_crp_group_rps);
/* BSM scope - bsm processing is per scope */
struct bsm_scope {
int sz_id; /* scope zone id */
- enum ncbsr_state state; /* non candidate BSR state */
+ enum bsr_state state; /* BSR state */
+
bool accept_nofwd_bsm; /* no fwd bsm accepted for scope */
pim_addr current_bsr; /* current elected BSR for the sz */
uint32_t current_bsr_prio; /* current BSR priority */
@@ -60,6 +109,93 @@ struct bsm_scope {
struct route_table *bsrp_table; /* group2rp mapping rcvd from BSR */
struct event *bs_timer; /* Boot strap timer */
+
+ /* Candidate BSR config */
+ struct cand_addrsel bsr_addrsel;
+ uint8_t cand_bsr_prio;
+
+ /* Candidate BSR state */
+ uint8_t current_cand_bsr_prio;
+ /* if nothing changed from Cand-RP data we received, less work... */
+ bool elec_rp_data_changed;
+
+ /* data that the E-BSR keeps - not to be confused with Candidate-RP
+ * stuff below. These two here are the info about all the Cand-RPs
+ * that we as a BSR received information for in Cand-RP-adv packets.
+ */
+ struct bsr_crp_rps_head ebsr_rps[1];
+ struct bsr_crp_groups_head ebsr_groups[1];
+
+ /* set if we have any group ranges where we're currently advertising
+ * rp-count = 0 (includes both ranges without any RPs as well as
+ * ranges with only NHT-unreachable RPs)
+ */
+ bool ebsr_have_dead_pending;
+ unsigned int changed_bsm_trigger;
+
+ struct event *t_ebsr_regen_bsm;
+
+ /* Candidate RP config */
+ struct cand_addrsel cand_rp_addrsel;
+ uint8_t cand_rp_prio;
+ unsigned int cand_rp_interval; /* default: PIM_CRP_ADV_INTERVAL=60 */
+ /* holdtime is not configurable, always 2.5 * interval. */
+ struct cand_rp_groups_head cand_rp_groups[1];
+
+ /* Candidate RP state */
+ int unicast_sock;
+ struct event *unicast_read;
+ struct event *cand_rp_adv_timer;
+ unsigned int cand_rp_adv_trigger; /* # trigg. C-RP-Adv left to send */
+
+ /* for sending holdtime=0 zap */
+ pim_addr cand_rp_prev_addr;
+};
+
+struct cand_rp_group {
+ struct cand_rp_groups_item item;
+
+ prefix_pim p;
+};
+
+struct bsr_crp_group {
+ struct bsr_crp_groups_item item;
+
+ prefix_pim range;
+ struct bsr_crp_group_rps_head rps[1];
+
+ size_t n_selected;
+ bool deleted_selected : 1;
+
+ /* number of times we've advertised this range with rp-count = 0 */
+ unsigned int dead_count;
+};
+
+struct bsr_crp_rp {
+ struct bsr_crp_rps_item item;
+
+ pim_addr addr;
+ struct bsr_crp_rp_groups_head groups[1];
+
+ struct bsm_scope *scope;
+ struct event *t_hold;
+ time_t seen_first;
+ time_t seen_last;
+
+ uint16_t holdtime;
+ uint8_t prio;
+ bool nht_ok;
+};
+
+/* "n * m" RP<->Group tie-in */
+struct bsr_crp_item {
+ struct bsr_crp_rp_groups_item r_g_item;
+ struct bsr_crp_group_rps_item g_r_item;
+
+ struct bsr_crp_group *group;
+ struct bsr_crp_rp *rp;
+
+ bool selected : 1;
};
/* BSM packet (= fragment) - this is stored as list in bsm_frags inside scope
@@ -200,6 +336,14 @@ struct bsmmsg_rpinfo {
uint8_t reserved;
} __attribute__((packed));
+struct cand_rp_msg {
+ uint8_t prefix_cnt;
+ uint8_t rp_prio;
+ uint16_t rp_holdtime;
+ pim_encoded_unicast rp_addr;
+ pim_encoded_group groups[0];
+} __attribute__((packed));
+
/* API */
void pim_bsm_proc_init(struct pim_instance *pim);
void pim_bsm_proc_free(struct pim_instance *pim);
@@ -210,4 +354,39 @@ int pim_bsm_process(struct interface *ifp, pim_sgaddr *sg, uint8_t *buf,
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_bsm_generate(struct bsm_scope *scope);
+void pim_bsm_changed(struct bsm_scope *scope);
+void pim_bsm_sent(struct bsm_scope *scope);
+void pim_bsm_frags_free(struct bsm_scope *scope);
+
+bool pim_bsm_parse_install_g2rp(struct bsm_scope *scope, uint8_t *buf,
+ int buflen, uint16_t bsm_frag_tag);
+
+void pim_cand_bsr_apply(struct bsm_scope *scope);
+void pim_cand_rp_apply(struct bsm_scope *scope);
+void pim_cand_rp_trigger(struct bsm_scope *scope);
+void pim_cand_rp_grp_add(struct bsm_scope *scope, const prefix_pim *p);
+void pim_cand_rp_grp_del(struct bsm_scope *scope, const prefix_pim *p);
+
+void pim_cand_addrs_changed(void);
+
+int pim_crp_process(struct interface *ifp, pim_sgaddr *src_dst, uint8_t *buf,
+ uint32_t buf_size);
+
+struct pim_nexthop_cache;
+void pim_crp_nht_update(struct pim_instance *pim, struct pim_nexthop_cache *pnc);
+
+void pim_crp_db_clear(struct bsm_scope *scope);
+int pim_crp_db_show(struct vty *vty, struct bsm_scope *scope, bool json);
+int pim_crp_groups_show(struct vty *vty, struct bsm_scope *scope, bool json);
+
+int pim_cand_config_write(struct pim_instance *pim, struct vty *vty);
+
+DECLARE_MTYPE(PIM_BSM_FRAG);
+
+DECLARE_MTYPE(PIM_BSM_FRAG);
+
+DECLARE_MTYPE(PIM_BSM_FRAG);
+
#endif