]>
Commit | Line | Data |
---|---|---|
b2998086 PR |
1 | /* |
2 | * Zebra EVPN MAC Data structures and definitions | |
3 | * These are "internal" to this function. | |
4 | * Copyright (C) 2016, 2017 Cumulus Networks, Inc. | |
5 | * Copyright (C) 2020 Volta Networks. | |
6 | * | |
7 | * This file is part of FRR. | |
8 | * | |
9 | * FRR is free software; you can redistribute it and/or modify it | |
10 | * under the terms of the GNU General Public License as published by the | |
11 | * Free Software Foundation; either version 2, or (at your option) any | |
12 | * later version. | |
13 | * | |
14 | * FRR is distributed in the hope that it will be useful, but | |
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with FRR; see the file COPYING. If not, write to the Free | |
21 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
22 | * 02111-1307, USA. | |
23 | */ | |
24 | ||
25 | #ifndef _ZEBRA_EVPN_MAC_H | |
26 | #define _ZEBRA_EVPN_MAC_H | |
27 | ||
28 | #ifdef __cplusplus | |
29 | extern "C" { | |
30 | #endif | |
31 | ||
b2998086 PR |
32 | |
33 | struct host_rb_entry { | |
34 | RB_ENTRY(host_rb_entry) hl_entry; | |
35 | ||
36 | struct prefix p; | |
37 | }; | |
38 | ||
39 | RB_HEAD(host_rb_tree_entry, host_rb_entry); | |
40 | RB_PROTOTYPE(host_rb_tree_entry, host_rb_entry, hl_entry, | |
41 | host_rb_entry_compare); | |
42 | /* | |
43 | * MAC hash table. | |
44 | * | |
45 | * This table contains the MAC addresses pertaining to this VNI. | |
46 | * This includes local MACs learnt on an attached VLAN that maps | |
47 | * to this VNI as well as remote MACs learnt and installed by BGP. | |
48 | * Local MACs will be known either on a VLAN sub-interface or | |
49 | * on (port, VLAN); however, it is sufficient for zebra to maintain | |
50 | * against the VNI i.e., it does not need to retain the local "port" | |
51 | * information. The correct VNI will be obtained as zebra maintains | |
52 | * the mapping (of VLAN to VNI). | |
53 | */ | |
3198b2b3 | 54 | struct zebra_mac { |
b2998086 PR |
55 | /* MAC address. */ |
56 | struct ethaddr macaddr; | |
57 | ||
b16e8004 | 58 | /* When modifying flags please fixup zebra_evpn_zebra_mac_flag_dump */ |
b2998086 PR |
59 | uint32_t flags; |
60 | #define ZEBRA_MAC_LOCAL 0x01 | |
61 | #define ZEBRA_MAC_REMOTE 0x02 | |
62 | #define ZEBRA_MAC_AUTO 0x04 /* Auto created for neighbor. */ | |
63 | #define ZEBRA_MAC_STICKY 0x08 /* Static MAC */ | |
64 | #define ZEBRA_MAC_REMOTE_RMAC 0x10 /* remote router mac */ | |
65 | #define ZEBRA_MAC_DEF_GW 0x20 | |
66 | /* remote VTEP advertised MAC as default GW */ | |
67 | #define ZEBRA_MAC_REMOTE_DEF_GW 0x40 | |
68 | #define ZEBRA_MAC_DUPLICATE 0x80 | |
69 | #define ZEBRA_MAC_FPM_SENT 0x100 /* whether or not this entry was sent. */ | |
70 | /* MAC is locally active on an ethernet segment peer */ | |
71 | #define ZEBRA_MAC_ES_PEER_ACTIVE 0x200 | |
72 | /* MAC has been proxy-advertised by peers. This means we need to | |
73 | * keep the entry for forwarding but cannot advertise it | |
74 | */ | |
75 | #define ZEBRA_MAC_ES_PEER_PROXY 0x400 | |
76 | /* We have not been able to independently establish that the host is | |
77 | * local connected but one or more ES peers claims it is. | |
78 | * We will maintain the entry for forwarding purposes and continue | |
79 | * to advertise it as locally attached but with a "proxy" flag | |
80 | */ | |
81 | #define ZEBRA_MAC_LOCAL_INACTIVE 0x800 | |
243b74ed AK |
82 | /* The MAC entry was created because of advertise_svi_mac */ |
83 | #define ZEBRA_MAC_SVI 0x1000 | |
b2998086 PR |
84 | |
85 | #define ZEBRA_MAC_ALL_LOCAL_FLAGS (ZEBRA_MAC_LOCAL | ZEBRA_MAC_LOCAL_INACTIVE) | |
86 | #define ZEBRA_MAC_ALL_PEER_FLAGS \ | |
87 | (ZEBRA_MAC_ES_PEER_PROXY | ZEBRA_MAC_ES_PEER_ACTIVE) | |
88 | ||
89 | /* back pointer to zevpn */ | |
f6371c34 | 90 | struct zebra_evpn *zevpn; |
b2998086 | 91 | |
8b07f173 AK |
92 | /* Local or remote info. |
93 | * Note: fwd_info is only relevant if mac->es is NULL. | |
94 | */ | |
b2998086 PR |
95 | union { |
96 | struct { | |
97 | ifindex_t ifindex; | |
47c58929 | 98 | ns_id_t ns_id; |
b2998086 PR |
99 | vlanid_t vid; |
100 | } local; | |
101 | ||
102 | struct in_addr r_vtep_ip; | |
103 | } fwd_info; | |
104 | ||
105 | /* Local or remote ES */ | |
106 | struct zebra_evpn_es *es; | |
107 | /* memory used to link the mac to the es */ | |
108 | struct listnode es_listnode; | |
109 | ||
8b07f173 AK |
110 | /* access-port/bridge member. only relevant for local macs that |
111 | * are associated with a zero-ESI, | |
112 | * XXX - this belongs in fwd_info.local; however fwd_info is | |
113 | * being cleared and memset to zero in different ways that can | |
114 | * mess up the links. | |
115 | */ | |
116 | struct interface *ifp; | |
117 | /* memory used to link the mac to the ifp */ | |
118 | struct listnode ifp_listnode; | |
119 | ||
b2998086 PR |
120 | /* Mobility sequence numbers associated with this entry. */ |
121 | uint32_t rem_seq; | |
122 | uint32_t loc_seq; | |
123 | ||
124 | /* List of neigh associated with this mac */ | |
125 | struct list *neigh_list; | |
126 | ||
db889978 CS |
127 | /* List of nexthop associated with this RMAC */ |
128 | struct list *nh_list; | |
b2998086 PR |
129 | |
130 | /* Duplicate mac detection */ | |
131 | uint32_t dad_count; | |
132 | ||
133 | struct thread *dad_mac_auto_recovery_timer; | |
134 | ||
135 | struct timeval detect_start_time; | |
136 | ||
137 | time_t dad_dup_detect_time; | |
138 | ||
139 | /* used for ageing out the PEER_ACTIVE flag */ | |
140 | struct thread *hold_timer; | |
141 | ||
142 | /* number of neigh entries (using this mac) that have | |
143 | * ZEBRA_MAC_ES_PEER_ACTIVE or ZEBRA_NEIGH_ES_PEER_PROXY | |
144 | */ | |
145 | uint32_t sync_neigh_cnt; | |
f1dbb1c7 DS |
146 | |
147 | time_t uptime; | |
b2998086 PR |
148 | }; |
149 | ||
150 | /* | |
151 | * Context for MAC hash walk - used by callbacks. | |
152 | */ | |
153 | struct mac_walk_ctx { | |
f6371c34 | 154 | struct zebra_evpn *zevpn; /* EVPN hash */ |
b2998086 PR |
155 | struct zebra_vrf *zvrf; /* VRF - for client notification. */ |
156 | int uninstall; /* uninstall from kernel? */ | |
157 | int upd_client; /* uninstall from client? */ | |
158 | ||
159 | uint32_t flags; | |
160 | #define DEL_LOCAL_MAC 0x1 | |
161 | #define DEL_REMOTE_MAC 0x2 | |
162 | #define DEL_ALL_MAC (DEL_LOCAL_MAC | DEL_REMOTE_MAC) | |
163 | #define DEL_REMOTE_MAC_FROM_VTEP 0x4 | |
164 | #define SHOW_REMOTE_MAC_FROM_VTEP 0x8 | |
165 | ||
166 | struct in_addr r_vtep_ip; /* To walk MACs from specific VTEP */ | |
167 | ||
168 | struct vty *vty; /* Used by VTY handlers */ | |
169 | uint32_t count; /* Used by VTY handlers */ | |
170 | struct json_object *json; /* Used for JSON Output */ | |
171 | bool print_dup; /* Used to print dup addr list */ | |
172 | }; | |
173 | ||
174 | struct rmac_walk_ctx { | |
175 | struct vty *vty; | |
176 | struct json_object *json; | |
177 | }; | |
178 | ||
179 | /* temporary datastruct to pass info between the mac-update and | |
180 | * neigh-update while handling mac-ip routes | |
181 | */ | |
182 | struct sync_mac_ip_ctx { | |
183 | bool ignore_macip; | |
184 | bool mac_created; | |
185 | bool mac_inactive; | |
186 | bool mac_dp_update_deferred; | |
3198b2b3 | 187 | struct zebra_mac *mac; |
b2998086 PR |
188 | }; |
189 | ||
190 | /**************************** SYNC MAC handling *****************************/ | |
191 | /* if the mac has been added of a mac-route from the peer | |
192 | * or if it is being referenced by a neigh added by the | |
193 | * peer we cannot let it age out i.e. we set the static bit | |
194 | * in the dataplane | |
195 | */ | |
3198b2b3 | 196 | static inline bool zebra_evpn_mac_is_static(struct zebra_mac *mac) |
b2998086 PR |
197 | { |
198 | return ((mac->flags & ZEBRA_MAC_ALL_PEER_FLAGS) || mac->sync_neigh_cnt); | |
199 | } | |
200 | ||
201 | /* mac needs to be locally active or active on an ES peer */ | |
202 | static inline bool zebra_evpn_mac_is_ready_for_bgp(uint32_t flags) | |
203 | { | |
204 | return (flags & ZEBRA_MAC_LOCAL) | |
205 | && (!(flags & ZEBRA_MAC_LOCAL_INACTIVE) | |
206 | || (flags & ZEBRA_MAC_ES_PEER_ACTIVE)); | |
207 | } | |
208 | ||
3198b2b3 | 209 | void zebra_evpn_mac_stop_hold_timer(struct zebra_mac *mac); |
19fdd1be | 210 | |
3198b2b3 | 211 | static inline void zebra_evpn_mac_clear_sync_info(struct zebra_mac *mac) |
b2998086 PR |
212 | { |
213 | UNSET_FLAG(mac->flags, ZEBRA_MAC_ALL_PEER_FLAGS); | |
214 | zebra_evpn_mac_stop_hold_timer(mac); | |
215 | } | |
216 | ||
3198b2b3 | 217 | static inline bool zebra_evpn_mac_in_use(struct zebra_mac *mac) |
243b74ed AK |
218 | { |
219 | return !list_isempty(mac->neigh_list) | |
220 | || CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI); | |
221 | } | |
222 | ||
b2998086 | 223 | struct hash *zebra_mac_db_create(const char *desc); |
f6371c34 DS |
224 | uint32_t num_valid_macs(struct zebra_evpn *zevi); |
225 | uint32_t num_dup_detected_macs(struct zebra_evpn *zevi); | |
3198b2b3 | 226 | int zebra_evpn_rem_mac_uninstall(struct zebra_evpn *zevi, struct zebra_mac *mac, |
f3722826 | 227 | bool force); |
3198b2b3 | 228 | int zebra_evpn_rem_mac_install(struct zebra_evpn *zevi, struct zebra_mac *mac, |
b2998086 | 229 | bool was_static); |
3198b2b3 DS |
230 | void zebra_evpn_deref_ip2mac(struct zebra_evpn *zevi, struct zebra_mac *mac); |
231 | struct zebra_mac *zebra_evpn_mac_lookup(struct zebra_evpn *zevi, | |
232 | const struct ethaddr *mac); | |
233 | struct zebra_mac *zebra_evpn_mac_add(struct zebra_evpn *zevi, | |
234 | const struct ethaddr *macaddr); | |
235 | int zebra_evpn_mac_del(struct zebra_evpn *zevi, struct zebra_mac *mac); | |
1a3bd37f MS |
236 | int zebra_evpn_macip_send_msg_to_client(uint32_t id, |
237 | const struct ethaddr *macaddr, | |
238 | const struct ipaddr *ip, uint8_t flags, | |
b2998086 PR |
239 | uint32_t seq, int state, |
240 | struct zebra_evpn_es *es, uint16_t cmd); | |
3198b2b3 | 241 | void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json); |
b2998086 PR |
242 | void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt); |
243 | void zebra_evpn_print_mac_hash_detail(struct hash_bucket *bucket, void *ctxt); | |
3198b2b3 | 244 | int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive, |
15400f95 | 245 | bool force_clear_static, const char *caller); |
3198b2b3 DS |
246 | void zebra_evpn_mac_send_add_del_to_client(struct zebra_mac *mac, |
247 | bool old_bgp_ready, | |
d9d3455e | 248 | bool new_bgp_ready); |
b2998086 | 249 | |
f6371c34 DS |
250 | void zebra_evpn_mac_del_all(struct zebra_evpn *zevi, int uninstall, |
251 | int upd_client, uint32_t flags); | |
1a3bd37f | 252 | int zebra_evpn_mac_send_add_to_client(vni_t vni, const struct ethaddr *macaddr, |
b2998086 PR |
253 | uint32_t mac_flags, uint32_t seq, |
254 | struct zebra_evpn_es *es); | |
1a3bd37f | 255 | int zebra_evpn_mac_send_del_to_client(vni_t vni, const struct ethaddr *macaddr, |
b2998086 | 256 | uint32_t flags, bool force); |
f6371c34 | 257 | void zebra_evpn_send_mac_list_to_client(struct zebra_evpn *zevi); |
3198b2b3 | 258 | struct zebra_mac *zebra_evpn_proc_sync_mac_update( |
f6371c34 DS |
259 | struct zebra_evpn *zevi, const struct ethaddr *macaddr, |
260 | uint16_t ipa_len, const struct ipaddr *ipaddr, uint8_t flags, | |
261 | uint32_t seq, const esi_t *esi, struct sync_mac_ip_ctx *ctx); | |
3198b2b3 DS |
262 | void zebra_evpn_sync_mac_del(struct zebra_mac *mac); |
263 | void zebra_evpn_rem_mac_del(struct zebra_evpn *zevi, struct zebra_mac *mac); | |
b2998086 PR |
264 | void zebra_evpn_print_dad_mac_hash(struct hash_bucket *bucket, void *ctxt); |
265 | void zebra_evpn_print_dad_mac_hash_detail(struct hash_bucket *bucket, | |
266 | void *ctxt); | |
f6371c34 DS |
267 | int zebra_evpn_mac_remote_macip_add( |
268 | struct zebra_evpn *zevpn, struct zebra_vrf *zvrf, | |
269 | const struct ethaddr *macaddr, uint16_t ipa_len, | |
3198b2b3 DS |
270 | const struct ipaddr *ipaddr, struct zebra_mac **macp, |
271 | struct in_addr vtep_ip, uint8_t flags, uint32_t seq, const esi_t *esi); | |
f6371c34 DS |
272 | |
273 | int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, | |
274 | struct zebra_evpn *zevpn, | |
d9d3455e | 275 | struct interface *ifp, |
1a3bd37f | 276 | const struct ethaddr *macaddr, vlanid_t vid, |
d9d3455e | 277 | bool sticky, bool local_inactive, |
3198b2b3 DS |
278 | bool dp_static, struct zebra_mac *mac); |
279 | int zebra_evpn_del_local_mac(struct zebra_evpn *zevpn, struct zebra_mac *mac, | |
00a7710c | 280 | bool clear_static); |
5ff58d0a | 281 | void zebra_evpn_mac_gw_macip_add(struct interface *ifp, |
282 | struct zebra_evpn *zevpn, | |
283 | const struct ipaddr *ip, | |
284 | struct zebra_mac **macp, | |
285 | const struct ethaddr *macaddr, | |
286 | vlanid_t vlan_id, bool def_gw); | |
f6371c34 DS |
287 | void zebra_evpn_mac_svi_add(struct interface *ifp, struct zebra_evpn *zevpn); |
288 | void zebra_evpn_mac_svi_del(struct interface *ifp, struct zebra_evpn *zevpn); | |
8b07f173 | 289 | void zebra_evpn_mac_ifp_del(struct interface *ifp); |
3198b2b3 | 290 | void zebra_evpn_mac_clear_fwd_info(struct zebra_mac *zmac); |
ad6ca5f4 | 291 | |
b2998086 PR |
292 | #ifdef __cplusplus |
293 | } | |
294 | #endif | |
295 | ||
296 | #endif /*_ZEBRA_EVPN_MAC_H */ |