]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_attr_evpn.c
Merge pull request #1630 from LabNConsulting/working/master/pr1629-no-json
[mirror_frr.git] / bgpd / bgp_attr_evpn.c
1 /* Ethernet-VPN Attribute handling file
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 */
20
21 #include <zebra.h>
22
23 #include "command.h"
24 #include "filter.h"
25 #include "prefix.h"
26 #include "log.h"
27 #include "memory.h"
28 #include "stream.h"
29
30 #include "bgpd/bgpd.h"
31 #include "bgpd/bgp_attr.h"
32 #include "bgpd/bgp_route.h"
33 #include "bgpd/bgp_attr_evpn.h"
34 #include "bgpd/bgp_ecommunity.h"
35 #include "bgpd/bgp_evpn.h"
36 #include "bgpd/bgp_evpn_private.h"
37
38 void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac)
39 {
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;
45 memcpy(&routermac_ecom.val[2], routermac->octet, ETH_ALEN);
46 if (!attr->ecommunity)
47 attr->ecommunity = ecommunity_new();
48 ecommunity_add_val(attr->ecommunity, &routermac_ecom);
49 ecommunity_str(attr->ecommunity);
50 }
51
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 */
57 int str2esi(const char *str, struct eth_segment_id *id)
58 {
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;
76 }
77
78 char *esi2str(struct eth_segment_id *id)
79 {
80 char *ptr;
81 u_char *val;
82
83 if (!id)
84 return NULL;
85
86 val = id->val;
87 ptr = (char *)XMALLOC(MTYPE_TMP,
88 (ESI_LEN * 2 + ESI_LEN - 1 + 1) * sizeof(char));
89
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]);
94
95 return ptr;
96 }
97
98 char *ecom_mac2str(char *ecom_mac)
99 {
100 char *en;
101
102 en = ecom_mac;
103 en += 2;
104
105 return prefix_mac2str((struct ethaddr *)en, NULL, 0);
106 }
107
108 /* Fetch router-mac from extended community */
109 void bgp_attr_rmac(struct attr *attr,
110 struct ethaddr *rmac)
111 {
112 int i = 0;
113 struct ecommunity *ecom;
114
115 ecom = attr->ecommunity;
116 if (!ecom || !ecom->size)
117 return;
118
119 /* If there is a router mac extended community, set RMAC in attr */
120 for (i = 0; i < ecom->size; i++) {
121 u_char *pnt = NULL;
122 u_char type = 0;
123 u_char sub_type = 0;
124
125 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
126 type = *pnt++;
127 sub_type = *pnt++;
128
129 if (!(type == ECOMMUNITY_ENCODE_EVPN &&
130 sub_type == ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC))
131 continue;
132
133 memcpy(rmac, pnt, ETH_ALEN);
134 }
135 }
136
137 /*
138 * Fetch and return the sequence number from MAC Mobility extended
139 * community, if present, else 0.
140 */
141 u_int32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, u_char *sticky)
142 {
143 struct ecommunity *ecom;
144 int i;
145 u_char flags = 0;
146
147 ecom = attr->ecommunity;
148 if (!ecom || !ecom->size)
149 return 0;
150
151 /* If there is a MAC Mobility extended community, return its
152 * sequence number.
153 * TODO: RFC is silent on handling of multiple MAC mobility extended
154 * communities for the same route. We will bail out upon the first
155 * one.
156 */
157 for (i = 0; i < ecom->size; i++) {
158 u_char *pnt;
159 u_char type, sub_type;
160 u_int32_t seq_num;
161
162 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
163 type = *pnt++;
164 sub_type = *pnt++;
165 if (!(type == ECOMMUNITY_ENCODE_EVPN
166 && sub_type == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY))
167 continue;
168 flags = *pnt++;
169
170 if (flags & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY)
171 *sticky = 1;
172 else
173 *sticky = 0;
174
175 pnt++;
176 pnt = ptr_get_be32(pnt, &seq_num);
177 (void)pnt; /* consume value */
178 return seq_num;
179 }
180
181 return 0;
182 }
183
184 /* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
185 extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
186 struct prefix *dst)
187 {
188 struct evpn_addr *p_evpn_p;
189 struct prefix p2;
190 struct prefix *src = &p2;
191
192 if (!dst || dst->family == 0)
193 return -1;
194 /* store initial prefix in src */
195 prefix_copy(src, dst);
196 memset(dst, 0, sizeof(struct prefix));
197 p_evpn_p = &(dst->u.prefix_evpn);
198 dst->family = AF_EVPN;
199 p_evpn_p->route_type = evpn_type;
200 if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) {
201 p_evpn_p->eth_tag = eth_tag;
202 p_evpn_p->ip_prefix_length = p2.prefixlen;
203 if (src->family == AF_INET) {
204 SET_IPADDR_V4(&p_evpn_p->ip);
205 memcpy(&p_evpn_p->ip.ipaddr_v4, &src->u.prefix4,
206 sizeof(struct in_addr));
207 dst->prefixlen = (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
208 } else {
209 SET_IPADDR_V6(&p_evpn_p->ip);
210 memcpy(&p_evpn_p->ip.ipaddr_v6, &src->u.prefix6,
211 sizeof(struct in6_addr));
212 dst->prefixlen = (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV6;
213 }
214 } else
215 return -1;
216 return 0;
217 }