]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
185fb14a AK |
2 | /* EVPN header for multihoming procedures |
3 | * | |
4 | * Copyright (C) 2019 Cumulus Networks | |
c44ab6f1 | 5 | * Anuradha Karuppiah |
185fb14a | 6 | * |
185fb14a AK |
7 | */ |
8 | ||
9 | #ifndef _FRR_BGP_EVPN_MH_H | |
10 | #define _FRR_BGP_EVPN_MH_H | |
11 | ||
12 | #include "vxlan.h" | |
13 | #include "bgpd.h" | |
14 | #include "bgp_evpn.h" | |
15 | #include "bgp_evpn_private.h" | |
16 | ||
c44ab6f1 AK |
17 | #define BGP_EVPN_AD_ES_ETH_TAG 0xffffffff |
18 | #define BGP_EVPN_AD_EVI_ETH_TAG 0 | |
19 | ||
20 | #define BGP_EVPNES_INCONS_STR_SZ 80 | |
c44ab6f1 AK |
21 | #define BGP_EVPN_VTEPS_FLAG_STR_SZ (BGP_EVPN_FLAG_STR_SZ * ES_VTEP_MAX_CNT) |
22 | ||
23 | #define BGP_EVPN_CONS_CHECK_INTERVAL 60 | |
24 | ||
a92764da | 25 | #define BGP_EVPN_MH_USE_ES_L3NHG_DEF true |
c44ab6f1 | 26 | |
7b0db0e4 AK |
27 | /* XXX - tune this */ |
28 | #define BGP_EVPN_MAX_EVI_PER_ES_FRAG 128 | |
29 | ||
30 | /* An ES can result in multiple EAD-per-ES route. Each EAD fragment is | |
31 | * associated with an unique RD | |
32 | */ | |
33 | struct bgp_evpn_es_frag { | |
34 | /* frag is associated with a parent ES */ | |
35 | struct bgp_evpn_es *es; | |
36 | ||
37 | /* Id for deriving the RD automatically for this ES fragment */ | |
38 | uint16_t rd_id; | |
39 | /* RD for this ES fragment */ | |
40 | struct prefix_rd prd; | |
41 | ||
fff7545a | 42 | /* Memory used for linking bgp_evpn_es_frag to |
43 | * bgp_evpn_es->es_frag_list | |
44 | */ | |
7b0db0e4 AK |
45 | struct listnode es_listnode; |
46 | ||
47 | /* List of ES-EVIs associated with this fragment */ | |
48 | struct list *es_evi_frag_list; | |
49 | }; | |
50 | ||
c44ab6f1 AK |
51 | /* Ethernet Segment entry - |
52 | * - Local and remote ESs are maintained in a global RB tree, | |
fff7545a | 53 | * bgp_mh_info->es_rb_tree using ESI as key |
c44ab6f1 AK |
54 | * - Local ESs are received from zebra (BGP_EVPNES_LOCAL) |
55 | * - Remotes ESs are implicitly created (by reference) by a remote ES-EVI | |
56 | * (BGP_EVPNES_REMOTE) | |
fff7545a | 57 | * - An ES can be simultaneously LOCAL and REMOTE; infact all LOCAL ESs are |
c44ab6f1 AK |
58 | * expected to have REMOTE ES peers. |
59 | */ | |
60 | struct bgp_evpn_es { | |
61 | /* Ethernet Segment Identifier */ | |
62 | esi_t esi; | |
63 | char esi_str[ESI_STR_LEN]; | |
64 | ||
65 | /* es flags */ | |
66 | uint32_t flags; | |
67 | /* created via zebra config */ | |
68 | #define BGP_EVPNES_LOCAL (1 << 0) | |
69 | /* created implicitly by a remote ES-EVI reference */ | |
70 | #define BGP_EVPNES_REMOTE (1 << 1) | |
71 | /* local ES link is oper-up */ | |
72 | #define BGP_EVPNES_OPER_UP (1 << 2) | |
73 | /* enable generation of EAD-EVI routes */ | |
74 | #define BGP_EVPNES_ADV_EVI (1 << 3) | |
75 | /* consistency checks pending */ | |
76 | #define BGP_EVPNES_CONS_CHECK_PEND (1 << 4) | |
74be8313 AK |
77 | /* ES is in LACP bypass mode - don't advertise EAD-ES or ESR */ |
78 | #define BGP_EVPNES_BYPASS (1 << 5) | |
79 | /* bits needed for printing the flags + null */ | |
80 | #define BGP_EVPN_FLAG_STR_SZ 7 | |
c44ab6f1 AK |
81 | |
82 | /* memory used for adding the es to bgp->es_rb_tree */ | |
83 | RB_ENTRY(bgp_evpn_es) rb_node; | |
84 | ||
85 | /* [EVPNES_LOCAL] memory used for linking the es to | |
86 | * bgp_mh_info->local_es_list | |
87 | */ | |
88 | struct listnode es_listnode; | |
89 | ||
90 | /* memory used for linking the es to "processing" pending list | |
91 | * bgp_mh_info->pend_es_list | |
92 | */ | |
93 | struct listnode pend_es_listnode; | |
94 | ||
fff7545a | 95 | /* [EVPNES_LOCAL] List of RDs for this ES (bgp_evpn_es_frag) */ |
7b0db0e4 AK |
96 | struct list *es_frag_list; |
97 | struct bgp_evpn_es_frag *es_base_frag; | |
c44ab6f1 AK |
98 | |
99 | /* [EVPNES_LOCAL] originator ip address */ | |
100 | struct in_addr originator_ip; | |
101 | ||
102 | /* [EVPNES_LOCAL] Route table for EVPN routes for this ESI- | |
103 | * - Type-4 local and remote routes | |
104 | * - Type-1 local routes | |
105 | */ | |
106 | struct bgp_table *route_table; | |
107 | ||
108 | /* list of PEs (bgp_evpn_es_vtep) attached to the ES */ | |
109 | struct list *es_vtep_list; | |
110 | ||
111 | /* List of ES-EVIs associated with this ES */ | |
112 | struct list *es_evi_list; | |
113 | ||
c589d847 AK |
114 | /* List of ES-VRFs associated with this ES */ |
115 | struct list *es_vrf_list; | |
116 | ||
2eef4f20 | 117 | /* List of MAC-IP VNI paths using this ES as destination - |
26c03e43 | 118 | * element is bgp_path_info_extra->es_info |
58bff4d1 AK |
119 | * Note: Only local/zebra-added MACIP paths in the VNI |
120 | * routing table are linked to this list | |
26c03e43 | 121 | */ |
d656e0ae | 122 | struct list *macip_evi_path_list; |
26c03e43 | 123 | |
58bff4d1 AK |
124 | /* List of MAC-IP paths in the global routing table using this |
125 | * ES as destination - data is bgp_path_info_extra->es_info | |
126 | * Note: Only non-local/imported MACIP paths in the global | |
127 | * routing table are linked to this list | |
128 | */ | |
129 | struct list *macip_global_path_list; | |
130 | ||
c44ab6f1 AK |
131 | /* Number of remote VNIs referencing this ES */ |
132 | uint32_t remote_es_evi_cnt; | |
133 | ||
134 | uint32_t inconsistencies; | |
135 | /* there are one or more EVIs whose VTEP list doesn't match | |
136 | * with the ES's VTEP list | |
137 | */ | |
138 | #define BGP_EVPNES_INCONS_VTEP_LIST (1 << 0) | |
139 | ||
140 | /* number of es-evi entries whose VTEP list doesn't match | |
141 | * with the ES's | |
142 | */ | |
143 | uint32_t incons_evi_vtep_cnt; | |
144 | ||
74e2bd89 AK |
145 | /* preference config for BUM-DF election. advertised via the ESR. */ |
146 | uint16_t df_pref; | |
147 | ||
96244aca | 148 | QOBJ_FIELDS; |
c44ab6f1 | 149 | }; |
96244aca | 150 | DECLARE_QOBJ_TYPE(bgp_evpn_es); |
c44ab6f1 AK |
151 | RB_HEAD(bgp_es_rb_head, bgp_evpn_es); |
152 | RB_PROTOTYPE(bgp_es_rb_head, bgp_evpn_es, rb_node, bgp_es_rb_cmp); | |
153 | ||
154 | /* PE attached to an ES */ | |
155 | struct bgp_evpn_es_vtep { | |
156 | struct bgp_evpn_es *es; /* parent ES */ | |
157 | struct in_addr vtep_ip; | |
158 | ||
23aa35ad AK |
159 | char vtep_str[INET6_ADDRSTRLEN]; |
160 | ||
c44ab6f1 AK |
161 | uint32_t flags; |
162 | /* Rxed a Type4 route from this PE */ | |
163 | #define BGP_EVPNES_VTEP_ESR (1 << 0) | |
164 | /* Active (rxed EAD-ES and EAD-EVI) and can be included as | |
165 | * a nexthop | |
166 | */ | |
167 | #define BGP_EVPNES_VTEP_ACTIVE (1 << 1) | |
168 | ||
169 | uint32_t evi_cnt; /* es_evis referencing this vtep as an active path */ | |
170 | ||
74e2bd89 AK |
171 | /* Algorithm and preference for DF election. Rxed via the ESR */ |
172 | uint8_t df_alg; | |
173 | uint16_t df_pref; | |
174 | ||
c44ab6f1 AK |
175 | /* memory used for adding the entry to es->es_vtep_list */ |
176 | struct listnode es_listnode; | |
177 | }; | |
178 | ||
c589d847 AK |
179 | /* ES-VRF element needed for managing L3 NHGs. It is implicitly created |
180 | * when an ES-EVI is associated with a tenant VRF | |
181 | */ | |
182 | struct bgp_evpn_es_vrf { | |
183 | struct bgp_evpn_es *es; | |
184 | struct bgp *bgp_vrf; | |
185 | ||
186 | uint32_t flags; | |
187 | /* NHG can only be activated if there are active VTEPs in the ES and | |
188 | * there is a valid L3-VNI associated with the VRF | |
189 | */ | |
190 | #define BGP_EVPNES_VRF_NHG_ACTIVE (1 << 0) | |
191 | ||
192 | /* memory used for adding the es_vrf to | |
193 | * es_vrf->bgp_vrf->es_vrf_rb_tree | |
194 | */ | |
195 | RB_ENTRY(bgp_evpn_es_vrf) rb_node; | |
196 | ||
197 | /* memory used for linking the es_vrf to es_vrf->es->es_vrf_list */ | |
198 | struct listnode es_listnode; | |
199 | ||
200 | uint32_t nhg_id; | |
6348981a | 201 | uint32_t v6_nhg_id; |
c589d847 AK |
202 | |
203 | /* Number of ES-EVI entries associated with this ES-VRF */ | |
204 | uint32_t ref_cnt; | |
205 | }; | |
206 | ||
c44ab6f1 AK |
207 | /* ES per-EVI info |
208 | * - ES-EVIs are maintained per-L2-VNI (vpn->es_evi_rb_tree) | |
209 | * - ES-EVIs are also linked to the parent ES (es->es_evi_list) | |
210 | * - Local ES-EVIs are created by zebra (via config). They are linked to a | |
211 | * per-VNI list (vpn->local_es_evi_list) for quick access | |
212 | * - Remote ES-EVIs are created implicitly when a bgp_evpn_es_evi_vtep | |
213 | * references it. | |
214 | */ | |
215 | struct bgp_evpn_es_evi { | |
216 | struct bgp_evpn_es *es; | |
7b0db0e4 AK |
217 | /* Only applicableif EVI_LOCAL */ |
218 | struct bgp_evpn_es_frag *es_frag; | |
c44ab6f1 AK |
219 | struct bgpevpn *vpn; |
220 | ||
221 | /* ES-EVI flags */ | |
222 | uint32_t flags; | |
223 | /* local ES-EVI, created by zebra */ | |
224 | #define BGP_EVPNES_EVI_LOCAL (1 << 0) | |
225 | /* created via a remote VTEP imported by BGP */ | |
226 | #define BGP_EVPNES_EVI_REMOTE (1 << 1) | |
227 | #define BGP_EVPNES_EVI_INCONS_VTEP_LIST (1 << 2) | |
228 | ||
229 | /* memory used for adding the es_evi to es_evi->vpn->es_evi_rb_tree */ | |
230 | RB_ENTRY(bgp_evpn_es_evi) rb_node; | |
231 | /* memory used for linking the es_evi to | |
232 | * es_evi->vpn->local_es_evi_list | |
233 | */ | |
234 | struct listnode l2vni_listnode; | |
235 | /* memory used for linking the es_evi to | |
236 | * es_evi->es->es_evi_list | |
237 | */ | |
238 | struct listnode es_listnode; | |
239 | ||
7b0db0e4 AK |
240 | /* memory used for linking the es_evi to |
241 | * es_evi->es_frag->es_evi_frag_list | |
242 | */ | |
243 | struct listnode es_frag_listnode; | |
c44ab6f1 AK |
244 | /* list of PEs (bgp_evpn_es_evi_vtep) attached to the ES for this VNI */ |
245 | struct list *es_evi_vtep_list; | |
c589d847 AK |
246 | |
247 | struct bgp_evpn_es_vrf *es_vrf; | |
c44ab6f1 AK |
248 | }; |
249 | ||
250 | /* PE attached to an ES for a VNI. This entry is created when an EAD-per-ES | |
251 | * or EAD-per-EVI Type1 route is imported into the VNI. | |
252 | */ | |
253 | struct bgp_evpn_es_evi_vtep { | |
254 | struct bgp_evpn_es_evi *es_evi; /* parent ES-EVI */ | |
255 | struct in_addr vtep_ip; | |
256 | ||
257 | uint32_t flags; | |
258 | /* Rxed an EAD-per-ES route from the PE */ | |
259 | #define BGP_EVPN_EVI_VTEP_EAD_PER_ES (1 << 0) /* rxed EAD-per-ES */ | |
260 | /* Rxed an EAD-per-EVI route from the PE */ | |
261 | #define BGP_EVPN_EVI_VTEP_EAD_PER_EVI (1 << 1) /* rxed EAD-per-EVI */ | |
262 | /* VTEP is active i.e. will result in the creation of an es-vtep */ | |
263 | #define BGP_EVPN_EVI_VTEP_ACTIVE (1 << 2) | |
264 | #define BGP_EVPN_EVI_VTEP_EAD (BGP_EVPN_EVI_VTEP_EAD_PER_ES |\ | |
265 | BGP_EVPN_EVI_VTEP_EAD_PER_EVI) | |
266 | ||
267 | /* memory used for adding the entry to es_evi->es_evi_vtep_list */ | |
268 | struct listnode es_evi_listnode; | |
269 | struct bgp_evpn_es_vtep *es_vtep; | |
270 | }; | |
271 | ||
090efa2f AK |
272 | /* A nexthop is created when a path (imported from an EVPN type-2 route) |
273 | * is added to the VRF route table using that nexthop. | |
274 | * It is added on first pi reference and removed on last pi deref. | |
275 | */ | |
276 | struct bgp_evpn_nh { | |
277 | /* backpointer to the VRF */ | |
278 | struct bgp *bgp_vrf; | |
279 | /* nexthop/VTEP IP */ | |
280 | struct ipaddr ip; | |
281 | /* description for easy logging */ | |
282 | char nh_str[INET6_ADDRSTRLEN]; | |
283 | struct ethaddr rmac; | |
284 | /* pi from which we are pulling the nh RMAC */ | |
285 | struct bgp_path_info *ref_pi; | |
286 | /* List of VRF paths using this nexthop */ | |
287 | struct list *pi_list; | |
288 | uint8_t flags; | |
289 | #define BGP_EVPN_NH_READY_FOR_ZEBRA (1 << 0) | |
290 | }; | |
291 | ||
c44ab6f1 AK |
292 | /* multihoming information stored in bgp_master */ |
293 | #define bgp_mh_info (bm->mh_info) | |
294 | struct bgp_evpn_mh_info { | |
295 | /* RB tree of Ethernet segments (used for EVPN-MH) */ | |
296 | struct bgp_es_rb_head es_rb_tree; | |
297 | /* List of local ESs */ | |
298 | struct list *local_es_list; | |
299 | /* List of ESs with pending/periodic processing */ | |
300 | struct list *pend_es_list; | |
301 | /* periodic timer for running background consistency checks */ | |
e6685141 | 302 | struct event *t_cons_check; |
c44ab6f1 AK |
303 | |
304 | /* config knobs for optimizing or interop */ | |
305 | /* Generate EAD-EVI routes even if the ES is oper-down. This can be | |
306 | * enabled as an optimization to avoid a storm of updates when an ES | |
307 | * link flaps. | |
308 | */ | |
309 | bool ead_evi_adv_for_down_links; | |
310 | /* Enable ES consistency checking */ | |
311 | bool consistency_checking; | |
8bcb09a1 | 312 | /* Use L3 NHGs for host routes in symmetric IRB */ |
6348981a | 313 | bool host_routes_use_l3nhg; |
fe8293c3 AK |
314 | /* Some vendors are not generating the EAD-per-EVI route. This knob |
315 | * can be turned off to activate a remote ES-PE when the EAD-per-ES | |
316 | * route is rxed i.e. not wait on the EAD-per-EVI route | |
317 | */ | |
318 | bool ead_evi_rx; | |
319 | #define BGP_EVPN_MH_EAD_EVI_RX_DEF true | |
320 | /* Skip EAD-EVI advertisements by turning off this knob */ | |
321 | bool ead_evi_tx; | |
322 | #define BGP_EVPN_MH_EAD_EVI_TX_DEF true | |
70524092 AK |
323 | /* If the Local ES is inactive we advertise the MAC-IP without the |
324 | * L3 ecomm | |
325 | */ | |
326 | bool suppress_l3_ecomm_on_inactive_es; | |
090efa2f AK |
327 | /* Setup EVPN PE nexthops and their RMAC in bgpd */ |
328 | bool bgp_evpn_nh_setup; | |
f4a5218d AK |
329 | |
330 | /* If global export-rts are configured that is used for sending | |
331 | * sending the ead-per-es route instead of the L2-VNI(s) RTs | |
332 | */ | |
333 | struct list *ead_es_export_rtl; | |
bb37eabe AK |
334 | |
335 | /* Number of EVIs in an ES fragment - used of EAD-per-ES route | |
336 | * construction | |
337 | */ | |
338 | uint32_t evi_per_es_frag; | |
c44ab6f1 AK |
339 | }; |
340 | ||
341 | /****************************************************************************/ | |
7904e9fd | 342 | static inline int bgp_evpn_is_es_local(struct bgp_evpn_es *es) |
c44ab6f1 AK |
343 | { |
344 | return CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL) ? 1 : 0; | |
345 | } | |
346 | ||
347 | extern esi_t *zero_esi; | |
7904e9fd AK |
348 | static inline bool bgp_evpn_is_esi_valid(esi_t *esi) |
349 | { | |
350 | return !!memcmp(esi, zero_esi, sizeof(esi_t)); | |
351 | } | |
352 | ||
c44ab6f1 AK |
353 | static inline esi_t *bgp_evpn_attr_get_esi(struct attr *attr) |
354 | { | |
7904e9fd AK |
355 | return attr ? &attr->esi : zero_esi; |
356 | } | |
357 | ||
358 | static inline bool bgp_evpn_attr_is_sync(struct attr *attr) | |
359 | { | |
360 | return attr ? !!(attr->es_flags & | |
361 | (ATTR_ES_PEER_PROXY | ATTR_ES_PEER_ACTIVE)) : false; | |
362 | } | |
363 | ||
364 | static inline uint32_t bgp_evpn_attr_get_sync_seq(struct attr *attr) | |
365 | { | |
366 | return attr ? attr->mm_sync_seqnum : 0; | |
367 | } | |
368 | ||
369 | static inline bool bgp_evpn_attr_is_active_on_peer(struct attr *attr) | |
370 | { | |
371 | return attr ? | |
372 | !!(attr->es_flags & ATTR_ES_PEER_ACTIVE) : false; | |
373 | } | |
374 | ||
375 | static inline bool bgp_evpn_attr_is_router_on_peer(struct attr *attr) | |
376 | { | |
377 | return attr ? | |
378 | !!(attr->es_flags & ATTR_ES_PEER_ROUTER) : false; | |
379 | } | |
380 | ||
381 | static inline bool bgp_evpn_attr_is_proxy(struct attr *attr) | |
382 | { | |
383 | return attr ? !!(attr->es_flags & ATTR_ES_PROXY_ADVERT) : false; | |
384 | } | |
385 | ||
386 | static inline bool bgp_evpn_attr_is_local_es(struct attr *attr) | |
387 | { | |
388 | return attr ? !!(attr->es_flags & ATTR_ES_IS_LOCAL) : false; | |
c44ab6f1 AK |
389 | } |
390 | ||
74e2bd89 AK |
391 | static inline uint32_t bgp_evpn_attr_get_df_pref(struct attr *attr) |
392 | { | |
393 | return (attr) ? attr->df_pref : 0; | |
394 | } | |
395 | ||
70524092 AK |
396 | static inline bool bgp_evpn_local_es_is_active(struct bgp_evpn_es *es) |
397 | { | |
398 | return (es->flags & BGP_EVPNES_OPER_UP) | |
399 | && !(es->flags & BGP_EVPNES_BYPASS); | |
400 | } | |
401 | ||
c44ab6f1 AK |
402 | /****************************************************************************/ |
403 | extern int bgp_evpn_es_route_install_uninstall(struct bgp *bgp, | |
404 | struct bgp_evpn_es *es, afi_t afi, safi_t safi, | |
405 | struct prefix_evpn *evp, struct bgp_path_info *pi, | |
406 | int install); | |
9c49ac74 | 407 | extern void update_type1_routes_for_evi(struct bgp *bgp, struct bgpevpn *vpn); |
d60f63f0 AD |
408 | extern int delete_global_ead_evi_routes(struct bgp *bgp, struct bgpevpn *vpn); |
409 | extern int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es, | |
410 | struct bgpevpn *vpn, afi_t afi, safi_t safi, | |
411 | struct bgp_dest *dest, struct attr *attr, | |
e0a79881 | 412 | struct bgp_path_info **ri, |
d60f63f0 | 413 | int *route_changed); |
c44ab6f1 AK |
414 | int bgp_evpn_type1_route_process(struct peer *peer, afi_t afi, safi_t safi, |
415 | struct attr *attr, uint8_t *pfx, int psize, | |
416 | uint32_t addpath_id); | |
417 | int bgp_evpn_type4_route_process(struct peer *peer, afi_t afi, safi_t safi, | |
418 | struct attr *attr, uint8_t *pfx, int psize, | |
419 | uint32_t addpath_id); | |
185fb14a | 420 | extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi, |
74e2bd89 | 421 | struct in_addr originator_ip, bool oper_up, |
74be8313 | 422 | uint16_t df_pref, bool bypass); |
c44ab6f1 AK |
423 | extern int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi); |
424 | extern int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni); | |
425 | extern int bgp_evpn_local_es_evi_del(struct bgp *bgp, esi_t *esi, vni_t vni); | |
426 | extern int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn, | |
427 | const struct prefix_evpn *p); | |
428 | extern int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn, | |
429 | const struct prefix_evpn *p); | |
430 | extern void bgp_evpn_mh_init(void); | |
431 | extern void bgp_evpn_mh_finish(void); | |
432 | void bgp_evpn_vni_es_init(struct bgpevpn *vpn); | |
433 | void bgp_evpn_vni_es_cleanup(struct bgpevpn *vpn); | |
434 | void bgp_evpn_es_show_esi(struct vty *vty, esi_t *esi, bool uj); | |
435 | void bgp_evpn_es_show(struct vty *vty, bool uj, bool detail); | |
436 | void bgp_evpn_es_evi_show_vni(struct vty *vty, vni_t vni, | |
437 | bool uj, bool detail); | |
438 | void bgp_evpn_es_evi_show(struct vty *vty, bool uj, bool detail); | |
439 | struct bgp_evpn_es *bgp_evpn_es_find(const esi_t *esi); | |
c589d847 | 440 | extern void bgp_evpn_vrf_es_init(struct bgp *bgp_vrf); |
74efb822 | 441 | extern bool bgp_evpn_is_esi_local_and_non_bypass(esi_t *esi); |
c589d847 AK |
442 | extern void bgp_evpn_es_vrf_deref(struct bgp_evpn_es_evi *es_evi); |
443 | extern void bgp_evpn_es_vrf_ref(struct bgp_evpn_es_evi *es_evi, | |
444 | struct bgp *bgp_vrf); | |
60605cbc | 445 | extern void bgp_evpn_path_mh_info_free(struct bgp_path_mh_info *mh_info); |
26c03e43 AK |
446 | extern void bgp_evpn_path_es_link(struct bgp_path_info *pi, vni_t vni, |
447 | esi_t *esi); | |
6348981a AK |
448 | extern bool bgp_evpn_path_es_use_nhg(struct bgp *bgp_vrf, |
449 | struct bgp_path_info *pi, uint32_t *nhg_p); | |
229587fb AK |
450 | extern void bgp_evpn_es_vrf_show(struct vty *vty, bool uj, |
451 | struct bgp_evpn_es *es); | |
452 | extern void bgp_evpn_es_vrf_show_esi(struct vty *vty, esi_t *esi, bool uj); | |
acd1d9bc | 453 | extern void bgp_evpn_switch_ead_evi_rx(void); |
70524092 | 454 | extern bool bgp_evpn_es_add_l3_ecomm_ok(esi_t *esi); |
58bff4d1 AK |
455 | extern void bgp_evpn_es_vrf_use_nhg(struct bgp *bgp_vrf, esi_t *esi, |
456 | bool *use_l3nhg, bool *is_l3nhg_active, | |
457 | struct bgp_evpn_es_vrf **es_vrf_p); | |
090efa2f AK |
458 | extern void bgp_evpn_nh_init(struct bgp *bgp_vrf); |
459 | extern void bgp_evpn_nh_finish(struct bgp *bgp_vrf); | |
460 | extern void bgp_evpn_nh_show(struct vty *vty, bool uj); | |
461 | extern void bgp_evpn_path_nh_add(struct bgp *bgp_vrf, struct bgp_path_info *pi); | |
462 | extern void bgp_evpn_path_nh_del(struct bgp *bgp_vrf, struct bgp_path_info *pi); | |
f4a5218d AK |
463 | extern void bgp_evpn_mh_config_ead_export_rt(struct bgp *bgp, |
464 | struct ecommunity *ecom, bool del); | |
c44ab6f1 | 465 | |
185fb14a | 466 | #endif /* _FRR_BGP_EVPN_MH_H */ |