summaryrefslogtreecommitdiffstats
path: root/pimd/pim_bsm.h
blob: 27714ab459c18c1a3aeb367088fe248abd2bfdd2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * pim_bsm.h: PIM BSM handling related
 *
 * Copyright (C) 2018-19 Vmware, Inc.
 * Saravanan K
 */

#ifndef __PIM_BSM_H__
#define __PIM_BSM_H__

#include "if.h"
#include "vty.h"
#include "typesafe.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 */

#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)
#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
};

enum cand_addr {
	CAND_ADDR_LO = 0,
	CAND_ADDR_ANY,
	CAND_ADDR_IFACE,
	CAND_ADDR_EXPLICIT,
};

/* used separately for Cand-RP, and (TBD) 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);

/* 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 */
	pim_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 */

	/* current set of fragments for forwarding */
	struct bsm_frags_head bsm_frags[1];

	struct route_table *bsrp_table; /* group2rp mapping rcvd from BSR */
	struct event *bs_timer;		/* Boot strap timer */

	/* 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 *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;
};

/* 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_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);

PREDECL_SORTLIST_UNIQ(bsm_rpinfos);

/* 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 */

	/* RPs advertised by BSR, and temporary list while receiving new set */
	struct bsm_rpinfos_head bsrp_list[1];
	struct bsm_rpinfos_head partial_bsrp_list[1];

	int pend_rp_cnt;		/* Total RP - Received RP */
	uint16_t frag_tag;		/* frag tag to identify the fragment */
};

/* Items on [partial_]bsrp_list above.
 * Holds info of each candidate RP received for the bsgrp_node's prefix.
 */
struct bsm_rpinfo {
	struct bsm_rpinfos_item item;

	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 */
	pim_addr rp_address;		/* RP Address */
	struct bsgrp_node *bsgrp_node;  /* Back ptr to bsgrp_node */
	struct event *g2rp_timer;	/* Run only for elected RP node */
};

extern int pim_bsm_rpinfo_cmp(const struct bsm_rpinfo *a,
			      const struct bsm_rpinfo *b);
DECLARE_SORTLIST_UNIQ(bsm_rpinfos, struct bsm_rpinfo, item, pim_bsm_rpinfo_cmp);

/*  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;
#if PIM_IPV == 4
	struct pim_encoded_ipv4_unicast bsr_addr;
#else
	struct pim_encoded_ipv6_unicast bsr_addr;
#endif
} __attribute__((packed));

struct bsmmsg_grpinfo {
#if PIM_IPV == 4
	struct pim_encoded_group_ipv4 group;
#else
	struct pim_encoded_group_ipv6 group;
#endif
	uint8_t rp_count;
	uint8_t frag_rp_count;
	uint16_t reserved;
} __attribute__((packed));

struct bsmmsg_rpinfo {
#if PIM_IPV == 4
	struct pim_encoded_ipv4_unicast rpaddr;
#else
	struct pim_encoded_ipv6_unicast rpaddr;
#endif
	uint16_t rp_holdtime;
	uint8_t rp_pri;
	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);
void pim_bsm_clear(struct pim_instance *pim);
void pim_bsm_write_config(struct vty *vty, struct interface *ifp);
int pim_bsm_process(struct interface *ifp, pim_sgaddr *sg, uint8_t *buf,
		    uint32_t buf_size, bool no_fwd);
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_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_cand_config_write(struct pim_instance *pim, struct vty *vty);

#endif