]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_attr_evpn.c
Merge pull request #7809 from donaldsharp/m_coverity
[mirror_frr.git] / bgpd / bgp_attr_evpn.c
CommitLineData
212f5cbc 1/* Ethernet-VPN Attribute handling file
896014f4
DL
2 * Copyright (C) 2016 6WIND
3 *
4 * This file is part of FRRouting.
5 *
6 * FRRouting is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * FRRouting is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
212f5cbc
PG
20
21#include <zebra.h>
22
23#include "command.h"
7ef5a232 24#include "filter.h"
212f5cbc
PG
25#include "prefix.h"
26#include "log.h"
27#include "memory.h"
28#include "stream.h"
74e2bd89 29#include "vxlan.h"
212f5cbc 30
dfa42ea3
PG
31#include "bgpd/bgpd.h"
32#include "bgpd/bgp_attr.h"
33#include "bgpd/bgp_route.h"
212f5cbc 34#include "bgpd/bgp_attr_evpn.h"
dfa42ea3 35#include "bgpd/bgp_ecommunity.h"
3da6fcd5 36#include "bgpd/bgp_evpn.h"
128ea8ab 37#include "bgpd/bgp_evpn_private.h"
dfa42ea3 38
31689a53 39void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac)
dfa42ea3 40{
d62a17ae 41 struct ecommunity_val routermac_ecom;
42
43 memset(&routermac_ecom, 0, sizeof(struct ecommunity_val));
44 routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN;
45 routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC;
28328ea9 46 memcpy(&routermac_ecom.val[2], routermac->octet, ETH_ALEN);
d62a17ae 47 if (!attr->ecommunity)
48 attr->ecommunity = ecommunity_new();
1207a5bc 49 ecommunity_add_val(attr->ecommunity, &routermac_ecom, false, false);
d62a17ae 50 ecommunity_str(attr->ecommunity);
dfa42ea3 51}
212f5cbc 52
212f5cbc
PG
53/* converts to an esi
54 * returns 1 on success, 0 otherwise
55 * format accepted: AA:BB:CC:DD:EE:FF:GG:HH:II:JJ
56 * if id is null, check only is done
57 */
0a50c248 58bool str2esi(const char *str, esi_t *id)
212f5cbc 59{
0a50c248 60 unsigned int a[ESI_BYTES];
d62a17ae 61 int i;
62
63 if (!str)
3dc339cd 64 return false;
d62a17ae 65 if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x", a + 0, a + 1,
66 a + 2, a + 3, a + 4, a + 5, a + 6, a + 7, a + 8, a + 9)
0a50c248 67 != ESI_BYTES) {
d62a17ae 68 /* error in incoming str length */
3dc339cd 69 return false;
d62a17ae 70 }
71 /* valid mac address */
72 if (!id)
3dc339cd 73 return true;
0a50c248 74 for (i = 0; i < ESI_BYTES; ++i)
d62a17ae 75 id->val[i] = a[i] & 0xff;
3dc339cd 76 return true;
212f5cbc
PG
77}
78
212f5cbc
PG
79char *ecom_mac2str(char *ecom_mac)
80{
d62a17ae 81 char *en;
212f5cbc 82
d62a17ae 83 en = ecom_mac;
84 en += 2;
128ea8ab 85
d62a17ae 86 return prefix_mac2str((struct ethaddr *)en, NULL, 0);
128ea8ab 87}
88
bc59a672 89/* Fetch router-mac from extended community */
eee353c5 90bool bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac)
bc59a672
MK
91{
92 int i = 0;
93 struct ecommunity *ecom;
94
95 ecom = attr->ecommunity;
96 if (!ecom || !ecom->size)
eee353c5 97 return false;
bc59a672
MK
98
99 /* If there is a router mac extended community, set RMAC in attr */
100 for (i = 0; i < ecom->size; i++) {
d7c0a89a
QY
101 uint8_t *pnt = NULL;
102 uint8_t type = 0;
103 uint8_t sub_type = 0;
bc59a672
MK
104
105 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
106 type = *pnt++;
107 sub_type = *pnt++;
108
996c9314
LB
109 if (!(type == ECOMMUNITY_ENCODE_EVPN
110 && sub_type == ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC))
bc59a672
MK
111 continue;
112
113 memcpy(rmac, pnt, ETH_ALEN);
eee353c5 114 return true;
bc59a672 115 }
eee353c5 116 return false;
bc59a672
MK
117}
118
ead40654
MK
119/*
120 * return true if attr contains default gw extended community
121 */
122uint8_t bgp_attr_default_gw(struct attr *attr)
123{
996c9314
LB
124 struct ecommunity *ecom;
125 int i;
ead40654
MK
126
127 ecom = attr->ecommunity;
128 if (!ecom || !ecom->size)
129 return 0;
130
131 /* If there is a default gw extendd community return true otherwise
132 * return 0 */
133 for (i = 0; i < ecom->size; i++) {
d7c0a89a
QY
134 uint8_t *pnt;
135 uint8_t type, sub_type;
ead40654
MK
136
137 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
138 type = *pnt++;
139 sub_type = *pnt++;
140
141 if ((type == ECOMMUNITY_ENCODE_OPAQUE
996c9314 142 && sub_type == ECOMMUNITY_EVPN_SUBTYPE_DEF_GW))
ead40654
MK
143 return 1;
144 }
145
146 return 0;
147}
148
74e2bd89
AK
149/*
150 * Fetch and return the DF preference and algorithm from
151 * DF election extended community, if present, else 0.
152 */
153uint16_t bgp_attr_df_pref_from_ec(struct attr *attr, uint8_t *alg)
154{
155 struct ecommunity *ecom;
156 int i;
157 uint16_t df_pref = 0;
158
159 *alg = EVPN_MH_DF_ALG_SERVICE_CARVING;
160 ecom = attr->ecommunity;
161 if (!ecom || !ecom->size)
162 return 0;
163
164 for (i = 0; i < ecom->size; i++) {
165 uint8_t *pnt;
166 uint8_t type, sub_type;
167
168 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
169 type = *pnt++;
170 sub_type = *pnt++;
171 if (!(type == ECOMMUNITY_ENCODE_EVPN
172 && sub_type == ECOMMUNITY_EVPN_SUBTYPE_DF_ELECTION))
173 continue;
174
175 *alg = (*pnt++) & ECOMMUNITY_EVPN_SUBTYPE_DF_ALG_BITS;
176
177 pnt += 3;
178 pnt = ptr_get_be16(pnt, &df_pref);
179 (void)pnt; /* consume value */
180 break;
181 }
182
183 return df_pref;
184}
185
128ea8ab 186/*
187 * Fetch and return the sequence number from MAC Mobility extended
188 * community, if present, else 0.
189 */
d7c0a89a 190uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky)
128ea8ab 191{
d62a17ae 192 struct ecommunity *ecom;
193 int i;
d7c0a89a 194 uint8_t flags = 0;
d62a17ae 195
196 ecom = attr->ecommunity;
197 if (!ecom || !ecom->size)
198 return 0;
199
200 /* If there is a MAC Mobility extended community, return its
201 * sequence number.
202 * TODO: RFC is silent on handling of multiple MAC mobility extended
203 * communities for the same route. We will bail out upon the first
204 * one.
205 */
206 for (i = 0; i < ecom->size; i++) {
1be1693e 207 const uint8_t *pnt;
d7c0a89a
QY
208 uint8_t type, sub_type;
209 uint32_t seq_num;
d62a17ae 210
211 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
212 type = *pnt++;
213 sub_type = *pnt++;
214 if (!(type == ECOMMUNITY_ENCODE_EVPN
215 && sub_type == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY))
216 continue;
217 flags = *pnt++;
218
219 if (flags & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY)
220 *sticky = 1;
221 else
222 *sticky = 0;
223
224 pnt++;
937652c6
DL
225 pnt = ptr_get_be32(pnt, &seq_num);
226 (void)pnt; /* consume value */
d62a17ae 227 return seq_num;
228 }
229
230 return 0;
212f5cbc 231}
3da6fcd5 232
68e33151
CS
233/*
234 * return true if attr contains router flag extended community
235 */
7904e9fd
AK
236void bgp_attr_evpn_na_flag(struct attr *attr,
237 uint8_t *router_flag, bool *proxy)
68e33151
CS
238{
239 struct ecommunity *ecom;
240 int i;
241 uint8_t val;
242
243 ecom = attr->ecommunity;
244 if (!ecom || !ecom->size)
245 return;
246
247 /* If there is a evpn na extendd community set router_flag */
248 for (i = 0; i < ecom->size; i++) {
249 uint8_t *pnt;
250 uint8_t type, sub_type;
251
252 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
253 type = *pnt++;
254 sub_type = *pnt++;
255
256 if (type == ECOMMUNITY_ENCODE_EVPN &&
257 sub_type == ECOMMUNITY_EVPN_SUBTYPE_ND) {
258 val = *pnt++;
7904e9fd
AK
259
260 if (val & ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG)
68e33151 261 *router_flag = 1;
7904e9fd
AK
262
263 if (val & ECOMMUNITY_EVPN_SUBTYPE_PROXY_FLAG)
264 *proxy = true;
265
266 break;
68e33151
CS
267 }
268 }
269}
270
3da6fcd5 271/* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
d62a17ae 272extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
273 struct prefix *dst)
3da6fcd5 274{
d62a17ae 275 struct evpn_addr *p_evpn_p;
276 struct prefix p2;
277 struct prefix *src = &p2;
278
279 if (!dst || dst->family == 0)
280 return -1;
281 /* store initial prefix in src */
282 prefix_copy(src, dst);
283 memset(dst, 0, sizeof(struct prefix));
284 p_evpn_p = &(dst->u.prefix_evpn);
b03b8898 285 dst->family = AF_EVPN;
d62a17ae 286 p_evpn_p->route_type = evpn_type;
287 if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) {
3714a385 288 p_evpn_p->prefix_addr.eth_tag = eth_tag;
289 p_evpn_p->prefix_addr.ip_prefix_length = p2.prefixlen;
d62a17ae 290 if (src->family == AF_INET) {
3714a385 291 SET_IPADDR_V4(&p_evpn_p->prefix_addr.ip);
292 memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v4,
293 &src->u.prefix4,
d62a17ae 294 sizeof(struct in_addr));
61be6e94 295 dst->prefixlen = (uint16_t)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
d62a17ae 296 } else {
3714a385 297 SET_IPADDR_V6(&p_evpn_p->prefix_addr.ip);
298 memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v6,
299 &src->u.prefix6,
d62a17ae 300 sizeof(struct in6_addr));
61be6e94 301 dst->prefixlen = (uint16_t)PREFIX_LEN_ROUTE_TYPE_5_IPV6;
d62a17ae 302 }
303 } else
304 return -1;
305 return 0;
3da6fcd5 306}
c6ec0c74
KA
307
308extern bool is_zero_gw_ip(const union gw_addr *gw_ip, const afi_t afi)
309{
310 if (afi == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(&gw_ip->ipv6))
311 return true;
312
313 if (afi == AF_INET && gw_ip->ipv4.s_addr == INADDR_ANY)
314 return true;
315
316 return false;
317}