]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_attr_evpn.c
Merge pull request #3444 from donaldsharp/adj_stuff
[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"
29
dfa42ea3
PG
30#include "bgpd/bgpd.h"
31#include "bgpd/bgp_attr.h"
32#include "bgpd/bgp_route.h"
212f5cbc 33#include "bgpd/bgp_attr_evpn.h"
dfa42ea3 34#include "bgpd/bgp_ecommunity.h"
3da6fcd5 35#include "bgpd/bgp_evpn.h"
128ea8ab 36#include "bgpd/bgp_evpn_private.h"
dfa42ea3 37
31689a53 38void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac)
dfa42ea3 39{
d62a17ae 40 struct ecommunity_val routermac_ecom;
41
42 memset(&routermac_ecom, 0, sizeof(struct ecommunity_val));
43 routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN;
44 routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC;
28328ea9 45 memcpy(&routermac_ecom.val[2], routermac->octet, ETH_ALEN);
d62a17ae 46 if (!attr->ecommunity)
47 attr->ecommunity = ecommunity_new();
48 ecommunity_add_val(attr->ecommunity, &routermac_ecom);
49 ecommunity_str(attr->ecommunity);
dfa42ea3 50}
212f5cbc 51
212f5cbc
PG
52/* converts to an esi
53 * returns 1 on success, 0 otherwise
54 * format accepted: AA:BB:CC:DD:EE:FF:GG:HH:II:JJ
55 * if id is null, check only is done
56 */
4d0e6ece 57int str2esi(const char *str, struct eth_segment_id *id)
212f5cbc 58{
d62a17ae 59 unsigned int a[ESI_LEN];
60 int i;
61
62 if (!str)
63 return 0;
64 if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x", a + 0, a + 1,
65 a + 2, a + 3, a + 4, a + 5, a + 6, a + 7, a + 8, a + 9)
66 != ESI_LEN) {
67 /* error in incoming str length */
68 return 0;
69 }
70 /* valid mac address */
71 if (!id)
72 return 1;
73 for (i = 0; i < ESI_LEN; ++i)
74 id->val[i] = a[i] & 0xff;
75 return 1;
212f5cbc
PG
76}
77
4d0e6ece 78char *esi2str(struct eth_segment_id *id)
212f5cbc 79{
d62a17ae 80 char *ptr;
d7c0a89a 81 uint8_t *val;
212f5cbc 82
d62a17ae 83 if (!id)
84 return NULL;
212f5cbc 85
d62a17ae 86 val = id->val;
87 ptr = (char *)XMALLOC(MTYPE_TMP,
88 (ESI_LEN * 2 + ESI_LEN - 1 + 1) * sizeof(char));
212f5cbc 89
d62a17ae 90 snprintf(ptr, (ESI_LEN * 2 + ESI_LEN - 1 + 1),
91 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", val[0],
92 val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8],
93 val[9]);
212f5cbc 94
d62a17ae 95 return ptr;
212f5cbc
PG
96}
97
212f5cbc
PG
98char *ecom_mac2str(char *ecom_mac)
99{
d62a17ae 100 char *en;
212f5cbc 101
d62a17ae 102 en = ecom_mac;
103 en += 2;
128ea8ab 104
d62a17ae 105 return prefix_mac2str((struct ethaddr *)en, NULL, 0);
128ea8ab 106}
107
bc59a672 108/* Fetch router-mac from extended community */
996c9314 109void bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac)
bc59a672
MK
110{
111 int i = 0;
112 struct ecommunity *ecom;
113
114 ecom = attr->ecommunity;
115 if (!ecom || !ecom->size)
116 return;
117
118 /* If there is a router mac extended community, set RMAC in attr */
119 for (i = 0; i < ecom->size; i++) {
d7c0a89a
QY
120 uint8_t *pnt = NULL;
121 uint8_t type = 0;
122 uint8_t sub_type = 0;
bc59a672
MK
123
124 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
125 type = *pnt++;
126 sub_type = *pnt++;
127
996c9314
LB
128 if (!(type == ECOMMUNITY_ENCODE_EVPN
129 && sub_type == ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC))
bc59a672
MK
130 continue;
131
132 memcpy(rmac, pnt, ETH_ALEN);
133 }
134}
135
ead40654
MK
136/*
137 * return true if attr contains default gw extended community
138 */
139uint8_t bgp_attr_default_gw(struct attr *attr)
140{
996c9314
LB
141 struct ecommunity *ecom;
142 int i;
ead40654
MK
143
144 ecom = attr->ecommunity;
145 if (!ecom || !ecom->size)
146 return 0;
147
148 /* If there is a default gw extendd community return true otherwise
149 * return 0 */
150 for (i = 0; i < ecom->size; i++) {
d7c0a89a
QY
151 uint8_t *pnt;
152 uint8_t type, sub_type;
ead40654
MK
153
154 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
155 type = *pnt++;
156 sub_type = *pnt++;
157
158 if ((type == ECOMMUNITY_ENCODE_OPAQUE
996c9314 159 && sub_type == ECOMMUNITY_EVPN_SUBTYPE_DEF_GW))
ead40654
MK
160 return 1;
161 }
162
163 return 0;
164}
165
128ea8ab 166/*
167 * Fetch and return the sequence number from MAC Mobility extended
168 * community, if present, else 0.
169 */
d7c0a89a 170uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky)
128ea8ab 171{
d62a17ae 172 struct ecommunity *ecom;
173 int i;
d7c0a89a 174 uint8_t flags = 0;
d62a17ae 175
176 ecom = attr->ecommunity;
177 if (!ecom || !ecom->size)
178 return 0;
179
180 /* If there is a MAC Mobility extended community, return its
181 * sequence number.
182 * TODO: RFC is silent on handling of multiple MAC mobility extended
183 * communities for the same route. We will bail out upon the first
184 * one.
185 */
186 for (i = 0; i < ecom->size; i++) {
d7c0a89a
QY
187 uint8_t *pnt;
188 uint8_t type, sub_type;
189 uint32_t seq_num;
d62a17ae 190
191 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
192 type = *pnt++;
193 sub_type = *pnt++;
194 if (!(type == ECOMMUNITY_ENCODE_EVPN
195 && sub_type == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY))
196 continue;
197 flags = *pnt++;
198
199 if (flags & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY)
200 *sticky = 1;
201 else
202 *sticky = 0;
203
204 pnt++;
937652c6
DL
205 pnt = ptr_get_be32(pnt, &seq_num);
206 (void)pnt; /* consume value */
d62a17ae 207 return seq_num;
208 }
209
210 return 0;
212f5cbc 211}
3da6fcd5 212
68e33151
CS
213/*
214 * return true if attr contains router flag extended community
215 */
216void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag)
217{
218 struct ecommunity *ecom;
219 int i;
220 uint8_t val;
221
222 ecom = attr->ecommunity;
223 if (!ecom || !ecom->size)
224 return;
225
226 /* If there is a evpn na extendd community set router_flag */
227 for (i = 0; i < ecom->size; i++) {
228 uint8_t *pnt;
229 uint8_t type, sub_type;
230
231 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
232 type = *pnt++;
233 sub_type = *pnt++;
234
235 if (type == ECOMMUNITY_ENCODE_EVPN &&
236 sub_type == ECOMMUNITY_EVPN_SUBTYPE_ND) {
237 val = *pnt++;
238 if (val & ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG) {
239 *router_flag = 1;
240 break;
241 }
242 }
243 }
244}
245
3da6fcd5 246/* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
d62a17ae 247extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
248 struct prefix *dst)
3da6fcd5 249{
d62a17ae 250 struct evpn_addr *p_evpn_p;
251 struct prefix p2;
252 struct prefix *src = &p2;
253
254 if (!dst || dst->family == 0)
255 return -1;
256 /* store initial prefix in src */
257 prefix_copy(src, dst);
258 memset(dst, 0, sizeof(struct prefix));
259 p_evpn_p = &(dst->u.prefix_evpn);
b03b8898 260 dst->family = AF_EVPN;
d62a17ae 261 p_evpn_p->route_type = evpn_type;
262 if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) {
3714a385 263 p_evpn_p->prefix_addr.eth_tag = eth_tag;
264 p_evpn_p->prefix_addr.ip_prefix_length = p2.prefixlen;
d62a17ae 265 if (src->family == AF_INET) {
3714a385 266 SET_IPADDR_V4(&p_evpn_p->prefix_addr.ip);
267 memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v4,
268 &src->u.prefix4,
d62a17ae 269 sizeof(struct in_addr));
d7c0a89a 270 dst->prefixlen = (uint8_t)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
d62a17ae 271 } else {
3714a385 272 SET_IPADDR_V6(&p_evpn_p->prefix_addr.ip);
273 memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v6,
274 &src->u.prefix6,
d62a17ae 275 sizeof(struct in6_addr));
d7c0a89a 276 dst->prefixlen = (uint8_t)PREFIX_LEN_ROUTE_TYPE_5_IPV6;
d62a17ae 277 }
278 } else
279 return -1;
280 return 0;
3da6fcd5 281}