summaryrefslogtreecommitdiffstats
path: root/zebra/zebra_router.h
blob: bd86cfb495191b5a09c530837e587c04a2adf409 (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
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
// SPDX-License-Identifier: GPL-2.0-or-later
/* Zebra Router header.
 * Copyright (C) 2018 Cumulus Networks, Inc.
 *                    Donald Sharp
 */
#ifndef __ZEBRA_ROUTER_H__
#define __ZEBRA_ROUTER_H__

#include "lib/mlag.h"

#include "zebra/zebra_ns.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * This header file contains the idea of a router and as such
 * owns data that is associated with a router from zebra's
 * perspective.
 */

struct zebra_router_table {
	RB_ENTRY(zebra_router_table) zebra_router_table_entry;

	uint32_t tableid;
	afi_t afi;
	safi_t safi;
	ns_id_t ns_id;

	struct route_table *table;
};
RB_HEAD(zebra_router_table_head, zebra_router_table);
RB_PROTOTYPE(zebra_router_table_head, zebra_router_table,
	     zebra_router_table_entry, zebra_router_table_entry_compare)

/* RPF lookup behaviour */
enum multicast_mode {
	MCAST_NO_CONFIG = 0,  /* MIX_MRIB_FIRST, but no show in config write */
	MCAST_MRIB_ONLY,      /* MRIB only */
	MCAST_URIB_ONLY,      /* URIB only */
	MCAST_MIX_MRIB_FIRST, /* MRIB, if nothing at all then URIB */
	MCAST_MIX_DISTANCE,   /* MRIB & URIB, lower distance wins */
	MCAST_MIX_PFXLEN,     /* MRIB & URIB, longer prefix wins */
			      /* on equal value, MRIB wins for last 2 */
};

/* An interface can be error-disabled if a protocol (such as EVPN or
 * VRRP) detects a problem with keeping it operationally-up.
 * If any of the protodown bits are set protodown-on is programmed
 * in the dataplane. This results in a carrier/L1 down on the
 * physical device.
 */
enum protodown_reasons {
	/* A process outside of FRR's control protodowned the interface */
	ZEBRA_PROTODOWN_EXTERNAL = (1 << 0),
	/* On startup local ESs are held down for some time to
	 * allow the underlay to converge and EVPN routes to
	 * get learnt
	 */
	ZEBRA_PROTODOWN_EVPN_STARTUP_DELAY = (1 << 1),
	/* If all the uplinks are down the switch has lost access
	 * to the VxLAN overlay and must shut down the access
	 * ports to allow servers to re-direct their traffic to
	 * other switches on the Ethernet Segment
	 */
	ZEBRA_PROTODOWN_EVPN_UPLINK_DOWN = (1 << 2),
	ZEBRA_PROTODOWN_EVPN_ALL = (ZEBRA_PROTODOWN_EVPN_UPLINK_DOWN |
				    ZEBRA_PROTODOWN_EVPN_STARTUP_DELAY),
	ZEBRA_PROTODOWN_VRRP = (1 << 3),
	/* This reason used exclusively for testing */
	ZEBRA_PROTODOWN_SHARP = (1 << 4),
	/* Just used to clear our fields on shutdown, externel not included */
	ZEBRA_PROTODOWN_ALL = (ZEBRA_PROTODOWN_EVPN_ALL | ZEBRA_PROTODOWN_VRRP |
			       ZEBRA_PROTODOWN_SHARP)
};
#define ZEBRA_PROTODOWN_RC_STR_LEN 80

struct zebra_mlag_info {
	/* Role this zebra router is playing */
	enum mlag_role role;

	/* The peerlink being used for mlag */
	char *peerlink;
	ifindex_t peerlink_ifindex;

	/* The system mac being used */
	struct ethaddr mac;
	/*
	 * Zebra will open the communication channel with MLAGD only if any
	 * clients are interested and it is controlled dynamically based on
	 * client registers & un-registers.
	 */
	uint32_t clients_interested_cnt;

	/* coomunication channel with MLAGD is established */
	bool connected;

	/* connection retry timer is running */
	bool timer_running;

	/* Holds the client data(unencoded) that need to be pushed to MCLAGD*/
	struct stream_fifo *mlag_fifo;

	/*
	 * A new Kernel thread will be created to post the data to MCLAGD.
	 * where as, read will be performed from the zebra main thread, because
	 * read involves accessing client registartion data structures.
	 */
	struct frr_pthread *zebra_pth_mlag;

	/* MLAG Thread context 'master' */
	struct event_loop *th_master;

	/*
	 * Event for Initial MLAG Connection setup & Data Read
	 * Read can be performed only after successful connection establishment,
	 * so no issues.
	 *
	 */
	struct event *t_read;
	/* Event for MLAG write */
	struct event *t_write;
};

struct zebra_router {
	atomic_bool in_shutdown;

	/* Thread master */
	struct event_loop *master;

	/* Lists of clients who have connected to us */
	struct list *client_list;

	/* List of clients in GR */
	struct list *stale_client_list;

	struct zebra_router_table_head tables;

	/* L3-VNI hash table (for EVPN). Only in default instance */
	struct hash *l3vni_table;

	/* Tables and other global info maintained for EVPN multihoming */
	struct zebra_evpn_mh_info *mh_info;

	struct zebra_neigh_info *neigh_info;

	/* EVPN MH broadcast domains indexed by the VID */
	struct hash *evpn_vlan_table;

	struct hash *rules_hash;

	struct hash *ipset_hash;

	struct hash *ipset_entry_hash;

	struct hash *iptable_hash;

	struct hash *qdisc_hash;
	struct hash *class_hash;
	struct hash *filter_hash;

	/* A sequence number used for tracking routes */
	_Atomic uint32_t sequence_num;

	/* rib work queue */
#define ZEBRA_RIB_PROCESS_HOLD_TIME 10
#define ZEBRA_RIB_PROCESS_RETRY_TIME 1
	struct work_queue *ribq;

	/* Meta Queue Information */
	struct meta_queue *mq;

	/* LSP work queue */
	struct work_queue *lsp_process_q;

#define ZEBRA_ZAPI_PACKETS_TO_PROCESS 1000
	_Atomic uint32_t packets_to_process;

	/* Mlag information for the router */
	struct zebra_mlag_info mlag_info;

	/*
	 * The EVPN instance, if any
	 */
	struct zebra_vrf *evpn_vrf;

	uint32_t multipath_num;

	/* RPF Lookup behavior */
	enum multicast_mode ipv4_multicast_mode;

	/*
	 * Time for when we sweep the rib from old routes
	 */
	time_t startup_time;
	struct event *sweeper;

	/*
	 * The hash of nexthop groups associated with this router
	 */
	struct hash *nhgs;
	struct hash *nhgs_id;

	/*
	 * Does the underlying system provide an asic offload
	 */
	bool asic_offloaded;
	bool notify_on_ack;
	bool v6_with_v4_nexthop;

	/*
	 * If the asic is notifying us about successful nexthop
	 * allocation/control.  Some developers have made their
	 * asic take control of how many nexthops/ecmp they can
	 * have and will report what is successfull or not
	 */
	bool asic_notification_nexthop_control;

	bool supports_nhgs;

	bool all_mc_forwardingv4, default_mc_forwardingv4;
	bool all_mc_forwardingv6, default_mc_forwardingv6;
	bool all_linkdownv4, default_linkdownv4;
	bool all_linkdownv6, default_linkdownv6;

#define ZEBRA_DEFAULT_NHG_KEEP_TIMER 180
	uint32_t nhg_keep;

	/* Should we allow non FRR processes to delete our routes */
	bool allow_delete;

	uint8_t protodown_r_bit;
};

#define GRACEFUL_RESTART_TIME 60

extern struct zebra_router zrouter;
extern uint32_t rcvbufsize;

extern void zebra_router_init(bool asic_offload, bool notify_on_ack,
			      bool v6_with_v4_nexthop);
extern void zebra_router_cleanup(void);
extern void zebra_router_terminate(void);

extern struct zebra_router_table *zebra_router_find_zrt(struct zebra_vrf *zvrf,
							uint32_t tableid,
							afi_t afi, safi_t safi);
extern struct route_table *zebra_router_find_table(struct zebra_vrf *zvrf,
						   uint32_t tableid, afi_t afi,
						   safi_t safi);
extern struct route_table *zebra_router_get_table(struct zebra_vrf *zvrf,
						  uint32_t tableid, afi_t afi,
						  safi_t safi);
extern void zebra_router_release_table(struct zebra_vrf *zvrf, uint32_t tableid,
				       afi_t afi, safi_t safi);

extern int zebra_router_config_write(struct vty *vty);

extern void zebra_router_sweep_route(void);
extern void zebra_router_sweep_nhgs(void);

extern void zebra_router_show_table_summary(struct vty *vty);

extern uint32_t zebra_router_get_next_sequence(void);

static inline vrf_id_t zebra_vrf_get_evpn_id(void)
{
	return zrouter.evpn_vrf ? zvrf_id(zrouter.evpn_vrf) : VRF_DEFAULT;
}
static inline struct zebra_vrf *zebra_vrf_get_evpn(void)
{
	return zrouter.evpn_vrf ? zrouter.evpn_vrf
			        : zebra_vrf_lookup_by_id(VRF_DEFAULT);
}

extern void multicast_mode_ipv4_set(enum multicast_mode mode);

extern enum multicast_mode multicast_mode_ipv4_get(void);

extern bool zebra_router_notify_on_ack(void);

static inline void zebra_router_set_supports_nhgs(bool support)
{
	zrouter.supports_nhgs = support;
}

static inline bool zebra_router_in_shutdown(void)
{
	return atomic_load_explicit(&zrouter.in_shutdown, memory_order_relaxed);
}

#define FRR_PROTODOWN_REASON_DEFAULT_BIT 7
/* Protodown bit setter/getter
 *
 * Allow users to change the bit if it conflicts with another
 * on their system.
 */
static inline void if_netlink_set_frr_protodown_r_bit(uint8_t bit)
{
	zrouter.protodown_r_bit = bit;
}

static inline void if_netlink_unset_frr_protodown_r_bit(void)
{
	zrouter.protodown_r_bit = FRR_PROTODOWN_REASON_DEFAULT_BIT;
}

static inline bool if_netlink_frr_protodown_r_bit_is_set(void)
{
	return (zrouter.protodown_r_bit != FRR_PROTODOWN_REASON_DEFAULT_BIT);
}

static inline uint8_t if_netlink_get_frr_protodown_r_bit(void)
{
	return zrouter.protodown_r_bit;
}

/* zebra_northbound.c */
extern const struct frr_yang_module_info frr_zebra_info;

#ifdef __cplusplus
}
#endif

#endif