summaryrefslogtreecommitdiffstats
path: root/zebra/zebra_evpn_neigh.h
blob: c82b3673b15ea8409935696db1bd6159ef5e801e (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
/*
 * Zebra EVPN Neighbor Data structures and definitions
 * These are "internal" to this function.
 * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
 * Copyright (C) 2020 Volta Networks.
 */

#ifndef _ZEBRA_EVPN_NEIGH_H
#define _ZEBRA_EVPN_NEIGH_H

#ifdef __cplusplus
extern "C" {
#endif

#define IS_ZEBRA_NEIGH_ACTIVE(n) (n->state == ZEBRA_NEIGH_ACTIVE)

#define IS_ZEBRA_NEIGH_INACTIVE(n) (n->state == ZEBRA_NEIGH_INACTIVE)

#define ZEBRA_NEIGH_SET_ACTIVE(n) n->state = ZEBRA_NEIGH_ACTIVE

#define ZEBRA_NEIGH_SET_INACTIVE(n) n->state = ZEBRA_NEIGH_INACTIVE

/*
 * Neighbor hash table.
 *
 * This table contains the neighbors (IP to MAC bindings) pertaining to
 * this VNI. This includes local neighbors learnt on the attached VLAN
 * device that maps to this VNI as well as remote neighbors learnt and
 * installed by BGP.
 * Local neighbors will be known against the VLAN device (SVI); however,
 * it is sufficient for zebra to maintain against the VNI. The correct
 * VNI will be obtained as zebra maintains the mapping (of VLAN to VNI).
 */
struct zebra_neigh {
	/* IP address. */
	struct ipaddr ip;

	/* MAC address. */
	struct ethaddr emac;

	/* Back pointer to MAC. Only applicable to hosts in a L2-VNI. */
	struct zebra_mac *mac;

	/* Underlying interface. */
	ifindex_t ifindex;

	struct zebra_evpn *zevpn;

	/* Refcnt - Only used by SVD neighs currently */
	uint32_t refcnt;

	uint32_t flags;
#define ZEBRA_NEIGH_LOCAL 0x01
#define ZEBRA_NEIGH_REMOTE 0x02
#define ZEBRA_NEIGH_REMOTE_NH 0x04 /* neigh entry for remote vtep */
#define ZEBRA_NEIGH_DEF_GW 0x08
#define ZEBRA_NEIGH_ROUTER_FLAG 0x10
#define ZEBRA_NEIGH_DUPLICATE 0x20
#define ZEBRA_NEIGH_SVI_IP 0x40
/* rxed from an ES peer */
#define ZEBRA_NEIGH_ES_PEER_ACTIVE 0x80
/* rxed from an ES peer as a proxy advertisement */
#define ZEBRA_NEIGH_ES_PEER_PROXY 0x100
/* We have not been able to independently establish that the host
 * is local connected
 */
#define ZEBRA_NEIGH_LOCAL_INACTIVE 0x200
#define ZEBRA_NEIGH_ALL_LOCAL_FLAGS                                            \
	(ZEBRA_NEIGH_LOCAL | ZEBRA_NEIGH_LOCAL_INACTIVE)
#define ZEBRA_NEIGH_ALL_PEER_FLAGS                                             \
	(ZEBRA_NEIGH_ES_PEER_PROXY | ZEBRA_NEIGH_ES_PEER_ACTIVE)

	enum zebra_neigh_state state;

	/* Remote VTEP IP - applicable only for remote neighbors. */
	struct in_addr r_vtep_ip;

	/*
	 * Mobility sequence numbers associated with this entry. The rem_seq
	 * represents the sequence number from the client (BGP) for the most
	 * recent add or update of this entry while the loc_seq represents
	 * the sequence number informed (or to be informed) by zebra to BGP
	 * for this entry.
	 */
	uint32_t rem_seq;
	uint32_t loc_seq;

	/* list of hosts pointing to this remote NH entry */
	struct host_rb_tree_entry host_rb;

	/* Duplicate ip detection */
	uint32_t dad_count;

	struct event *dad_ip_auto_recovery_timer;

	struct timeval detect_start_time;

	time_t dad_dup_detect_time;

	time_t uptime;

	/* used for ageing out the PEER_ACTIVE flag */
	struct event *hold_timer;
};

/*
 * Context for neighbor hash walk - used by callbacks.
 */
struct neigh_walk_ctx {
	struct zebra_evpn *zevpn; /* VNI hash */
	struct zebra_vrf *zvrf; /* VRF - for client notification. */
	int uninstall;		/* uninstall from kernel? */
	int upd_client;		/* uninstall from client? */

	uint32_t flags;
#define DEL_LOCAL_NEIGH 0x1
#define DEL_REMOTE_NEIGH 0x2
#define DEL_ALL_NEIGH (DEL_LOCAL_NEIGH | DEL_REMOTE_NEIGH)
#define DEL_REMOTE_NEIGH_FROM_VTEP 0x4
#define SHOW_REMOTE_NEIGH_FROM_VTEP 0x8

	struct in_addr r_vtep_ip; /* To walk neighbors from specific VTEP */

	struct vty *vty;	  /* Used by VTY handlers */
	uint32_t count;		  /* Used by VTY handlers */
	uint8_t addr_width;       /* Used by VTY handlers */
	struct json_object *json; /* Used for JSON Output */
};

/**************************** SYNC neigh handling **************************/
static inline bool zebra_evpn_neigh_is_static(struct zebra_neigh *neigh)
{
	return !!(neigh->flags & ZEBRA_NEIGH_ALL_PEER_FLAGS);
}

static inline bool zebra_evpn_neigh_is_ready_for_bgp(struct zebra_neigh *n)
{
	bool mac_ready;
	bool neigh_ready;

	mac_ready = !!(n->mac->flags & ZEBRA_MAC_LOCAL);
	neigh_ready =
		((n->flags & ZEBRA_NEIGH_LOCAL) && IS_ZEBRA_NEIGH_ACTIVE(n)
		 && (!(n->flags & ZEBRA_NEIGH_LOCAL_INACTIVE)
		     || (n->flags & ZEBRA_NEIGH_ES_PEER_ACTIVE)))
			? true
			: false;

	return mac_ready && neigh_ready;
}

static inline void zebra_evpn_neigh_stop_hold_timer(struct zebra_neigh *n)
{
	if (!n->hold_timer)
		return;

	if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
		zlog_debug("sync-neigh vni %u ip %pIA mac %pEA 0x%x hold stop",
			   n->zevpn->vni, &n->ip, &n->emac, n->flags);
	EVENT_OFF(n->hold_timer);
}

void zebra_evpn_sync_neigh_static_chg(struct zebra_neigh *n, bool old_n_static,
				      bool new_n_static, bool defer_n_dp,
				      bool defer_mac_dp, const char *caller);

static inline bool zebra_evpn_neigh_clear_sync_info(struct zebra_neigh *n)
{
	bool old_n_static = false;
	bool new_n_static = false;

	if (n->flags & ZEBRA_NEIGH_ALL_PEER_FLAGS) {
		if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
			zlog_debug("sync-neigh vni %u ip %pIA mac %pEA 0x%x clear",
				   n->zevpn->vni, &n->ip, &n->emac, n->flags);

		old_n_static = zebra_evpn_neigh_is_static(n);
		UNSET_FLAG(n->flags, ZEBRA_NEIGH_ALL_PEER_FLAGS);
		new_n_static = zebra_evpn_neigh_is_static(n);
		if (old_n_static != new_n_static)
			zebra_evpn_sync_neigh_static_chg(
				n, old_n_static, new_n_static,
				true /*defer_dp)*/, false /*defer_mac_dp*/,
				__func__);
	}
	zebra_evpn_neigh_stop_hold_timer(n);

	/* if the neigh static flag changed inform that a dp
	 * re-install maybe needed
	 */
	return old_n_static != new_n_static;
}

int remote_neigh_count(struct zebra_mac *zmac);

int neigh_list_cmp(void *p1, void *p2);
struct hash *zebra_neigh_db_create(const char *desc);
uint32_t num_dup_detected_neighs(struct zebra_evpn *zevpn);
void zebra_evpn_find_neigh_addr_width(struct hash_bucket *bucket, void *ctxt);
int remote_neigh_count(struct zebra_mac *zmac);
int zebra_evpn_rem_neigh_install(struct zebra_evpn *zevpn,
				 struct zebra_neigh *n, bool was_static);
void zebra_evpn_install_neigh_hash(struct hash_bucket *bucket, void *ctxt);
int zebra_evpn_neigh_send_add_to_client(vni_t vni, const struct ipaddr *ip,
					const struct ethaddr *macaddr,
					struct zebra_mac *zmac,
					uint32_t neigh_flags, uint32_t seq);
int zebra_evpn_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
					struct ethaddr *macaddr, uint32_t flags,
					int state, bool force);
bool zebra_evpn_neigh_is_bgp_seq_ok(struct zebra_evpn *zevpn,
				    struct zebra_neigh *n,
				    const struct ethaddr *macaddr, uint32_t seq,
				    bool sync);
int zebra_evpn_neigh_del(struct zebra_evpn *zevpn, struct zebra_neigh *n);
void zebra_evpn_sync_neigh_del(struct zebra_neigh *n);
struct zebra_neigh *zebra_evpn_proc_sync_neigh_update(
	struct zebra_evpn *zevpn, struct zebra_neigh *n, uint16_t ipa_len,
	const struct ipaddr *ipaddr, uint8_t flags, uint32_t seq,
	const esi_t *esi, struct zebra_mac *mac);
void zebra_evpn_neigh_del_all(struct zebra_evpn *zevpn, int uninstall,
			      int upd_client, uint32_t flags);
struct zebra_neigh *zebra_evpn_neigh_lookup(struct zebra_evpn *zevpn,
					    const struct ipaddr *ip);

int zebra_evpn_rem_neigh_install(struct zebra_evpn *zevpn,
				 struct zebra_neigh *n, bool was_static);
void zebra_evpn_process_neigh_on_remote_mac_add(struct zebra_evpn *zevpn,
						struct zebra_mac *zmac);
void zebra_evpn_process_neigh_on_local_mac_del(struct zebra_evpn *zevpn,
					       struct zebra_mac *zmac);
void zebra_evpn_process_neigh_on_local_mac_change(struct zebra_evpn *zevpn,
						  struct zebra_mac *zmac,
						  bool seq_change,
						  bool es_change);
void zebra_evpn_process_neigh_on_remote_mac_del(struct zebra_evpn *zevpn,
						struct zebra_mac *zmac);
int zebra_evpn_local_neigh_update(struct zebra_evpn *zevpn,
				  struct interface *ifp,
				  const struct ipaddr *ip,
				  const struct ethaddr *macaddr, bool is_router,
				  bool local_inactive, bool dp_static);
int zebra_evpn_remote_neigh_update(struct zebra_evpn *zevpn,
				   struct interface *ifp,
				   const struct ipaddr *ip,
				   const struct ethaddr *macaddr,
				   uint16_t state);
void zebra_evpn_send_neigh_to_client(struct zebra_evpn *zevpn);
void zebra_evpn_clear_dup_neigh_hash(struct hash_bucket *bucket, void *ctxt);
void zebra_evpn_print_neigh(struct zebra_neigh *n, void *ctxt,
			    json_object *json);
void zebra_evpn_print_neigh_hash(struct hash_bucket *bucket, void *ctxt);
void zebra_evpn_print_neigh_hdr(struct vty *vty, struct neigh_walk_ctx *wctx);
void zebra_evpn_print_neigh_hash_detail(struct hash_bucket *bucket, void *ctxt);
void zebra_evpn_print_dad_neigh_hash(struct hash_bucket *bucket, void *ctxt);
void zebra_evpn_print_dad_neigh_hash_detail(struct hash_bucket *bucket,
					    void *ctxt);
void zebra_evpn_neigh_remote_macip_add(struct zebra_evpn *zevpn,
				       struct zebra_vrf *zvrf,
				       const struct ipaddr *ipaddr,
				       struct zebra_mac *mac,
				       struct in_addr vtep_ip, uint8_t flags,
				       uint32_t seq);
int zebra_evpn_neigh_gw_macip_add(struct interface *ifp,
				  struct zebra_evpn *zevpn, struct ipaddr *ip,
				  struct zebra_mac *mac);
void zebra_evpn_neigh_remote_uninstall(struct zebra_evpn *zevpn,
				       struct zebra_vrf *zvrf,
				       struct zebra_neigh *n,
				       struct zebra_mac *mac,
				       const struct ipaddr *ipaddr);
int zebra_evpn_neigh_del_ip(struct zebra_evpn *zevpn, const struct ipaddr *ip);


#ifdef __cplusplus
}
#endif

#endif /*_ZEBRA_EVPN_NEIGH_H */