1 /*
2  * Zebra VxLAN (EVPN) Data structures and definitions
3  * These are "internal" to this function.
4  * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
5  *
6  * This file is part of FRR.
7  *
8  * FRR is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation; either version 2, or (at your option) any
11  * later version.
12  *
13  * FRR is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with FRR; see the file COPYING.  If not, write to the Free
20  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21  * 02111-1307, USA.
22  */
23 
24 #ifndef _ZEBRA_VXLAN_PRIVATE_H
25 #define _ZEBRA_VXLAN_PRIVATE_H
26 
27 #include <zebra.h>
28 
29 #include "if.h"
30 #include "linklist.h"
31 #include "zebra_vxlan.h"
32 #include "zebra_evpn.h"
33 #include "zebra_evpn_mac.h"
34 
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38 
39 #define ERR_STR_SZ 256
40 
41 /* definitions */
42 typedef struct zebra_l3vni_t_ zebra_l3vni_t;
43 
44 
45 /* L3 VNI hash table */
46 struct zebra_l3vni_t_ {
47 
48 	/* VNI key */
49 	vni_t vni;
50 
51 	/* vrf_id */
52 	vrf_id_t vrf_id;
53 
54 	uint32_t filter;
55 #define PREFIX_ROUTES_ONLY	(1 << 0) /* l3-vni used for prefix routes only */
56 
57 	/* Local IP */
58 	struct in_addr local_vtep_ip;
59 
60 	/* kernel interface for l3vni */
61 	struct interface *vxlan_if;
62 
63 	/* SVI interface corresponding to the l3vni */
64 	struct interface *svi_if;
65 
66 	struct interface *mac_vlan_if;
67 
68 	/* list of L2 VNIs associated with the L3 VNI */
69 	struct list *l2vnis;
70 
71 	/* list of remote router-macs */
72 	struct hash *rmac_table;
73 
74 	/* list of remote vtep-ip neigh */
75 	struct hash *nh_table;
76 };
77 
78 /* get the vx-intf name for l3vni */
zl3vni_vxlan_if_name(zebra_l3vni_t * zl3vni)79 static inline const char *zl3vni_vxlan_if_name(zebra_l3vni_t *zl3vni)
80 {
81 	return zl3vni->vxlan_if ? zl3vni->vxlan_if->name : "None";
82 }
83 
84 /* get the svi intf name for l3vni */
zl3vni_svi_if_name(zebra_l3vni_t * zl3vni)85 static inline const char *zl3vni_svi_if_name(zebra_l3vni_t *zl3vni)
86 {
87 	return zl3vni->svi_if ? zl3vni->svi_if->name : "None";
88 }
89 
90 /* get the vrf name for l3vni */
zl3vni_vrf_name(zebra_l3vni_t * zl3vni)91 static inline const char *zl3vni_vrf_name(zebra_l3vni_t *zl3vni)
92 {
93 	return vrf_id_to_name(zl3vni->vrf_id);
94 }
95 
96 /* get the rmac string */
zl3vni_rmac2str(zebra_l3vni_t * zl3vni,char * buf,int size)97 static inline const char *zl3vni_rmac2str(zebra_l3vni_t *zl3vni, char *buf,
98 					  int size)
99 {
100 	char *ptr;
101 
102 	if (!buf)
103 		ptr = XMALLOC(MTYPE_TMP, ETHER_ADDR_STRLEN * sizeof(char));
104 	else {
105 		assert(size >= ETHER_ADDR_STRLEN);
106 		ptr = buf;
107 	}
108 
109 	if (zl3vni->mac_vlan_if)
110 		snprintf(ptr, (ETHER_ADDR_STRLEN),
111 			 "%02x:%02x:%02x:%02x:%02x:%02x",
112 			 (uint8_t)zl3vni->mac_vlan_if->hw_addr[0],
113 			 (uint8_t)zl3vni->mac_vlan_if->hw_addr[1],
114 			 (uint8_t)zl3vni->mac_vlan_if->hw_addr[2],
115 			 (uint8_t)zl3vni->mac_vlan_if->hw_addr[3],
116 			 (uint8_t)zl3vni->mac_vlan_if->hw_addr[4],
117 			 (uint8_t)zl3vni->mac_vlan_if->hw_addr[5]);
118 	else if (zl3vni->svi_if)
119 		snprintf(ptr, (ETHER_ADDR_STRLEN),
120 			 "%02x:%02x:%02x:%02x:%02x:%02x",
121 			 (uint8_t)zl3vni->svi_if->hw_addr[0],
122 			 (uint8_t)zl3vni->svi_if->hw_addr[1],
123 			 (uint8_t)zl3vni->svi_if->hw_addr[2],
124 			 (uint8_t)zl3vni->svi_if->hw_addr[3],
125 			 (uint8_t)zl3vni->svi_if->hw_addr[4],
126 			 (uint8_t)zl3vni->svi_if->hw_addr[5]);
127 	else
128 		snprintf(ptr, ETHER_ADDR_STRLEN, "None");
129 
130 	return ptr;
131 }
132 
133 /* get the sys mac string */
zl3vni_sysmac2str(zebra_l3vni_t * zl3vni,char * buf,int size)134 static inline const char *zl3vni_sysmac2str(zebra_l3vni_t *zl3vni, char *buf,
135 					    int size)
136 {
137 	char *ptr;
138 
139 	if (!buf)
140 		ptr = XMALLOC(MTYPE_TMP, ETHER_ADDR_STRLEN * sizeof(char));
141 	else {
142 		assert(size >= ETHER_ADDR_STRLEN);
143 		ptr = buf;
144 	}
145 
146 	if (zl3vni->svi_if)
147 		snprintf(ptr, (ETHER_ADDR_STRLEN),
148 			 "%02x:%02x:%02x:%02x:%02x:%02x",
149 			 (uint8_t)zl3vni->svi_if->hw_addr[0],
150 			 (uint8_t)zl3vni->svi_if->hw_addr[1],
151 			 (uint8_t)zl3vni->svi_if->hw_addr[2],
152 			 (uint8_t)zl3vni->svi_if->hw_addr[3],
153 			 (uint8_t)zl3vni->svi_if->hw_addr[4],
154 			 (uint8_t)zl3vni->svi_if->hw_addr[5]);
155 	else
156 		snprintf(ptr, ETHER_ADDR_STRLEN, "None");
157 
158 	return ptr;
159 }
160 
161 /*
162  * l3-vni is oper up when:
163  * 0. if EVPN is enabled (advertise-all-vni cfged)
164  * 1. it is associated to a vxlan-intf
165  * 2. Associated vxlan-intf is oper up
166  * 3. it is associated to an SVI
167  * 4. associated SVI is oper up
168  */
is_l3vni_oper_up(zebra_l3vni_t * zl3vni)169 static inline int is_l3vni_oper_up(zebra_l3vni_t *zl3vni)
170 {
171 	return (is_evpn_enabled() && zl3vni && (zl3vni->vrf_id != VRF_UNKNOWN)
172 		&& zl3vni->vxlan_if && if_is_operative(zl3vni->vxlan_if)
173 		&& zl3vni->svi_if && if_is_operative(zl3vni->svi_if));
174 }
175 
zl3vni_state2str(zebra_l3vni_t * zl3vni)176 static inline const char *zl3vni_state2str(zebra_l3vni_t *zl3vni)
177 {
178 	if (!zl3vni)
179 		return NULL;
180 
181 	if (is_l3vni_oper_up(zl3vni))
182 		return "Up";
183 	else
184 		return "Down";
185 
186 	return NULL;
187 }
188 
zl3vni_vrf_id(zebra_l3vni_t * zl3vni)189 static inline vrf_id_t zl3vni_vrf_id(zebra_l3vni_t *zl3vni)
190 {
191 	return zl3vni->vrf_id;
192 }
193 
zl3vni_get_svi_rmac(zebra_l3vni_t * zl3vni,struct ethaddr * rmac)194 static inline void zl3vni_get_svi_rmac(zebra_l3vni_t *zl3vni,
195 				       struct ethaddr *rmac)
196 {
197 	if (!zl3vni)
198 		return;
199 
200 	if (!is_l3vni_oper_up(zl3vni))
201 		return;
202 
203 	if (zl3vni->svi_if && if_is_operative(zl3vni->svi_if))
204 		memcpy(rmac->octet, zl3vni->svi_if->hw_addr, ETH_ALEN);
205 }
206 
207 
208 /* context for neigh hash walk - update l3vni and rmac */
209 struct neigh_l3info_walk_ctx {
210 
211 	zebra_evpn_t *zevpn;
212 	zebra_l3vni_t *zl3vni;
213 	int add;
214 };
215 
216 struct nh_walk_ctx {
217 
218 	struct vty *vty;
219 	struct json_object *json;
220 };
221 
222 extern zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t vrf_id);
223 extern struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni);
224 extern struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni);
225 extern struct interface *zl3vni_map_to_mac_vlan_if(zebra_l3vni_t *zl3vni);
226 extern zebra_l3vni_t *zl3vni_lookup(vni_t vni);
227 
228 DECLARE_HOOK(zebra_rmac_update, (zebra_mac_t *rmac, zebra_l3vni_t *zl3vni,
229 	     bool delete, const char *reason), (rmac, zl3vni, delete, reason))
230 
231 
232 #ifdef __cplusplus
233 }
234 #endif
235 
236 /*
237  * Multicast hash table.
238  *
239  * This table contains -
240  * 1. The (S, G) entries used for encapsulating and forwarding BUM traffic.
241  *    S is the local VTEP-IP and G is a BUM mcast group address.
242  * 2. The (X, G) entries used for terminating a BUM flow.
243  * Multiple L2-VNIs can share the same MDT hence the need to maintain
244  * an aggregated table that pimd can consume without much
245  * re-interpretation.
246  */
247 typedef struct zebra_vxlan_sg_ {
248 	struct zebra_vrf *zvrf;
249 
250 	struct prefix_sg sg;
251 	char sg_str[PREFIX_SG_STR_LEN];
252 
253 	/* For SG - num of L2 VNIs using this entry for sending BUM traffic */
254 	/* For XG - num of SG using this as parent */
255 	uint32_t ref_cnt;
256 } zebra_vxlan_sg_t;
257 
258 extern zebra_evpn_t *zevpn_lookup(vni_t vni);
259 extern void zebra_vxlan_sync_mac_dp_install(zebra_mac_t *mac, bool set_inactive,
260 		bool force_clear_static, const char *caller);
261 
262 #endif /* _ZEBRA_VXLAN_PRIVATE_H */
263